1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2018 Alan Somers
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 #include <sys/socket.h>
30 #include <sys/event.h>
31 #include <sys/select.h>
32 #include <sys/sysctl.h>
33 #include <sys/un.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <poll.h>
39 #include <pthread.h>
40 #include <pthread_np.h>
41
42 #include <atf-c.h>
43
44 static void
do_socketpair(int * sv)45 do_socketpair(int *sv)
46 {
47 int s;
48
49 s = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv);
50 ATF_REQUIRE_EQ(0, s);
51 ATF_REQUIRE(sv[0] >= 0);
52 ATF_REQUIRE(sv[1] >= 0);
53 ATF_REQUIRE(sv[0] != sv[1]);
54 }
55
56 static u_long
getsendspace(void)57 getsendspace(void)
58 {
59 u_long sendspace;
60
61 ATF_REQUIRE_MSG(sysctlbyname("net.local.stream.sendspace", &sendspace,
62 &(size_t){sizeof(u_long)}, NULL, 0) != -1,
63 "sysctl net.local.stream.sendspace failed: %s", strerror(errno));
64
65 return (sendspace);
66 }
67
68 /* getpeereid(3) should work with stream sockets created via socketpair(2) */
69 ATF_TC_WITHOUT_HEAD(getpeereid);
ATF_TC_BODY(getpeereid,tc)70 ATF_TC_BODY(getpeereid, tc)
71 {
72 int sv[2];
73 uid_t real_euid, euid;
74 gid_t real_egid, egid;
75
76 real_euid = geteuid();
77 real_egid = getegid();
78
79 do_socketpair(sv);
80
81 ATF_REQUIRE_EQ(0, getpeereid(sv[0], &euid, &egid));
82 ATF_CHECK_EQ(real_euid, euid);
83 ATF_CHECK_EQ(real_egid, egid);
84
85 ATF_REQUIRE_EQ(0, getpeereid(sv[1], &euid, &egid));
86 ATF_CHECK_EQ(real_euid, euid);
87 ATF_CHECK_EQ(real_egid, egid);
88
89 close(sv[0]);
90 close(sv[1]);
91 }
92
93 /* Sending zero bytes should succeed (once regressed in aba79b0f4a3f). */
94 ATF_TC_WITHOUT_HEAD(send_0);
ATF_TC_BODY(send_0,tc)95 ATF_TC_BODY(send_0, tc)
96 {
97 int sv[2];
98
99 do_socketpair(sv);
100 ATF_REQUIRE(send(sv[0], sv, 0, 0) == 0);
101 close(sv[0]);
102 close(sv[1]);
103 }
104
105 struct check_ctx;
106 typedef void check_func_t(struct check_ctx *);
107 struct check_ctx {
108 check_func_t *method;
109 int sv[2];
110 bool timeout;
111 union {
112 enum { SELECT_RD, SELECT_WR } select_what;
113 short poll_events;
114 short kev_filter;
115 };
116 int nfds;
117 union {
118 short poll_revents;
119 unsigned short kev_flags;
120 };
121 };
122
123 static void
check_select(struct check_ctx * ctx)124 check_select(struct check_ctx *ctx)
125 {
126 fd_set fds;
127 int nfds;
128
129 FD_ZERO(&fds);
130 FD_SET(ctx->sv[0], &fds);
131 nfds = select(ctx->sv[0] + 1,
132 ctx->select_what == SELECT_RD ? &fds : NULL,
133 ctx->select_what == SELECT_WR ? &fds : NULL,
134 NULL,
135 ctx->timeout ? &(struct timeval){.tv_usec = 1000} : NULL);
136 ATF_REQUIRE_MSG(nfds == ctx->nfds,
137 "select() returns %d errno %d", nfds, errno);
138 }
139
140 static void
check_poll(struct check_ctx * ctx)141 check_poll(struct check_ctx *ctx)
142 {
143 struct pollfd pfd[1];
144 int nfds;
145
146 pfd[0] = (struct pollfd){
147 .fd = ctx->sv[0],
148 .events = ctx->poll_events,
149 };
150 nfds = poll(pfd, 1, ctx->timeout ? 1 : INFTIM);
151 ATF_REQUIRE_MSG(nfds == ctx->nfds,
152 "poll() returns %d errno %d", nfds, errno);
153 ATF_REQUIRE((pfd[0].revents & ctx->poll_revents) == ctx->poll_revents);
154 }
155
156 static void
check_kevent(struct check_ctx * ctx)157 check_kevent(struct check_ctx *ctx)
158 {
159 struct kevent kev;
160 int nfds, kq;
161
162 ATF_REQUIRE(kq = kqueue());
163 EV_SET(&kev, ctx->sv[0], ctx->kev_filter, EV_ADD, 0, 0, NULL);
164 nfds = kevent(kq, &kev, 1, NULL, 0, NULL);
165 ATF_REQUIRE_MSG(nfds == 0,
166 "kevent() returns %d errno %d", nfds, errno);
167 nfds = kevent(kq, NULL, 0, &kev, 1, ctx->timeout ?
168 &(struct timespec){.tv_nsec = 1000000} : NULL);
169 ATF_REQUIRE_MSG(nfds == ctx->nfds,
170 "kevent() returns %d errno %d", nfds, errno);
171 ATF_REQUIRE(kev.ident == (uintptr_t)ctx->sv[0] &&
172 kev.filter == ctx->kev_filter &&
173 (kev.flags & ctx->kev_flags) == ctx->kev_flags);
174 close(kq);
175 }
176
177 static void
full_socketpair(int * sv)178 full_socketpair(int *sv)
179 {
180 void *buf;
181 u_long sendspace;
182
183 sendspace = getsendspace();
184 ATF_REQUIRE((buf = malloc(sendspace)) != NULL);
185 do_socketpair(sv);
186 ATF_REQUIRE(fcntl(sv[0], F_SETFL, O_NONBLOCK) != -1);
187 do {} while (send(sv[0], buf, sendspace, 0) == (ssize_t)sendspace);
188 ATF_REQUIRE(errno == EAGAIN);
189 ATF_REQUIRE(fcntl(sv[0], F_SETFL, 0) != -1);
190 free(buf);
191 }
192
193 static void *
pthread_wrap(void * arg)194 pthread_wrap(void *arg)
195 {
196 struct check_ctx *ctx = arg;
197
198 ctx->method(ctx);
199
200 return (NULL);
201 }
202
203 /*
204 * Launch a thread that would block in event mech and return it.
205 */
206 static pthread_t
pthread_create_blocked(struct check_ctx * ctx)207 pthread_create_blocked(struct check_ctx *ctx)
208 {
209 pthread_t thr;
210
211 ctx->timeout = false;
212 ctx->nfds = 1;
213 ATF_REQUIRE(pthread_create(&thr, NULL, pthread_wrap, ctx) == 0);
214
215 /* Sleep a bit to make sure that thread is put to sleep. */
216 usleep(10000);
217 ATF_REQUIRE(pthread_peekjoin_np(thr, NULL) == EBUSY);
218
219 return (thr);
220 }
221
222 static void
full_writability_check(struct check_ctx * ctx)223 full_writability_check(struct check_ctx *ctx)
224 {
225 pthread_t thr;
226 void *buf;
227 u_long space;
228
229 space = getsendspace() / 2;
230 ATF_REQUIRE((buf = malloc(space)) != NULL);
231
232 /* First check with timeout, expecting 0 fds returned. */
233 ctx->timeout = true;
234 ctx->nfds = 0;
235 ctx->method(ctx);
236
237 thr = pthread_create_blocked(ctx);
238
239 /* Read some data and re-check, the fd is expected to be returned. */
240 ATF_REQUIRE(read(ctx->sv[1], buf, space) == (ssize_t)space);
241
242 /* Now check that thread was successfully woken up and exited. */
243 ATF_REQUIRE(pthread_join(thr, NULL) == 0);
244
245 /* Extra check repeating what joined thread already did. */
246 ctx->method(ctx);
247
248 close(ctx->sv[0]);
249 close(ctx->sv[1]);
250 free(buf);
251 }
252
253 /*
254 * Make sure that a full socket is not reported as writable by event APIs.
255 */
256 ATF_TC_WITHOUT_HEAD(full_writability_select);
ATF_TC_BODY(full_writability_select,tc)257 ATF_TC_BODY(full_writability_select, tc)
258 {
259 struct check_ctx ctx = {
260 .method = check_select,
261 .select_what = SELECT_WR,
262 };
263
264 full_socketpair(ctx.sv);
265 full_writability_check(&ctx);
266 close(ctx.sv[0]);
267 close(ctx.sv[1]);
268 }
269
270 ATF_TC_WITHOUT_HEAD(full_writability_poll);
ATF_TC_BODY(full_writability_poll,tc)271 ATF_TC_BODY(full_writability_poll, tc)
272 {
273 struct check_ctx ctx = {
274 .method = check_poll,
275 .poll_events = POLLOUT | POLLWRNORM,
276 };
277
278 full_socketpair(ctx.sv);
279 full_writability_check(&ctx);
280 close(ctx.sv[0]);
281 close(ctx.sv[1]);
282 }
283
284 ATF_TC_WITHOUT_HEAD(full_writability_kevent);
ATF_TC_BODY(full_writability_kevent,tc)285 ATF_TC_BODY(full_writability_kevent, tc)
286 {
287 struct check_ctx ctx = {
288 .method = check_kevent,
289 .kev_filter = EVFILT_WRITE,
290 };
291
292 full_socketpair(ctx.sv);
293 full_writability_check(&ctx);
294 close(ctx.sv[0]);
295 close(ctx.sv[1]);
296 }
297
298 ATF_TC_WITHOUT_HEAD(connected_writability);
ATF_TC_BODY(connected_writability,tc)299 ATF_TC_BODY(connected_writability, tc)
300 {
301 struct check_ctx ctx = {
302 .timeout = true,
303 .nfds = 1,
304 };
305
306 do_socketpair(ctx.sv);
307
308 ctx.select_what = SELECT_WR;
309 check_select(&ctx);
310 ctx.poll_events = POLLOUT | POLLWRNORM;
311 check_poll(&ctx);
312 ctx.kev_filter = EVFILT_WRITE;
313 check_kevent(&ctx);
314
315 close(ctx.sv[0]);
316 close(ctx.sv[1]);
317 }
318
319 ATF_TC_WITHOUT_HEAD(unconnected_writability);
ATF_TC_BODY(unconnected_writability,tc)320 ATF_TC_BODY(unconnected_writability, tc)
321 {
322 struct check_ctx ctx = {
323 .timeout = true,
324 .nfds = 0,
325 };
326
327 ATF_REQUIRE((ctx.sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0);
328
329 ctx.select_what = SELECT_WR;
330 check_select(&ctx);
331 ctx.poll_events = POLLOUT | POLLWRNORM;
332 check_poll(&ctx);
333 ctx.kev_filter = EVFILT_WRITE;
334 check_kevent(&ctx);
335
336 close(ctx.sv[0]);
337 }
338
339 ATF_TC_WITHOUT_HEAD(peerclosed_writability);
ATF_TC_BODY(peerclosed_writability,tc)340 ATF_TC_BODY(peerclosed_writability, tc)
341 {
342 struct check_ctx ctx = {
343 .timeout = false,
344 .nfds = 1,
345 };
346
347 do_socketpair(ctx.sv);
348 close(ctx.sv[1]);
349
350 ctx.select_what = SELECT_WR;
351 check_select(&ctx);
352 ctx.poll_events = POLLOUT | POLLWRNORM;
353 check_poll(&ctx);
354 ctx.kev_filter = EVFILT_WRITE;
355 ctx.kev_flags = EV_EOF;
356 check_kevent(&ctx);
357
358 close(ctx.sv[0]);
359 }
360
361 ATF_TC_WITHOUT_HEAD(peershutdown_writability);
ATF_TC_BODY(peershutdown_writability,tc)362 ATF_TC_BODY(peershutdown_writability, tc)
363 {
364 struct check_ctx ctx = {
365 .timeout = false,
366 .nfds = 1,
367 };
368
369 do_socketpair(ctx.sv);
370 shutdown(ctx.sv[1], SHUT_RD);
371
372 ctx.select_what = SELECT_WR;
373 check_select(&ctx);
374 ctx.poll_events = POLLOUT | POLLWRNORM;
375 check_poll(&ctx);
376 /*
377 * XXXGL: historically unix(4) sockets were not reporting peer's
378 * shutdown(SHUT_RD) as our EV_EOF. The kevent(2) manual page says
379 * "filter will set EV_EOF when the reader disconnects", which is hard
380 * to interpret unambigously. For now leave the historic behavior,
381 * but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(),
382 * and then this test will also expect EV_EOF in returned flags.
383 */
384 ctx.kev_filter = EVFILT_WRITE;
385 check_kevent(&ctx);
386
387 close(ctx.sv[0]);
388 close(ctx.sv[1]);
389 }
390
391 ATF_TC_WITHOUT_HEAD(peershutdown_readability);
ATF_TC_BODY(peershutdown_readability,tc)392 ATF_TC_BODY(peershutdown_readability, tc)
393 {
394 struct check_ctx ctx = {
395 .timeout = false,
396 .nfds = 1,
397 };
398 ssize_t readsz;
399 char c;
400
401 do_socketpair(ctx.sv);
402 shutdown(ctx.sv[1], SHUT_WR);
403
404 /*
405 * The other side should flag as readable in select(2) to allow it to
406 * read(2) and observe EOF. Ensure that both poll(2) and select(2)
407 * are consistent here.
408 */
409 ctx.select_what = SELECT_RD;
410 check_select(&ctx);
411 ctx.poll_events = POLLIN | POLLRDNORM;
412 check_poll(&ctx);
413
414 /*
415 * Also check that read doesn't block.
416 */
417 readsz = read(ctx.sv[0], &c, sizeof(c));
418 ATF_REQUIRE_INTEQ(0, readsz);
419
420 close(ctx.sv[0]);
421 close(ctx.sv[1]);
422 }
423
424 static void
peershutdown_wakeup(struct check_ctx * ctx)425 peershutdown_wakeup(struct check_ctx *ctx)
426 {
427 pthread_t thr;
428
429 ctx->timeout = false;
430 ctx->nfds = 1;
431
432 do_socketpair(ctx->sv);
433 thr = pthread_create_blocked(ctx);
434 shutdown(ctx->sv[1], SHUT_WR);
435 ATF_REQUIRE(pthread_join(thr, NULL) == 0);
436
437 close(ctx->sv[0]);
438 close(ctx->sv[1]);
439 }
440
441 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_select);
ATF_TC_BODY(peershutdown_wakeup_select,tc)442 ATF_TC_BODY(peershutdown_wakeup_select, tc)
443 {
444 peershutdown_wakeup(&(struct check_ctx){
445 .method = check_select,
446 .select_what = SELECT_RD,
447 });
448 }
449
450 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_poll);
ATF_TC_BODY(peershutdown_wakeup_poll,tc)451 ATF_TC_BODY(peershutdown_wakeup_poll, tc)
452 {
453 peershutdown_wakeup(&(struct check_ctx){
454 .method = check_poll,
455 .poll_events = POLLIN | POLLRDNORM | POLLRDHUP,
456 .poll_revents = POLLRDHUP,
457 });
458 }
459
460 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_kevent);
ATF_TC_BODY(peershutdown_wakeup_kevent,tc)461 ATF_TC_BODY(peershutdown_wakeup_kevent, tc)
462 {
463 peershutdown_wakeup(&(struct check_ctx){
464 .method = check_kevent,
465 .kev_filter = EVFILT_READ,
466 .kev_flags = EV_EOF,
467 });
468 }
469
ATF_TP_ADD_TCS(tp)470 ATF_TP_ADD_TCS(tp)
471 {
472 ATF_TP_ADD_TC(tp, getpeereid);
473 ATF_TP_ADD_TC(tp, send_0);
474 ATF_TP_ADD_TC(tp, connected_writability);
475 ATF_TP_ADD_TC(tp, unconnected_writability);
476 ATF_TP_ADD_TC(tp, full_writability_select);
477 ATF_TP_ADD_TC(tp, full_writability_poll);
478 ATF_TP_ADD_TC(tp, full_writability_kevent);
479 ATF_TP_ADD_TC(tp, peerclosed_writability);
480 ATF_TP_ADD_TC(tp, peershutdown_writability);
481 ATF_TP_ADD_TC(tp, peershutdown_readability);
482 ATF_TP_ADD_TC(tp, peershutdown_wakeup_select);
483 ATF_TP_ADD_TC(tp, peershutdown_wakeup_poll);
484 ATF_TP_ADD_TC(tp, peershutdown_wakeup_kevent);
485
486 return atf_no_error();
487 }
488