1*d4514f0bSApple OSS Distributions #ifdef T_NAMESPACE
2*d4514f0bSApple OSS Distributions #undef T_NAMESPACE
3*d4514f0bSApple OSS Distributions #endif
4*d4514f0bSApple OSS Distributions #include <darwintest.h>
5*d4514f0bSApple OSS Distributions
6*d4514f0bSApple OSS Distributions #include <dispatch/dispatch.h>
7*d4514f0bSApple OSS Distributions #include <fcntl.h>
8*d4514f0bSApple OSS Distributions #include <mach/mach.h>
9*d4514f0bSApple OSS Distributions #include <poll.h>
10*d4514f0bSApple OSS Distributions #include <stdint.h>
11*d4514f0bSApple OSS Distributions #include <unistd.h>
12*d4514f0bSApple OSS Distributions
13*d4514f0bSApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.poll"),
14*d4514f0bSApple OSS Distributions T_META_RUN_CONCURRENTLY(true));
15*d4514f0bSApple OSS Distributions
16*d4514f0bSApple OSS Distributions #define SLEEP_TIME_SECS 1
17*d4514f0bSApple OSS Distributions #define POLL_TIMEOUT_MS 1800
18*d4514f0bSApple OSS Distributions static_assert(POLL_TIMEOUT_MS > (SLEEP_TIME_SECS * 1000),
19*d4514f0bSApple OSS Distributions "poll timeout should be longer than sleep time");
20*d4514f0bSApple OSS Distributions
21*d4514f0bSApple OSS Distributions /*
22*d4514f0bSApple OSS Distributions * This matches the behavior of other UNIXes, but is under-specified in POSIX.
23*d4514f0bSApple OSS Distributions *
24*d4514f0bSApple OSS Distributions * See <rdar://problem/28372390>.
25*d4514f0bSApple OSS Distributions */
26*d4514f0bSApple OSS Distributions T_DECL(sleep_with_no_fds,
27*d4514f0bSApple OSS Distributions "poll() called with no fds provided should act like sleep", T_META_TAG_VM_PREFERRED)
28*d4514f0bSApple OSS Distributions {
29*d4514f0bSApple OSS Distributions uint64_t begin_time, sleep_time, poll_time;
30*d4514f0bSApple OSS Distributions struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 };
31*d4514f0bSApple OSS Distributions
32*d4514f0bSApple OSS Distributions begin_time = mach_absolute_time();
33*d4514f0bSApple OSS Distributions sleep(SLEEP_TIME_SECS);
34*d4514f0bSApple OSS Distributions sleep_time = mach_absolute_time() - begin_time;
35*d4514f0bSApple OSS Distributions T_LOG("sleep(%d) ~= %llu mach absolute time units", SLEEP_TIME_SECS, sleep_time);
36*d4514f0bSApple OSS Distributions
37*d4514f0bSApple OSS Distributions begin_time = mach_absolute_time();
38*d4514f0bSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(poll(&pfd, 0, POLL_TIMEOUT_MS),
39*d4514f0bSApple OSS Distributions "poll() with 0 events and timeout %d ms", POLL_TIMEOUT_MS);
40*d4514f0bSApple OSS Distributions poll_time = mach_absolute_time() - begin_time;
41*d4514f0bSApple OSS Distributions
42*d4514f0bSApple OSS Distributions T_EXPECT_GT(poll_time, sleep_time,
43*d4514f0bSApple OSS Distributions "poll(... %d) should wait longer than sleep(1)", POLL_TIMEOUT_MS);
44*d4514f0bSApple OSS Distributions }
45*d4514f0bSApple OSS Distributions
46*d4514f0bSApple OSS Distributions #define LAUNCHD_PATH "/sbin/launchd"
47*d4514f0bSApple OSS Distributions #define PIPE_DIR_TIMEOUT_SECS 1
48*d4514f0bSApple OSS Distributions
49*d4514f0bSApple OSS Distributions /*
50*d4514f0bSApple OSS Distributions * See <rdar://problem/28539155>.
51*d4514f0bSApple OSS Distributions */
52*d4514f0bSApple OSS Distributions T_DECL(directories,
53*d4514f0bSApple OSS Distributions "poll() with directories should return an error", T_META_TAG_VM_PREFERRED)
54*d4514f0bSApple OSS Distributions {
55*d4514f0bSApple OSS Distributions int file, dir, pipes[2];
56*d4514f0bSApple OSS Distributions struct pollfd pfd[] = {
57*d4514f0bSApple OSS Distributions { .events = POLLIN },
58*d4514f0bSApple OSS Distributions { .events = POLLIN },
59*d4514f0bSApple OSS Distributions { .events = POLLIN },
60*d4514f0bSApple OSS Distributions };
61*d4514f0bSApple OSS Distributions
62*d4514f0bSApple OSS Distributions file = open(LAUNCHD_PATH, O_RDONLY | O_NONBLOCK);
63*d4514f0bSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(file, "open(%s)", LAUNCHD_PATH);
64*d4514f0bSApple OSS Distributions dir = open(".", O_RDONLY | O_NONBLOCK);
65*d4514f0bSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(dir, "open(\".\")");
66*d4514f0bSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(pipe(pipes), NULL);
67*d4514f0bSApple OSS Distributions
68*d4514f0bSApple OSS Distributions /* just directory */
69*d4514f0bSApple OSS Distributions pfd[0].fd = dir;
70*d4514f0bSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 1, -1), "poll() with a directory");
71*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
72*d4514f0bSApple OSS Distributions "directory should be an invalid event");
73*d4514f0bSApple OSS Distributions
74*d4514f0bSApple OSS Distributions /* file and directory */
75*d4514f0bSApple OSS Distributions pfd[0].fd = file; pfd[0].revents = 0;
76*d4514f0bSApple OSS Distributions pfd[1].fd = dir; pfd[1].revents = 0;
77*d4514f0bSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
78*d4514f0bSApple OSS Distributions "poll() with a file and directory");
79*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
80*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLNVAL,
81*d4514f0bSApple OSS Distributions "directory should be an invalid event");
82*d4514f0bSApple OSS Distributions
83*d4514f0bSApple OSS Distributions /* directory and file */
84*d4514f0bSApple OSS Distributions pfd[0].fd = dir; pfd[0].revents = 0;
85*d4514f0bSApple OSS Distributions pfd[1].fd = file; pfd[1].revents = 0;
86*d4514f0bSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
87*d4514f0bSApple OSS Distributions "poll() with a directory and a file");
88*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
89*d4514f0bSApple OSS Distributions "directory should be an invalid event");
90*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLIN, "file should be readable");
91*d4514f0bSApple OSS Distributions
92*d4514f0bSApple OSS Distributions /* file and pipe */
93*d4514f0bSApple OSS Distributions pfd[0].fd = file; pfd[0].revents = 0;
94*d4514f0bSApple OSS Distributions pfd[1].fd = pipes[0]; pfd[0].revents = 0;
95*d4514f0bSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
96*d4514f0bSApple OSS Distributions "poll() with a file and pipe");
97*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
98*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_FALSE(pfd[1].revents & POLLIN,
99*d4514f0bSApple OSS Distributions "pipe should not be readable");
100*d4514f0bSApple OSS Distributions
101*d4514f0bSApple OSS Distributions /* file, directory, and pipe */
102*d4514f0bSApple OSS Distributions pfd[0].fd = file; pfd[0].revents = 0;
103*d4514f0bSApple OSS Distributions pfd[1].fd = dir; pfd[1].revents = 0;
104*d4514f0bSApple OSS Distributions pfd[2].fd = pipes[0]; pfd[2].revents = 0;
105*d4514f0bSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 3, -1),
106*d4514f0bSApple OSS Distributions "poll() with a file, directory, and pipe");
107*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
108*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLNVAL,
109*d4514f0bSApple OSS Distributions "directory should be an invalid event");
110*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_FALSE(pfd[2].revents & POLLIN, "pipe should not be readable");
111*d4514f0bSApple OSS Distributions
112*d4514f0bSApple OSS Distributions /* directory and pipe */
113*d4514f0bSApple OSS Distributions __block bool timed_out = true;
114*d4514f0bSApple OSS Distributions pfd[0].fd = dir; pfd[0].revents = 0;
115*d4514f0bSApple OSS Distributions pfd[1].fd = pipes[0]; pfd[1].revents = 0;
116*d4514f0bSApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
117*d4514f0bSApple OSS Distributions PIPE_DIR_TIMEOUT_SECS * NSEC_PER_SEC),
118*d4514f0bSApple OSS Distributions dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
119*d4514f0bSApple OSS Distributions T_ASSERT_FALSE(timed_out, "poll timed out after %d seconds",
120*d4514f0bSApple OSS Distributions PIPE_DIR_TIMEOUT_SECS);
121*d4514f0bSApple OSS Distributions });
122*d4514f0bSApple OSS Distributions
123*d4514f0bSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(poll(pfd, 3, -1),
124*d4514f0bSApple OSS Distributions "poll() with a directory and pipe");
125*d4514f0bSApple OSS Distributions timed_out = false;
126*d4514f0bSApple OSS Distributions
127*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
128*d4514f0bSApple OSS Distributions "directory should be an invalid event");
129*d4514f0bSApple OSS Distributions T_QUIET; T_EXPECT_FALSE(pfd[1].revents & POLLIN, "pipe should not be readable");
130*d4514f0bSApple OSS Distributions }
131*d4514f0bSApple OSS Distributions
132*d4514f0bSApple OSS Distributions #define PRIVATE
133*d4514f0bSApple OSS Distributions #include <libproc.h>
134*d4514f0bSApple OSS Distributions
135*d4514f0bSApple OSS Distributions static void *
leak_thread(void * ptr)136*d4514f0bSApple OSS Distributions leak_thread(void *ptr)
137*d4514f0bSApple OSS Distributions {
138*d4514f0bSApple OSS Distributions T_LOG("Trying to find kevent kernel pointer...\n");
139*d4514f0bSApple OSS Distributions
140*d4514f0bSApple OSS Distributions unsigned char *buffer = (unsigned char*) malloc(16392 * 8);
141*d4514f0bSApple OSS Distributions
142*d4514f0bSApple OSS Distributions while (1) {
143*d4514f0bSApple OSS Distributions memset(buffer, 0, 16392 * 8);
144*d4514f0bSApple OSS Distributions
145*d4514f0bSApple OSS Distributions // Dump the kevent udatas for self
146*d4514f0bSApple OSS Distributions int ret = proc_list_uptrs(getpid(), buffer, 16392 * 8);
147*d4514f0bSApple OSS Distributions
148*d4514f0bSApple OSS Distributions if (ret > 0) {
149*d4514f0bSApple OSS Distributions T_LOG("udata pointers returned: %d\n", ret);
150*d4514f0bSApple OSS Distributions uint64_t *ptrs = (uint64_t*) buffer;
151*d4514f0bSApple OSS Distributions for (int i = 0; i < ret; i++) {
152*d4514f0bSApple OSS Distributions T_EXPECT_EQ(ptrs[i] & 0xffffff0000000000, 0, "kptr? -> 0x%llx\n", ptrs[i]);
153*d4514f0bSApple OSS Distributions }
154*d4514f0bSApple OSS Distributions break;
155*d4514f0bSApple OSS Distributions }
156*d4514f0bSApple OSS Distributions }
157*d4514f0bSApple OSS Distributions
158*d4514f0bSApple OSS Distributions free(buffer);
159*d4514f0bSApple OSS Distributions return NULL;
160*d4514f0bSApple OSS Distributions }
161*d4514f0bSApple OSS Distributions
162*d4514f0bSApple OSS Distributions T_DECL(poll_dont_leak_kernel_pointers, "poll and proc_pidinfo should not leak kernel pointers", T_META_TAG_VM_PREFERRED)
163*d4514f0bSApple OSS Distributions {
164*d4514f0bSApple OSS Distributions pthread_t thr;
165*d4514f0bSApple OSS Distributions pthread_create(&thr, NULL, *leak_thread, (void *) NULL);
166*d4514f0bSApple OSS Distributions
167*d4514f0bSApple OSS Distributions struct pollfd fds[2] = {};
168*d4514f0bSApple OSS Distributions fds[0].fd = STDERR_FILENO;
169*d4514f0bSApple OSS Distributions fds[0].events = POLLERR | POLLHUP;
170*d4514f0bSApple OSS Distributions fds[0].revents = POLLERR;
171*d4514f0bSApple OSS Distributions fds[1].fd = STDOUT_FILENO;
172*d4514f0bSApple OSS Distributions fds[1].events = POLLERR | POLLHUP;
173*d4514f0bSApple OSS Distributions fds[1].revents = POLLERR;
174*d4514f0bSApple OSS Distributions
175*d4514f0bSApple OSS Distributions //int poll_nocancel(struct pollfd *fds, u_int nfds, int timeout)
176*d4514f0bSApple OSS Distributions poll(fds, 2, 5000);
177*d4514f0bSApple OSS Distributions
178*d4514f0bSApple OSS Distributions pthread_join(thr, NULL);
179*d4514f0bSApple OSS Distributions }
180