xref: /xnu-11215.81.4/tests/vfs/o_search.c (revision d4514f0bc1d3f944c22d92e68b646ac3fb40d452)
1 /* compile: xcrun -sdk macosx.internal clang -ldarwintest -o o_search o_search.c -g -Weverything */
2 
3 #include <darwintest.h>
4 #include <darwintest_utils.h>
5 #include <darwintest_multiprocess.h>
6 #include <errno.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/attr.h>
11 #include <sys/event.h>
12 #include <sys/resource.h>
13 #include <dirent.h>
14 
15 #ifndef O_EXEC
16 #define O_EXEC 0x40000000
17 #define O_SEARCH (O_EXEC | O_DIRECTORY)
18 #endif
19 
20 T_GLOBAL_META(
21 	T_META_NAMESPACE("xnu.vfs"),
22 	T_META_RADAR_COMPONENT_NAME("xnu"),
23 	T_META_RADAR_COMPONENT_VERSION("vfs"),
24 	T_META_ASROOT(false),
25 	T_META_CHECK_LEAKS(false));
26 
27 #define TEST_FILE "testfile"
28 #define NUMDIRS 5
29 
30 static char g_testfile[MAXPATHLEN];
31 
32 extern ssize_t __getdirentries64(int, void *, size_t, off_t *);
33 
34 static void
exit_cleanup(void)35 exit_cleanup(void)
36 {
37 	(void)unlink(g_testfile);
38 }
39 
40 T_DECL(o_search,
41     "test O_SEARCH for open",
42     T_META_ASROOT(false))
43 {
44 	const char *tmpdir = dt_tmpdir();
45 	void *mapped = MAP_FAILED;
46 	off_t dirbyte = 0;
47 	int retval = 0;
48 	int fd = -1;
49 	int tmpdir_fd = -1;
50 	char namebuf[(sizeof(struct dirent) * (NUMDIRS + 2))];
51 	char attrbuf[256];
52 
53 	T_SETUPBEGIN;
54 
55 	atexit(exit_cleanup);
56 
57 	T_ASSERT_POSIX_ZERO(chdir(tmpdir),
58 	    "Setup: changing to tmpdir: %s", tmpdir);
59 
60 	snprintf(g_testfile, MAXPATHLEN, "%s/%s", tmpdir, TEST_FILE);
61 
62 	T_ASSERT_POSIX_SUCCESS(fd = open(g_testfile, O_CREAT | O_RDWR, 0644), NULL);
63 	T_ASSERT_POSIX_SUCCESS(retval = (int)write(fd, g_testfile, sizeof(g_testfile)), "Write: %s", g_testfile);
64 	T_ASSERT_POSIX_SUCCESS(close(fd), "Close test file: %s", g_testfile);
65 
66 	T_SETUPEND;
67 
68 	T_WITH_ERRNO;
69 	tmpdir_fd = open(tmpdir, O_EXEC);
70 	T_ASSERT_TRUE((tmpdir_fd == -1) && (errno == EISDIR),
71 	    "Trying to open directory O_EXEC: %s, tmpdir_fd = %d, errno = %d", g_testfile, tmpdir_fd, errno);
72 
73 	T_ASSERT_POSIX_SUCCESS(tmpdir_fd = open(tmpdir, O_RDONLY), NULL);
74 	T_ASSERT_POSIX_SUCCESS(retval = (int)__getdirentries64(tmpdir_fd, namebuf, sizeof(namebuf), &dirbyte), NULL);
75 	T_ASSERT_POSIX_SUCCESS(close(tmpdir_fd), NULL);
76 
77 	T_ASSERT_POSIX_SUCCESS(tmpdir_fd = open(tmpdir, O_SEARCH), NULL);
78 	retval = (int)__getdirentries64(tmpdir_fd, namebuf, sizeof(namebuf), &dirbyte);
79 	T_ASSERT_TRUE((retval == -1) && (errno == EBADF),
80 	    "Trying to read directory opened with O_SEARCH: %s, retval = %d, errno = %d",
81 	    tmpdir, retval, errno);
82 
83 	fd = openat(tmpdir_fd, TEST_FILE, O_EXEC);
84 	T_ASSERT_TRUE((fd == -1) && (errno == EACCES),
85 	    "Trying to open file for execute with perms 644: %s, retval = %d, errno = %d",
86 	    tmpdir, retval, errno);
87 
88 	T_ASSERT_POSIX_SUCCESS(retval = fchmodat(tmpdir_fd, TEST_FILE, 0744, 0), NULL);
89 
90 	fd = openat(tmpdir_fd, TEST_FILE, O_SEARCH);
91 	T_ASSERT_TRUE((fd == -1) && (errno == ENOTDIR),
92 	    "Trying to open file for execute with perms 644: %s, retval = %d, errno = %d",
93 	    tmpdir, retval, errno);
94 
95 	T_ASSERT_POSIX_SUCCESS(fd = openat(tmpdir_fd, TEST_FILE, O_EXEC), NULL);
96 
97 	retval = (int)read(fd, &attrbuf, 2);
98 	T_ASSERT_TRUE((retval == -1) && (errno == EBADF),
99 	    "Trying to read file opened with O_EXEC: %s, retval = %d, errno = %d",
100 	    g_testfile, retval, errno);
101 
102 	retval = (int)write(fd, &attrbuf, 2);
103 	T_ASSERT_TRUE((retval == -1) && (errno == EBADF),
104 	    "Trying to write file opened with O_EXEC: %s, retval = %d, errno = %d",
105 	    g_testfile, retval, errno);
106 
107 	mapped = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED,
108 	    fd, 0);
109 	T_ASSERT_TRUE((mapped == MAP_FAILED) && (errno == EACCES),
110 	    "Trying to mmap file for read opened with O_EXEC: %s, mapped = %ld, errno = %d",
111 	    g_testfile, (long)mapped, errno);
112 
113 	mapped = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED,
114 	    fd, 0);
115 	T_ASSERT_TRUE((mapped == MAP_FAILED) && (errno == EACCES),
116 	    "Trying to mmap file for write opened with O_EXEC: %s, mapped = %ld, errno = %d",
117 	    g_testfile, (long)mapped, errno);
118 
119 	T_ASSERT_POSIX_SUCCESS(close(fd), NULL);
120 	T_ASSERT_POSIX_SUCCESS(close(tmpdir_fd), NULL);
121 }
122