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); 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); 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); 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); 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); 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); 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); 294 ATF_TC_HEAD(bindany, tc) 295 { 296 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 297 } 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 } 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); 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 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 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); 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 } 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 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