xref: /xnu-10063.121.3/tests/iopolicy.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1*2c2f96dcSApple OSS Distributions /* compile: xcrun -sdk macosx.internal clang -ldarwintest -o iopolicy iopolicy.c -g -Weverything */
2*2c2f96dcSApple OSS Distributions 
3*2c2f96dcSApple OSS Distributions #include <darwintest.h>
4*2c2f96dcSApple OSS Distributions #include <darwintest_utils.h>
5*2c2f96dcSApple OSS Distributions #include <darwintest_multiprocess.h>
6*2c2f96dcSApple OSS Distributions #include <errno.h>
7*2c2f96dcSApple OSS Distributions #include <stdint.h>
8*2c2f96dcSApple OSS Distributions #include <stdlib.h>
9*2c2f96dcSApple OSS Distributions #include <unistd.h>
10*2c2f96dcSApple OSS Distributions #include <sys/attr.h>
11*2c2f96dcSApple OSS Distributions #include <sys/event.h>
12*2c2f96dcSApple OSS Distributions #include <sys/resource.h>
13*2c2f96dcSApple OSS Distributions 
14*2c2f96dcSApple OSS Distributions #ifndef IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY
15*2c2f96dcSApple OSS Distributions #define IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY 10
16*2c2f96dcSApple OSS Distributions #endif
17*2c2f96dcSApple OSS Distributions 
18*2c2f96dcSApple OSS Distributions #ifndef IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_OFF
19*2c2f96dcSApple OSS Distributions #define IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_OFF 0
20*2c2f96dcSApple OSS Distributions #endif
21*2c2f96dcSApple OSS Distributions 
22*2c2f96dcSApple OSS Distributions #ifndef IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_ON
23*2c2f96dcSApple OSS Distributions #define IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_ON 1
24*2c2f96dcSApple OSS Distributions #endif
25*2c2f96dcSApple OSS Distributions 
26*2c2f96dcSApple OSS Distributions T_GLOBAL_META(
27*2c2f96dcSApple OSS Distributions 	T_META_NAMESPACE("xnu.vfs.iopolicy"),
28*2c2f96dcSApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
29*2c2f96dcSApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("vfs"),
30*2c2f96dcSApple OSS Distributions 	T_META_CHECK_LEAKS(false));
31*2c2f96dcSApple OSS Distributions 
32*2c2f96dcSApple OSS Distributions #define TEST_FILE "testfile"
33*2c2f96dcSApple OSS Distributions 
34*2c2f96dcSApple OSS Distributions static char g_testfile[MAXPATHLEN];
35*2c2f96dcSApple OSS Distributions static char g_testdata[1024];
36*2c2f96dcSApple OSS Distributions 
37*2c2f96dcSApple OSS Distributions static void
exit_cleanup(void)38*2c2f96dcSApple OSS Distributions exit_cleanup(void)
39*2c2f96dcSApple OSS Distributions {
40*2c2f96dcSApple OSS Distributions 	(void)remove(g_testfile);
41*2c2f96dcSApple OSS Distributions }
42*2c2f96dcSApple OSS Distributions 
43*2c2f96dcSApple OSS Distributions T_DECL(iopol_type_vfs_disallow_rw_for_o_evtonly,
44*2c2f96dcSApple OSS Distributions     "test IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY policy")
45*2c2f96dcSApple OSS Distributions {
46*2c2f96dcSApple OSS Distributions 	char attrbuf[256];
47*2c2f96dcSApple OSS Distributions 	struct attrlist attrlist;
48*2c2f96dcSApple OSS Distributions 	struct kevent vnode_kevent;
49*2c2f96dcSApple OSS Distributions 	struct timespec kevent_timeout;
50*2c2f96dcSApple OSS Distributions 	const char *tmpdir = dt_tmpdir();
51*2c2f96dcSApple OSS Distributions 	void *mapped;
52*2c2f96dcSApple OSS Distributions 	int err, fd, kq;
53*2c2f96dcSApple OSS Distributions 
54*2c2f96dcSApple OSS Distributions 	T_SETUPBEGIN;
55*2c2f96dcSApple OSS Distributions 
56*2c2f96dcSApple OSS Distributions 	atexit(exit_cleanup);
57*2c2f96dcSApple OSS Distributions 
58*2c2f96dcSApple OSS Distributions 	T_ASSERT_POSIX_ZERO(chdir(tmpdir),
59*2c2f96dcSApple OSS Distributions 	    "Setup: changing to tmpdir: %s", tmpdir);
60*2c2f96dcSApple OSS Distributions 
61*2c2f96dcSApple OSS Distributions 	snprintf(g_testfile, MAXPATHLEN, "%s/%s", tmpdir, TEST_FILE);
62*2c2f96dcSApple OSS Distributions 
63*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
64*2c2f96dcSApple OSS Distributions 	fd = open(g_testfile, O_CREAT | O_RDWR, 0666);
65*2c2f96dcSApple OSS Distributions 	T_ASSERT_NE(fd, -1, "Create test file: %s", g_testfile);
66*2c2f96dcSApple OSS Distributions 
67*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
68*2c2f96dcSApple OSS Distributions 	err = (int)write(fd, g_testfile, sizeof(g_testfile));
69*2c2f96dcSApple OSS Distributions 	T_ASSERT_NE(err, -1, "Write: %s", g_testfile);
70*2c2f96dcSApple OSS Distributions 
71*2c2f96dcSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", g_testfile);
72*2c2f96dcSApple OSS Distributions 
73*2c2f96dcSApple OSS Distributions 	kq = kqueue();
74*2c2f96dcSApple OSS Distributions 	T_ASSERT_NE(kq, -1, "Create kqueue");
75*2c2f96dcSApple OSS Distributions 
76*2c2f96dcSApple OSS Distributions 	T_SETUPEND;
77*2c2f96dcSApple OSS Distributions 
78*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
79*2c2f96dcSApple OSS Distributions 	err = setiopolicy_np(IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY,
80*2c2f96dcSApple OSS Distributions 	    IOPOL_SCOPE_THREAD, IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_ON);
81*2c2f96dcSApple OSS Distributions 	T_ASSERT_TRUE((err == -1) && (errno == EINVAL),
82*2c2f96dcSApple OSS Distributions 	    "setiopolicy_np(IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY, IOPOL_SCOPE_THREAD, 1)");
83*2c2f96dcSApple OSS Distributions 
84*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
85*2c2f96dcSApple OSS Distributions 	err = setiopolicy_np(IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY,
86*2c2f96dcSApple OSS Distributions 	    IOPOL_SCOPE_PROCESS, IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_ON);
87*2c2f96dcSApple OSS Distributions 	T_ASSERT_NE(err, -1,
88*2c2f96dcSApple OSS Distributions 	    "setiopolicy_np(IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY, IOPOL_SCOPE_PROCESS, 1)");
89*2c2f96dcSApple OSS Distributions 
90*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
91*2c2f96dcSApple OSS Distributions 	err = getiopolicy_np(IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY,
92*2c2f96dcSApple OSS Distributions 	    IOPOL_SCOPE_PROCESS);
93*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(err, IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_ON,
94*2c2f96dcSApple OSS Distributions 	    "getiopolicy_np(IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY, IOPOL_SCOPE_PROCESS)");
95*2c2f96dcSApple OSS Distributions 
96*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
97*2c2f96dcSApple OSS Distributions 	err = setiopolicy_np(IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY,
98*2c2f96dcSApple OSS Distributions 	    IOPOL_SCOPE_PROCESS, IOPOL_VFS_DISALLOW_RW_FOR_O_EVTONLY_OFF);
99*2c2f96dcSApple OSS Distributions 	T_ASSERT_TRUE((err == -1) && (errno == EINVAL),
100*2c2f96dcSApple OSS Distributions 	    "setiopolicy_np(IOPOL_TYPE_VFS_DISALLOW_RW_FOR_O_EVTONLY, IOPOL_SCOPE_PROCESS, 0)");
101*2c2f96dcSApple OSS Distributions 
102*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
103*2c2f96dcSApple OSS Distributions 	fd = open(g_testfile, O_RDWR | O_EVTONLY, 0666);
104*2c2f96dcSApple OSS Distributions 	T_ASSERT_NE(fd, -1, "Open test fi1e in 'O_RDW|O_EVTONLY': %s", g_testfile);
105*2c2f96dcSApple OSS Distributions 
106*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
107*2c2f96dcSApple OSS Distributions 	err = (int)write(fd, g_testdata, sizeof(g_testdata));
108*2c2f96dcSApple OSS Distributions 	T_ASSERT_TRUE((err == -1) && (errno == EBADF),
109*2c2f96dcSApple OSS Distributions 	    "Trying to write: %s", g_testfile);
110*2c2f96dcSApple OSS Distributions 
111*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
112*2c2f96dcSApple OSS Distributions 	err = (int)read(fd, g_testdata, sizeof(g_testdata));
113*2c2f96dcSApple OSS Distributions 	T_ASSERT_TRUE((err == -1) && (errno == EBADF),
114*2c2f96dcSApple OSS Distributions 	    "Trying to read: %s", g_testfile);
115*2c2f96dcSApple OSS Distributions 
116*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
117*2c2f96dcSApple OSS Distributions 	mapped = mmap(NULL, sizeof(g_testdata), PROT_READ | PROT_WRITE, MAP_SHARED,
118*2c2f96dcSApple OSS Distributions 	    fd, 0);
119*2c2f96dcSApple OSS Distributions 	T_ASSERT_TRUE((err == -1) && (errno == EACCES),
120*2c2f96dcSApple OSS Distributions 	    "Trying to mmaped read/write: %s", g_testfile);
121*2c2f96dcSApple OSS Distributions 
122*2c2f96dcSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", g_testfile);
123*2c2f96dcSApple OSS Distributions 
124*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
125*2c2f96dcSApple OSS Distributions 	fd = open(g_testfile, O_EVTONLY, 0666);
126*2c2f96dcSApple OSS Distributions 	T_ASSERT_NE(fd, -1, "Open test fi1e in 'O_EVTONLY': %s", g_testfile);
127*2c2f96dcSApple OSS Distributions 
128*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
129*2c2f96dcSApple OSS Distributions 	err = (int)read(fd, g_testdata, sizeof(g_testdata));
130*2c2f96dcSApple OSS Distributions 	T_ASSERT_TRUE((err == -1) && (errno == EBADF),
131*2c2f96dcSApple OSS Distributions 	    "Trying to read: %s", g_testfile);
132*2c2f96dcSApple OSS Distributions 
133*2c2f96dcSApple OSS Distributions 	T_WITH_ERRNO;
134*2c2f96dcSApple OSS Distributions 	memset(&attrlist, 0, sizeof(attrlist));
135*2c2f96dcSApple OSS Distributions 	attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
136*2c2f96dcSApple OSS Distributions 	attrlist.commonattr = (ATTR_CMN_OBJTYPE | ATTR_CMN_OBJID | ATTR_CMN_MODTIME);
137*2c2f96dcSApple OSS Distributions 
138*2c2f96dcSApple OSS Distributions 	err = fgetattrlist(fd, &attrlist, &attrbuf, sizeof(attrbuf), 0);
139*2c2f96dcSApple OSS Distributions 	T_ASSERT_NE(err, -1, "Perform getattrlist: %s", g_testfile);
140*2c2f96dcSApple OSS Distributions 
141*2c2f96dcSApple OSS Distributions 	kevent_timeout.tv_sec = kevent_timeout.tv_nsec = 0;
142*2c2f96dcSApple OSS Distributions 	EV_SET(&vnode_kevent, fd, EVFILT_VNODE, (EV_ADD | EV_ENABLE | EV_CLEAR),
143*2c2f96dcSApple OSS Distributions 	    NOTE_WRITE, 0, (void *)g_testfile);
144*2c2f96dcSApple OSS Distributions 	err = kevent(kq, &vnode_kevent, 1, NULL, 0, &kevent_timeout);
145*2c2f96dcSApple OSS Distributions 	T_ASSERT_GE(err, 0, "Register vnode event on kq: %d", kq);
146*2c2f96dcSApple OSS Distributions 
147*2c2f96dcSApple OSS Distributions 	kevent_timeout.tv_sec = 2;
148*2c2f96dcSApple OSS Distributions 	kevent_timeout.tv_nsec = 0;
149*2c2f96dcSApple OSS Distributions 	EV_SET(&vnode_kevent, fd, EVFILT_VNODE, EV_CLEAR, 0, 0, 0);
150*2c2f96dcSApple OSS Distributions 
151*2c2f96dcSApple OSS Distributions 	err = kevent(kq, NULL, 0, &vnode_kevent, 1, &kevent_timeout);
152*2c2f96dcSApple OSS Distributions 	T_ASSERT_NE(err, -1, "Listen for vnode event on kq: %d", kq);
153*2c2f96dcSApple OSS Distributions 
154*2c2f96dcSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", g_testfile);
155*2c2f96dcSApple OSS Distributions }
156