xref: /freebsd/tests/sys/netinet/socket_afinet.c (revision 618dc484b5817b7a7560632410c9ca5c32c85a84)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Bjoern A. Zeeb
5  * Copyright (c) 2024 Stormshield
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <sys/wait.h>
32 
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 
36 #include <errno.h>
37 #include <poll.h>
38 #include <pwd.h>
39 #include <stdio.h>
40 #include <unistd.h>
41 
42 #include <atf-c.h>
43 
44 ATF_TC_WITHOUT_HEAD(basic);
ATF_TC_BODY(basic,tc)45 ATF_TC_BODY(basic, tc)
46 {
47 	int sd;
48 
49 	sd = socket(PF_INET, SOCK_DGRAM, 0);
50 	ATF_CHECK(sd >= 0);
51 
52 	close(sd);
53 }
54 
55 ATF_TC_WITHOUT_HEAD(bind_zero);
ATF_TC_BODY(bind_zero,tc)56 ATF_TC_BODY(bind_zero, tc)
57 {
58 	int sd, rc;
59 	struct sockaddr_in sin;
60 
61 	sd = socket(PF_INET, SOCK_DGRAM, 0);
62 	ATF_CHECK(sd >= 0);
63 
64 	bzero(&sin, sizeof(sin));
65 	/*
66 	 * For AF_INET we do not check the family in in_pcbbind_setup(9),
67 	 * sa_len gets set from the syscall argument in getsockaddr(9),
68 	 * so we bind to 0:0.
69 	 */
70 	rc = bind(sd, (struct sockaddr *)&sin, sizeof(sin));
71 	ATF_CHECK_EQ(0, rc);
72 
73 	close(sd);
74 }
75 
76 ATF_TC_WITHOUT_HEAD(bind_ok);
ATF_TC_BODY(bind_ok,tc)77 ATF_TC_BODY(bind_ok, tc)
78 {
79 	int sd, rc;
80 	struct sockaddr_in sin;
81 
82 	sd = socket(PF_INET, SOCK_DGRAM, 0);
83 	ATF_CHECK(sd >= 0);
84 
85 	bzero(&sin, sizeof(sin));
86 	sin.sin_family = AF_INET;
87 	sin.sin_len = sizeof(sin);
88 	sin.sin_port = htons(0);
89 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
90 	rc = bind(sd, (struct sockaddr *)&sin, sizeof(sin));
91 	ATF_CHECK_EQ(0, rc);
92 
93 	close(sd);
94 }
95 
96 ATF_TC_WITHOUT_HEAD(poll_no_rdhup);
ATF_TC_BODY(poll_no_rdhup,tc)97 ATF_TC_BODY(poll_no_rdhup, tc)
98 {
99 	int ss, ss2, cs, rc;
100 	struct sockaddr_in sin;
101 	socklen_t slen;
102 	struct pollfd pfd;
103 	int one = 1;
104 
105 	/* Verify that we don't expose POLLRDHUP if not requested. */
106 
107 	/* Server setup. */
108 	ss = socket(PF_INET, SOCK_STREAM, 0);
109 	ATF_CHECK(ss >= 0);
110 	rc = setsockopt(ss, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
111 	ATF_CHECK_EQ(0, rc);
112 	bzero(&sin, sizeof(sin));
113 	sin.sin_family = AF_INET;
114 	sin.sin_len = sizeof(sin);
115 	sin.sin_port = htons(0);
116 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
117 	rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin));
118 	ATF_CHECK_EQ(0, rc);
119 	rc = listen(ss, 1);
120 	ATF_CHECK_EQ(0, rc);
121 	slen = sizeof(sin);
122 	rc = getsockname(ss, (struct sockaddr *)&sin, &slen);
123 	ATF_CHECK_EQ(0, rc);
124 
125 	/* Client connects, server accepts. */
126 	cs = socket(PF_INET, SOCK_STREAM, 0);
127 	ATF_CHECK(cs >= 0);
128 	rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
129 	ATF_CHECK_EQ(0, rc);
130 	ss2 = accept(ss, NULL, NULL);
131 	ATF_CHECK(ss2 >= 0);
132 
133 	/* Server can write, sees only POLLOUT. */
134 	pfd.fd = ss2;
135 	pfd.events = POLLIN | POLLOUT;
136 	rc = poll(&pfd, 1, 0);
137 	ATF_CHECK_EQ(1, rc);
138 	ATF_CHECK_EQ(POLLOUT, pfd.revents);
139 
140 	/* Client closes socket! */
141 	rc = close(cs);
142 	ATF_CHECK_EQ(0, rc);
143 
144 	/*
145 	 * Server now sees POLLIN, but not POLLRDHUP because we didn't ask.
146 	 * Need non-zero timeout to wait for the FIN to arrive and trigger the
147 	 * socket to become readable.
148 	 */
149 	pfd.fd = ss2;
150 	pfd.events = POLLIN;
151 	rc = poll(&pfd, 1, 60000);
152 	ATF_CHECK_EQ(1, rc);
153 	ATF_CHECK_EQ(POLLIN, pfd.revents);
154 
155 	close(ss2);
156 	close(ss);
157 }
158 
159 ATF_TC_WITHOUT_HEAD(poll_rdhup);
ATF_TC_BODY(poll_rdhup,tc)160 ATF_TC_BODY(poll_rdhup, tc)
161 {
162 	int ss, ss2, cs, rc;
163 	struct sockaddr_in sin;
164 	socklen_t slen;
165 	struct pollfd pfd;
166 	char buffer;
167 	int one = 1;
168 
169 	/* Verify that server sees POLLRDHUP if it asks for it. */
170 
171 	/* Server setup. */
172 	ss = socket(PF_INET, SOCK_STREAM, 0);
173 	ATF_CHECK(ss >= 0);
174 	rc = setsockopt(ss, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
175 	ATF_CHECK_EQ(0, rc);
176 	bzero(&sin, sizeof(sin));
177 	sin.sin_family = AF_INET;
178 	sin.sin_len = sizeof(sin);
179 	sin.sin_port = htons(0);
180 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
181 	rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin));
182 	ATF_CHECK_EQ(0, rc);
183 	rc = listen(ss, 1);
184 	ATF_CHECK_EQ(0, rc);
185 	slen = sizeof(sin);
186 	rc = getsockname(ss, (struct sockaddr *)&sin, &slen);
187 	ATF_CHECK_EQ(0, rc);
188 
189 	/* Client connects, server accepts. */
190 	cs = socket(PF_INET, SOCK_STREAM, 0);
191 	ATF_CHECK(cs >= 0);
192 	rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
193 	ATF_CHECK_EQ(0, rc);
194 	ss2 = accept(ss, NULL, NULL);
195 	ATF_CHECK(ss2 >= 0);
196 
197 	/* Server can write, so sees POLLOUT. */
198 	pfd.fd = ss2;
199 	pfd.events = POLLIN | POLLOUT | POLLRDHUP;
200 	rc = poll(&pfd, 1, 0);
201 	ATF_CHECK_EQ(1, rc);
202 	ATF_CHECK_EQ(POLLOUT, pfd.revents);
203 
204 	/* Client writes two bytes, server reads only one of them. */
205 	rc = write(cs, "xx", 2);
206 	ATF_CHECK_EQ(2, rc);
207 	rc = read(ss2, &buffer, 1);
208 	ATF_CHECK_EQ(1, rc);
209 
210 	/* Server can read, so sees POLLIN. */
211 	pfd.fd = ss2;
212 	pfd.events = POLLIN | POLLOUT | POLLRDHUP;
213 	rc = poll(&pfd, 1, 0);
214 	ATF_CHECK_EQ(1, rc);
215 	ATF_CHECK_EQ(POLLIN | POLLOUT, pfd.revents);
216 
217 	/* Client closes socket! */
218 	rc = close(cs);
219 	ATF_CHECK_EQ(0, rc);
220 
221 	/*
222 	 * Server sees Linux-style POLLRDHUP.  Note that this is the case even
223 	 * though one byte of data remains unread.
224 	 *
225 	 * This races against the delivery of FIN caused by the close() above.
226 	 * Sometimes (more likely when run under truss or if another system
227 	 * call is added in between) it hits the path where sopoll_generic()
228 	 * immediately sees SBS_CANTRCVMORE, and sometimes it sleeps with flag
229 	 * SB_SEL so that it's woken up almost immediately and runs again,
230 	 * which is why we need a non-zero timeout here.
231 	 */
232 	pfd.fd = ss2;
233 	pfd.events = POLLRDHUP;
234 	rc = poll(&pfd, 1, 60000);
235 	ATF_CHECK_EQ(1, rc);
236 	ATF_CHECK_EQ(POLLRDHUP, pfd.revents);
237 
238 	close(ss2);
239 	close(ss);
240 }
241 
242 ATF_TC_WITHOUT_HEAD(stream_reconnect);
ATF_TC_BODY(stream_reconnect,tc)243 ATF_TC_BODY(stream_reconnect, tc)
244 {
245 	struct sockaddr_in sin;
246 	socklen_t slen;
247 	int ss, cs, rc;
248 
249 	/*
250 	 * Make sure that an attempt to connect(2) a connected or disconnected
251 	 * stream socket fails with EISCONN.
252 	 */
253 
254 	/* Server setup. */
255 	ss = socket(PF_INET, SOCK_STREAM, 0);
256 	ATF_CHECK(ss >= 0);
257 	bzero(&sin, sizeof(sin));
258 	sin.sin_family = AF_INET;
259 	sin.sin_len = sizeof(sin);
260 	sin.sin_port = htons(0);
261 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
262 	rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin));
263 	ATF_CHECK_EQ(0, rc);
264 	rc = listen(ss, 1);
265 	ATF_CHECK_EQ(0, rc);
266 	slen = sizeof(sin);
267 	rc = getsockname(ss, (struct sockaddr *)&sin, &slen);
268 	ATF_CHECK_EQ(0, rc);
269 
270 	/* Client connects, shuts down. */
271 	cs = socket(PF_INET, SOCK_STREAM, 0);
272 	ATF_CHECK(cs >= 0);
273 	rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
274 	ATF_CHECK_EQ(0, rc);
275 	rc = shutdown(cs, SHUT_RDWR);
276 	ATF_CHECK_EQ(0, rc);
277 
278 	/* A subsequent connect(2) fails with EISCONN. */
279 	rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin));
280 	ATF_CHECK_EQ(-1, rc);
281 	ATF_CHECK_EQ(errno, EISCONN);
282 
283 	rc = close(cs);
284 	ATF_CHECK_EQ(0, rc);
285 	rc = close(ss);
286 	ATF_CHECK_EQ(0, rc);
287 }
288 
289 /*
290  * Make sure that unprivileged users can't set the IP_BINDANY or IPV6_BINDANY
291  * socket options.
292  */
293 ATF_TC(bindany);
ATF_TC_HEAD(bindany,tc)294 ATF_TC_HEAD(bindany, tc)
295 {
296 	atf_tc_set_md_var(tc, "require.user", "unprivileged");
297 }
ATF_TC_BODY(bindany,tc)298 ATF_TC_BODY(bindany, tc)
299 {
300 	int s;
301 
302 	s = socket(AF_INET, SOCK_STREAM, 0);
303 	ATF_REQUIRE(s >= 0);
304 	ATF_REQUIRE_ERRNO(EPERM,
305 	    setsockopt(s, IPPROTO_IP, IP_BINDANY, &(int){1}, sizeof(int)) ==
306 	    -1);
307 	ATF_REQUIRE(close(s) == 0);
308 
309 	s = socket(AF_INET, SOCK_DGRAM, 0);
310 	ATF_REQUIRE(s >= 0);
311 	ATF_REQUIRE_ERRNO(EPERM,
312 	    setsockopt(s, IPPROTO_IP, IP_BINDANY, &(int){1}, sizeof(int)) ==
313 	    -1);
314 	ATF_REQUIRE(close(s) == 0);
315 
316 	s = socket(AF_INET6, SOCK_STREAM, 0);
317 	ATF_REQUIRE(s >= 0);
318 	ATF_REQUIRE_ERRNO(EPERM,
319 	    setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY, &(int){1}, sizeof(int)) ==
320 	    -1);
321 	ATF_REQUIRE(close(s) == 0);
322 
323 	s = socket(AF_INET6, SOCK_DGRAM, 0);
324 	ATF_REQUIRE(s >= 0);
325 	ATF_REQUIRE_ERRNO(EPERM,
326 	    setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY, &(int){1}, sizeof(int)) ==
327 	    -1);
328 	ATF_REQUIRE(close(s) == 0);
329 }
330 
331 /*
332  * Bind a socket to the specified address, optionally dropping privileges and
333  * setting one of the SO_REUSE* options first.
334  *
335  * Expected returns for different test case scenarios are: 1) successful
336  * immediate bind(2), successful bind(2) after setting specified SO_REUSE*
337  * socket option, and bind(2) failed with EADDRINUSE.
338  */
339 static enum bind_res {
340 	BIND_FAILED = 0,
341 	SETEUID_FAIL = 1,
342 	SOCKET_FAIL = 2,
343 	BIND_INSTANT_SUCCESS = 3,
344 	BIND_BADERR1 = 4,
345 	SETSOCKOPT_FAIL = 5,
346 	BIND_REUSE_SUCCESS = 6,
347 	BIND_BADERR2 = 7,
348 }
child_bind(const atf_tc_t * tc,int type,const struct sockaddr * sa,int opt,bool unpriv)349 child_bind(const atf_tc_t *tc, int type, const struct sockaddr *sa, int opt,
350     bool unpriv)
351 {
352 	const char *user;
353 	pid_t child;
354 
355 	if (unpriv) {
356 		if (!atf_tc_has_config_var(tc, "unprivileged_user"))
357 			atf_tc_skip("unprivileged_user not set");
358 		user = atf_tc_get_config_var(tc, "unprivileged_user");
359 	} else {
360 		user = NULL;
361 	}
362 
363 	child = fork();
364 	ATF_REQUIRE(child != -1);
365 	if (child == 0) {
366 		int s;
367 
368 		if (user != NULL) {
369 			struct passwd *passwd;
370 
371 			passwd = getpwnam(user);
372 			if (seteuid(passwd->pw_uid) != 0)
373 				_exit(SETEUID_FAIL);
374 		}
375 
376 		s = socket(sa->sa_family, type, 0);
377 		if (s < 0)
378 			_exit(SOCKET_FAIL);
379 		if (bind(s, sa, sa->sa_len) == 0)
380 			_exit(BIND_INSTANT_SUCCESS);
381 		if (errno != EADDRINUSE)
382 			_exit(BIND_BADERR1);
383 		if (opt != 0) {
384 			if (setsockopt(s, SOL_SOCKET, opt, &(int){1},
385 			    sizeof(int)) != 0)
386 				_exit(SETSOCKOPT_FAIL);
387 		}
388 		if (bind(s, sa, sa->sa_len) == 0)
389 			_exit(BIND_REUSE_SUCCESS);
390 		if (errno != EADDRINUSE)
391 			_exit(BIND_BADERR1);
392 		_exit(BIND_FAILED);
393 	} else {
394 		int status;
395 
396 		ATF_REQUIRE_EQ(waitpid(child, &status, 0), child);
397 		ATF_REQUIRE(WIFEXITED(status));
398 		status = WEXITSTATUS(status);
399 		return (status);
400 	}
401 }
402 
403 /*
404  * Try to bind two sockets to the same address/port tuple.  Under some
405  * conditions this is permitted.
406  */
407 ATF_TC(multibind);
ATF_TC_HEAD(multibind,tc)408 ATF_TC_HEAD(multibind, tc)
409 {
410 	atf_tc_set_md_var(tc, "require.user", "root");
411 	atf_tc_set_md_var(tc, "require.config", "unprivileged_user");
412 }
413 
ATF_TC_BODY(multibind,tc)414 ATF_TC_BODY(multibind, tc)
415 {
416 	const struct {
417 		int type;
418 		int opt1;
419 		bool wild1;
420 		int opt2;
421 		bool wild2;	/* not exercised yet, uses getsockname() rv */
422 		enum bind_res priv_res;
423 		enum bind_res unpriv_res;
424 	} tests[] = {
425 #define	ADDR	SO_REUSEADDR
426 #define	PORT	SO_REUSEPORT
427 #define	LB	SO_REUSEPORT_LB
428 #define	x true
429 #define	o false
430 #define	F BIND_FAILED
431 #define	R BIND_REUSE_SUCCESS
432 		/*                               p  u */
433 		{ SOCK_STREAM,    0, o,    0, o, F, F },
434 		{ SOCK_STREAM,    0, o, ADDR, o, F, F },
435 		{ SOCK_STREAM,    0, o, PORT, o, F, F },
436 		{ SOCK_STREAM,    0, o,   LB, o, F, F },
437 		{ SOCK_STREAM, ADDR, o,    0, o, F, F },
438 		{ SOCK_STREAM, ADDR, o, ADDR, o, F, F },
439 		{ SOCK_STREAM, ADDR, o, PORT, o, F, F },
440 		{ SOCK_STREAM, ADDR, o,   LB, o, F, F },
441 		{ SOCK_STREAM, PORT, o,    0, o, F, F },
442 		{ SOCK_STREAM, PORT, o, ADDR, o, F, F },
443 		{ SOCK_STREAM, PORT, o, PORT, o, R, F },
444 		{ SOCK_STREAM, PORT, o,   LB, o, F, F },
445 		{ SOCK_STREAM,   LB, o,    0, o, F, F },
446 		{ SOCK_STREAM,   LB, o, ADDR, o, F, F },
447 		{ SOCK_STREAM,   LB, o, PORT, o, F, F },
448 		{ SOCK_STREAM,   LB, o,   LB, o, R, F },
449 		{ SOCK_STREAM,    0, x,    0, x, F, F },
450 		{ SOCK_STREAM,    0, x, ADDR, x, F, F },
451 		{ SOCK_STREAM,    0, x, PORT, x, F, F },
452 		{ SOCK_STREAM,    0, x,   LB, x, F, F },
453 		{ SOCK_STREAM, ADDR, x,    0, x, F, F },
454 		{ SOCK_STREAM, ADDR, x, ADDR, x, F, F },
455 		{ SOCK_STREAM, ADDR, x, PORT, x, F, F },
456 		{ SOCK_STREAM, ADDR, x,   LB, x, F, F },
457 		{ SOCK_STREAM, PORT, x,    0, x, F, F },
458 		{ SOCK_STREAM, PORT, x, ADDR, x, F, F },
459 		{ SOCK_STREAM, PORT, x, PORT, x, R, F },
460 		{ SOCK_STREAM, PORT, x,   LB, x, F, F },
461 		{ SOCK_STREAM,   LB, x,    0, x, F, F },
462 		{ SOCK_STREAM,   LB, x, ADDR, x, F, F },
463 		{ SOCK_STREAM,   LB, x, PORT, x, F, F },
464 		{ SOCK_STREAM,   LB, x,   LB, x, R, F },
465 		{ SOCK_STREAM,    0, x,    0, o, F, F },
466 		{ SOCK_STREAM,    0, x, ADDR, o, R, F },
467 		{ SOCK_STREAM,    0, x, PORT, o, R, F }, /* bug? */
468 		{ SOCK_STREAM,    0, o,    0, x, F, F },
469 		{ SOCK_STREAM,    0, o, ADDR, x, R, F }, /* too strict? */
470 		{ SOCK_STREAM,    0, o, PORT, x, R, F }, /* bug? */
471 		/*
472 		 * ATM, expected result for SOCK_DGRAM is the same as for
473 		 * SOCK_STREAM.  Thus the below is copy-and-paste of the above.
474 		 */
475 		{ SOCK_DGRAM,    0, o,    0, o, F, F },
476 		{ SOCK_DGRAM,    0, o, ADDR, o, F, F },
477 		{ SOCK_DGRAM,    0, o, PORT, o, F, F },
478 		{ SOCK_DGRAM,    0, o,   LB, o, F, F },
479 		{ SOCK_DGRAM, ADDR, o,    0, o, F, F },
480 		{ SOCK_DGRAM, ADDR, o, ADDR, o, F, F },
481 		{ SOCK_DGRAM, ADDR, o, PORT, o, F, F },
482 		{ SOCK_DGRAM, ADDR, o,   LB, o, F, F },
483 		{ SOCK_DGRAM, PORT, o,    0, o, F, F },
484 		{ SOCK_DGRAM, PORT, o, ADDR, o, F, F },
485 		{ SOCK_DGRAM, PORT, o, PORT, o, R, F },
486 		{ SOCK_DGRAM, PORT, o,   LB, o, F, F },
487 		{ SOCK_DGRAM,   LB, o,    0, o, F, F },
488 		{ SOCK_DGRAM,   LB, o, ADDR, o, F, F },
489 		{ SOCK_DGRAM,   LB, o, PORT, o, F, F },
490 		{ SOCK_DGRAM,   LB, o,   LB, o, R, F },
491 		{ SOCK_DGRAM,    0, x,    0, x, F, F },
492 		{ SOCK_DGRAM,    0, x, ADDR, x, F, F },
493 		{ SOCK_DGRAM,    0, x, PORT, x, F, F },
494 		{ SOCK_DGRAM,    0, x,   LB, x, F, F },
495 		{ SOCK_DGRAM, ADDR, x,    0, x, F, F },
496 		{ SOCK_DGRAM, ADDR, x, ADDR, x, F, F },
497 		{ SOCK_DGRAM, ADDR, x, PORT, x, F, F },
498 		{ SOCK_DGRAM, ADDR, x,   LB, x, F, F },
499 		{ SOCK_DGRAM, PORT, x,    0, x, F, F },
500 		{ SOCK_DGRAM, PORT, x, ADDR, x, F, F },
501 		{ SOCK_DGRAM, PORT, x, PORT, x, R, F },
502 		{ SOCK_DGRAM, PORT, x,   LB, x, F, F },
503 		{ SOCK_DGRAM,   LB, x,    0, x, F, F },
504 		{ SOCK_DGRAM,   LB, x, ADDR, x, F, F },
505 		{ SOCK_DGRAM,   LB, x, PORT, x, F, F },
506 		{ SOCK_DGRAM,   LB, x,   LB, x, R, F },
507 		{ SOCK_DGRAM,    0, x,    0, o, F, F },
508 		{ SOCK_DGRAM,    0, x, ADDR, o, R, F },
509 		{ SOCK_DGRAM,    0, x, PORT, o, R, F }, /* bug? */
510 		{ SOCK_DGRAM,    0, o,    0, x, F, F },
511 		{ SOCK_DGRAM,    0, o, ADDR, x, R, F }, /* too strict? */
512 		{ SOCK_DGRAM,    0, o, PORT, x, R, F }, /* bug? */
513 #undef F
514 #undef R
515 #undef x
516 #undef o
517 #undef ADDR
518 #undef PORT
519 #undef LB
520 	};
521 	/*
522 	 * Expected results for IPv4 and IPv6 shall always be the same, so
523 	 * this dimension is implemented as a cycle rather than table entry.
524 	 */
525 	const union sockaddr_union {
526 		struct sockaddr_in sin;
527 		struct sockaddr_in6 sin6;
528 		struct sockaddr sa;
529 	} wild[] = {
530 		{
531 		    .sin.sin_family = AF_INET,
532 		    .sin.sin_len = sizeof(struct sockaddr_in),
533 		},
534 		{
535 		    .sin6.sin6_family = AF_INET6,
536 		    .sin6.sin6_len = sizeof(struct sockaddr_in6),
537 		},
538 	}, loop[] = {
539 		{
540 		    .sin.sin_family = AF_INET,
541 		    .sin.sin_len = sizeof(struct sockaddr_in),
542 		    .sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
543 		},
544 		{
545 		    .sin6.sin6_family = AF_INET6,
546 		    .sin6.sin6_len = sizeof(struct sockaddr_in6),
547 		    .sin6.sin6_addr = in6addr_loopback,
548 		},
549 	};
550 
551 	_Static_assert(nitems(wild) == nitems(loop), "EDOOFUS");
552 	for (u_int af = 0; af < nitems(wild); af++) {
553 		for (u_int i = 0; i < nitems(tests); i++) {
554 			const struct sockaddr *sa;
555 			union sockaddr_union su;
556 			socklen_t slen;
557 			enum bind_res res;
558 			int s;
559 			in_port_t port;
560 
561 			s = socket(wild[af].sa.sa_family, tests[i].type, 0);
562 			ATF_REQUIRE(s >= 0);
563 			sa = tests[i].wild1 ? &wild[af].sa : &loop[af].sa;
564 			slen = sa->sa_len;
565 			ATF_REQUIRE(bind(s, sa, slen) == 0);
566 			if (tests[i].opt1 != 0)
567 				ATF_REQUIRE(setsockopt(s, SOL_SOCKET,
568 				    tests[i].opt1, &(int){1}, sizeof(int)) ==
569 				    0);
570 			ATF_REQUIRE(getsockname(s, &su.sa, &slen) == 0);
571 			_Static_assert(offsetof(struct sockaddr_in, sin_port)
572 			    == offsetof(struct sockaddr_in6, sin6_port),
573 			    "EDOOFUS");
574 			port = su.sin.sin_port;
575 			memcpy(&su, tests[i].wild2 ? &wild[af] : &loop[af],
576 			    sizeof(su));
577 			su.sin.sin_port = port;
578 			sa = &su.sa;
579 			res = child_bind(tc, tests[i].type, sa, tests[i].opt2,
580 			    false);
581 			ATF_REQUIRE_MSG(tests[i].priv_res == res,
582 			    "af %d test #%d (priv) failed", sa->sa_family, i);
583 
584 			res = child_bind(tc, tests[i].type, sa, tests[i].opt2,
585 			    true);
586 			ATF_REQUIRE_MSG(tests[i].unpriv_res == res,
587 			    "af %d test #%d (unpriv) failed", sa->sa_family, i);
588 
589 			ATF_REQUIRE(close(s) == 0);
590 		}
591 	}
592 }
593 
594 /*
595  * Test operation of bind(2) in presence of a connected inpcb using the
596  * same local port.
597  */
598 static enum bind_res
bind_connected_port_test(const atf_tc_t * tc,int domain,int type,bool wild,bool unpriv)599 bind_connected_port_test(const atf_tc_t *tc, int domain, int type, bool wild,
600     bool unpriv)
601 {
602 	struct sockaddr_in sin;
603 	struct sockaddr_in6 sin6;
604 	struct sockaddr *sinp;
605 	socklen_t slen;
606 	int error, ss, cs, as;
607 	enum bind_res res;
608 
609 	/*
610 	 * Create a connected socket pair.
611 	 */
612 	ss = socket(domain, type, 0);
613 	ATF_REQUIRE_MSG(ss >= 0, "socket failed: %s", strerror(errno));
614 	if (domain == PF_INET) {
615 		memset(&sin, 0, sizeof(sin));
616 		sin.sin_family = AF_INET;
617 		sin.sin_len = sizeof(sin);
618 		sin.sin_addr.s_addr = htonl(INADDR_ANY);
619 		sin.sin_port = htons(0);
620 		sinp = (struct sockaddr *)&sin;
621 	} else {
622 		ATF_REQUIRE(domain == PF_INET6);
623 		memset(&sin6, 0, sizeof(sin6));
624 		sin6.sin6_family = AF_INET6;
625 		sin6.sin6_len = sizeof(sin6);
626 		sin6.sin6_addr = in6addr_any;
627 		sin6.sin6_port = htons(0);
628 		sinp = (struct sockaddr *)&sin6;
629 	}
630 
631 	error = bind(ss, sinp, sinp->sa_len);
632 	ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
633 
634 	if (type == SOCK_STREAM) {
635 		error = getsockname(ss, sinp, &(socklen_t){ sinp->sa_len });
636 		ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s",
637 		    strerror(errno));
638 		error = listen(ss, 1);
639 		ATF_REQUIRE_MSG(error == 0,
640 		    "listen failed: %s", strerror(errno));
641 		cs = socket(domain, type, 0);
642 		ATF_REQUIRE_MSG(cs >= 0, "socket failed: %s", strerror(errno));
643 		if (domain == PF_INET)
644 			sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
645 		else
646 			sin6.sin6_addr = in6addr_loopback;
647 		error = connect(cs, sinp, sinp->sa_len);
648 		ATF_REQUIRE_MSG(error == 0,
649 		    "connect failed: %s", strerror(errno));
650 		slen = sinp->sa_len;
651 		as = accept(ss, sinp, &slen);
652 		ATF_REQUIRE_MSG(as >= 0, "accept failed: %s", strerror(errno));
653 	} else {
654 		ATF_REQUIRE(type == SOCK_DGRAM);
655 		if (domain == PF_INET) {
656 			sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
657 			sin.sin_port = htons(6666);
658 		} else {
659 			sin6.sin6_addr = in6addr_loopback;
660 			sin6.sin6_port = htons(6666);
661 		}
662 		error = connect(ss, sinp, sinp->sa_len);
663 		ATF_REQUIRE_MSG(error == 0,
664 		    "connect failed: %s", strerror(errno));
665 		error = getsockname(ss, sinp, &(socklen_t){ sinp->sa_len });
666 		ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s",
667 		    strerror(errno));
668 	}
669 
670 	if (wild) {
671 		if (domain == PF_INET)
672 			sin.sin_addr.s_addr = htonl(INADDR_ANY);
673 		else
674 			sin6.sin6_addr = in6addr_any;
675 	}
676 
677 	res = child_bind(tc, type, sinp, SO_REUSEADDR, unpriv);
678 
679 	if (type == SOCK_STREAM) {
680 		ATF_REQUIRE(close(as) == 0);
681 		ATF_REQUIRE(close(cs) == 0);
682 	}
683 	ATF_REQUIRE(close(ss) == 0);
684 
685 	return (res);
686 }
687 
688 /*
689  * Normally bind() prevents port stealing by a different user, even when
690  * SO_REUSE* are specified.  However, if the port is bound by a connected
691  * socket, then it's fair game.
692  */
693 ATF_TC(bind_connected_port);
ATF_TC_HEAD(bind_connected_port,tc)694 ATF_TC_HEAD(bind_connected_port, tc)
695 {
696 	atf_tc_set_md_var(tc, "require.user", "root");
697 	atf_tc_set_md_var(tc, "require.config", "unprivileged_user");
698 }
ATF_TC_BODY(bind_connected_port,tc)699 ATF_TC_BODY(bind_connected_port, tc)
700 {
701 	struct bind_connected_port_res {
702 		int domain;
703 		int type;
704 		bool wild;
705 		bool unpriv;
706 		enum bind_res result;
707 	} tests[] = {
708 #define	x true
709 #define	o false
710 				     /* W  U */
711 	    { AF_INET,	SOCK_STREAM,	x, x, BIND_REUSE_SUCCESS },
712 	    { AF_INET,	SOCK_STREAM,	o, x, BIND_REUSE_SUCCESS },
713 	    { AF_INET,	SOCK_STREAM,	x, o, BIND_REUSE_SUCCESS },
714 	    { AF_INET,	SOCK_STREAM,	o, o, BIND_REUSE_SUCCESS },
715 	    { AF_INET6,	SOCK_STREAM,	x, x, BIND_REUSE_SUCCESS },
716 	    { AF_INET6,	SOCK_STREAM,	o, x, BIND_REUSE_SUCCESS },
717 	    { AF_INET6,	SOCK_STREAM,	x, o, BIND_REUSE_SUCCESS },
718 	    { AF_INET6,	SOCK_STREAM,	o, o, BIND_REUSE_SUCCESS },
719 	    { AF_INET,	SOCK_DGRAM,	x, x, BIND_FAILED },
720 	    { AF_INET,	SOCK_DGRAM,	o, x, BIND_FAILED },
721 	    { AF_INET,	SOCK_DGRAM,	x, o, BIND_REUSE_SUCCESS },
722 	    { AF_INET,	SOCK_DGRAM,	o, o, BIND_REUSE_SUCCESS },
723 	    { AF_INET6,	SOCK_DGRAM,	x, x, BIND_FAILED },
724 	    { AF_INET6,	SOCK_DGRAM,	o, x, BIND_FAILED },
725 	    { AF_INET6,	SOCK_DGRAM,	x, o, BIND_REUSE_SUCCESS },
726 	    { AF_INET6,	SOCK_DGRAM,	o, o, BIND_REUSE_SUCCESS },
727 #undef x
728 #undef o
729 	};
730 
731 	for (u_int i = 0; i < nitems(tests); i++) {
732 		enum bind_res res;
733 
734 		res = bind_connected_port_test(tc, tests[i].domain,
735 		    tests[i].type, tests[i].wild, tests[i].unpriv);
736 		ATF_REQUIRE_MSG(res == tests[i].result, "test #%u: "
737 		    "domain %u type %u%s %sprivileged: result %u (expected %u)",
738 		    i, tests[i].domain, tests[i].type,
739 		    tests[i].wild ? " wild" : "",
740 		    tests[i].unpriv ? "un" : "",
741 		    res, tests[i].result);
742 	}
743 }
744 
ATF_TP_ADD_TCS(tp)745 ATF_TP_ADD_TCS(tp)
746 {
747 	ATF_TP_ADD_TC(tp, basic);
748 	ATF_TP_ADD_TC(tp, bind_zero);
749 	ATF_TP_ADD_TC(tp, bind_ok);
750 	ATF_TP_ADD_TC(tp, poll_no_rdhup);
751 	ATF_TP_ADD_TC(tp, poll_rdhup);
752 	ATF_TP_ADD_TC(tp, stream_reconnect);
753 	ATF_TP_ADD_TC(tp, bindany);
754 	ATF_TP_ADD_TC(tp, multibind);
755 	ATF_TP_ADD_TC(tp, bind_connected_port);
756 
757 	return atf_no_error();
758 }
759