xref: /freebsd/tests/sys/kern/unix_stream.c (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
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
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
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);
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);
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
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
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
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
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 *
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
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
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);
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);
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);
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);
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);
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);
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);
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);
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
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);
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);
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);
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 
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