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, 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 static enum bind_res 404 child_bind_priv(const atf_tc_t *tc, int type, struct sockaddr *sa, int opt) 405 { 406 return (child_bind(tc, type, sa, opt, false)); 407 } 408 409 static enum bind_res 410 child_bind_unpriv(const atf_tc_t *tc, int type, struct sockaddr *sa, int opt) 411 { 412 return (child_bind(tc, type, sa, opt, true)); 413 } 414 415 static int 416 bind_socket(int domain, int type, int opt, bool unspec, struct sockaddr *sa) 417 { 418 socklen_t slen; 419 int s; 420 421 s = socket(domain, type, 0); 422 ATF_REQUIRE(s >= 0); 423 424 if (domain == AF_INET) { 425 struct sockaddr_in sin; 426 427 bzero(&sin, sizeof(sin)); 428 sin.sin_family = AF_INET; 429 sin.sin_len = sizeof(sin); 430 sin.sin_addr.s_addr = htonl(unspec ? 431 INADDR_ANY : INADDR_LOOPBACK); 432 sin.sin_port = htons(0); 433 ATF_REQUIRE(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0); 434 435 slen = sizeof(sin); 436 } else /* if (domain == AF_INET6) */ { 437 struct sockaddr_in6 sin6; 438 439 bzero(&sin6, sizeof(sin6)); 440 sin6.sin6_family = AF_INET6; 441 sin6.sin6_len = sizeof(sin6); 442 sin6.sin6_addr = unspec ? in6addr_any : in6addr_loopback; 443 sin6.sin6_port = htons(0); 444 ATF_REQUIRE(bind(s, (struct sockaddr *)&sin6, sizeof(sin6)) == 0); 445 446 slen = sizeof(sin6); 447 } 448 449 if (opt != 0) { 450 ATF_REQUIRE(setsockopt(s, SOL_SOCKET, opt, &(int){1}, 451 sizeof(int)) == 0); 452 } 453 454 ATF_REQUIRE(getsockname(s, sa, &slen) == 0); 455 456 return (s); 457 } 458 459 static void 460 multibind_test(const atf_tc_t *tc, int domain, int type) 461 { 462 struct sockaddr_storage ss; 463 int opts[4] = { 0, SO_REUSEADDR, SO_REUSEPORT, SO_REUSEPORT_LB }; 464 int s; 465 bool flags[2] = { false, true }; 466 enum bind_res res; 467 468 for (size_t flagi = 0; flagi < nitems(flags); flagi++) { 469 for (size_t opti = 0; opti < nitems(opts); opti++) { 470 s = bind_socket(domain, type, opts[opti], flags[flagi], 471 (struct sockaddr *)&ss); 472 for (size_t optj = 0; optj < nitems(opts); optj++) { 473 int opt; 474 475 opt = opts[optj]; 476 res = child_bind_priv(tc, type, 477 (struct sockaddr *)&ss, opt); 478 /* 479 * Multi-binding is only allowed when both 480 * sockets have SO_REUSEPORT or SO_REUSEPORT_LB 481 * set. 482 */ 483 if (opts[opti] != 0 && 484 opts[opti] != SO_REUSEADDR && opti == optj) 485 ATF_REQUIRE(res == BIND_REUSE_SUCCESS); 486 else 487 ATF_REQUIRE(res == BIND_FAILED); 488 489 res = child_bind_unpriv(tc, type, 490 (struct sockaddr *)&ss, opt); 491 /* 492 * Multi-binding is only allowed when both 493 * sockets have the same owner. 494 */ 495 ATF_REQUIRE_MSG(res == BIND_FAILED, 496 "domain %u type %u opts %u:%u: " 497 "result %u (expected %u)", 498 domain, type, opts[opti], opts[optj], 499 res, BIND_FAILED); 500 } 501 ATF_REQUIRE(close(s) == 0); 502 } 503 } 504 } 505 506 /* 507 * Try to bind two sockets to the same address/port tuple. Under some 508 * conditions this is permitted. 509 */ 510 ATF_TC(multibind); 511 ATF_TC_HEAD(multibind, tc) 512 { 513 atf_tc_set_md_var(tc, "require.user", "root"); 514 atf_tc_set_md_var(tc, "require.config", "unprivileged_user"); 515 } 516 ATF_TC_BODY(multibind, tc) 517 { 518 multibind_test(tc, AF_INET, SOCK_STREAM); 519 multibind_test(tc, AF_INET, SOCK_DGRAM); 520 multibind_test(tc, AF_INET6, SOCK_STREAM); 521 multibind_test(tc, AF_INET6, SOCK_DGRAM); 522 } 523 524 /* 525 * Test operation of bind(2) in presence of a connected inpcb using the 526 * same local port. 527 */ 528 static enum bind_res 529 bind_connected_port_test(const atf_tc_t *tc, int domain, int type, bool wild, 530 bool unpriv) 531 { 532 struct sockaddr_in sin; 533 struct sockaddr_in6 sin6; 534 struct sockaddr *sinp; 535 socklen_t slen; 536 int error, ss, cs, as; 537 enum bind_res res; 538 539 /* 540 * Create a connected socket pair. 541 */ 542 ss = socket(domain, type, 0); 543 ATF_REQUIRE_MSG(ss >= 0, "socket failed: %s", strerror(errno)); 544 if (domain == PF_INET) { 545 memset(&sin, 0, sizeof(sin)); 546 sin.sin_family = AF_INET; 547 sin.sin_len = sizeof(sin); 548 sin.sin_addr.s_addr = htonl(INADDR_ANY); 549 sin.sin_port = htons(0); 550 sinp = (struct sockaddr *)&sin; 551 } else { 552 ATF_REQUIRE(domain == PF_INET6); 553 memset(&sin6, 0, sizeof(sin6)); 554 sin6.sin6_family = AF_INET6; 555 sin6.sin6_len = sizeof(sin6); 556 sin6.sin6_addr = in6addr_any; 557 sin6.sin6_port = htons(0); 558 sinp = (struct sockaddr *)&sin6; 559 } 560 561 error = bind(ss, sinp, sinp->sa_len); 562 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 563 564 if (type == SOCK_STREAM) { 565 error = getsockname(ss, sinp, &(socklen_t){ sinp->sa_len }); 566 ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", 567 strerror(errno)); 568 error = listen(ss, 1); 569 ATF_REQUIRE_MSG(error == 0, 570 "listen failed: %s", strerror(errno)); 571 cs = socket(domain, type, 0); 572 ATF_REQUIRE_MSG(cs >= 0, "socket failed: %s", strerror(errno)); 573 if (domain == PF_INET) 574 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 575 else 576 sin6.sin6_addr = in6addr_loopback; 577 error = connect(cs, sinp, sinp->sa_len); 578 ATF_REQUIRE_MSG(error == 0, 579 "connect failed: %s", strerror(errno)); 580 slen = sinp->sa_len; 581 as = accept(ss, sinp, &slen); 582 ATF_REQUIRE_MSG(as >= 0, "accept failed: %s", strerror(errno)); 583 } else { 584 ATF_REQUIRE(type == SOCK_DGRAM); 585 if (domain == PF_INET) { 586 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 587 sin.sin_port = htons(6666); 588 } else { 589 sin6.sin6_addr = in6addr_loopback; 590 sin6.sin6_port = htons(6666); 591 } 592 error = connect(ss, sinp, sinp->sa_len); 593 ATF_REQUIRE_MSG(error == 0, 594 "connect failed: %s", strerror(errno)); 595 error = getsockname(ss, sinp, &(socklen_t){ sinp->sa_len }); 596 ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", 597 strerror(errno)); 598 } 599 600 if (wild) { 601 if (domain == PF_INET) 602 sin.sin_addr.s_addr = htonl(INADDR_ANY); 603 else 604 sin6.sin6_addr = in6addr_any; 605 } 606 607 res = child_bind(tc, type, sinp, SO_REUSEADDR, unpriv); 608 609 if (type == SOCK_STREAM) { 610 ATF_REQUIRE(close(as) == 0); 611 ATF_REQUIRE(close(cs) == 0); 612 } 613 ATF_REQUIRE(close(ss) == 0); 614 615 return (res); 616 } 617 618 /* 619 * Normally bind() prevents port stealing by a different user, even when 620 * SO_REUSE* are specified. However, if the port is bound by a connected 621 * socket, then it's fair game. 622 */ 623 ATF_TC(bind_connected_port); 624 ATF_TC_HEAD(bind_connected_port, tc) 625 { 626 atf_tc_set_md_var(tc, "require.user", "root"); 627 atf_tc_set_md_var(tc, "require.config", "unprivileged_user"); 628 } 629 ATF_TC_BODY(bind_connected_port, tc) 630 { 631 struct bind_connected_port_res { 632 int domain; 633 int type; 634 bool wild; 635 bool unpriv; 636 enum bind_res result; 637 } tests[] = { 638 #define x true 639 #define o false 640 /* W U */ 641 { AF_INET, SOCK_STREAM, x, x, BIND_REUSE_SUCCESS }, 642 { AF_INET, SOCK_STREAM, o, x, BIND_REUSE_SUCCESS }, 643 { AF_INET, SOCK_STREAM, x, o, BIND_REUSE_SUCCESS }, 644 { AF_INET, SOCK_STREAM, o, o, BIND_REUSE_SUCCESS }, 645 { AF_INET6, SOCK_STREAM, x, x, BIND_REUSE_SUCCESS }, 646 { AF_INET6, SOCK_STREAM, o, x, BIND_REUSE_SUCCESS }, 647 { AF_INET6, SOCK_STREAM, x, o, BIND_REUSE_SUCCESS }, 648 { AF_INET6, SOCK_STREAM, o, o, BIND_REUSE_SUCCESS }, 649 { AF_INET, SOCK_DGRAM, x, x, BIND_FAILED }, 650 { AF_INET, SOCK_DGRAM, o, x, BIND_FAILED }, 651 { AF_INET, SOCK_DGRAM, x, o, BIND_REUSE_SUCCESS }, 652 { AF_INET, SOCK_DGRAM, o, o, BIND_REUSE_SUCCESS }, 653 { AF_INET6, SOCK_DGRAM, x, x, BIND_FAILED }, 654 { AF_INET6, SOCK_DGRAM, o, x, BIND_FAILED }, 655 { AF_INET6, SOCK_DGRAM, x, o, BIND_REUSE_SUCCESS }, 656 { AF_INET6, SOCK_DGRAM, o, o, BIND_REUSE_SUCCESS }, 657 #undef x 658 #undef o 659 }; 660 661 for (u_int i = 0; i < nitems(tests); i++) { 662 enum bind_res res; 663 664 res = bind_connected_port_test(tc, tests[i].domain, 665 tests[i].type, tests[i].wild, tests[i].unpriv); 666 ATF_REQUIRE_MSG(res == tests[i].result, "test #%u: " 667 "domain %u type %u%s %sprivileged: result %u (expected %u)", 668 i, tests[i].domain, tests[i].type, 669 tests[i].wild ? " wild" : "", 670 tests[i].unpriv ? "un" : "", 671 res, tests[i].result); 672 } 673 } 674 675 ATF_TP_ADD_TCS(tp) 676 { 677 ATF_TP_ADD_TC(tp, basic); 678 ATF_TP_ADD_TC(tp, bind_zero); 679 ATF_TP_ADD_TC(tp, bind_ok); 680 ATF_TP_ADD_TC(tp, poll_no_rdhup); 681 ATF_TP_ADD_TC(tp, poll_rdhup); 682 ATF_TP_ADD_TC(tp, stream_reconnect); 683 ATF_TP_ADD_TC(tp, bindany); 684 ATF_TP_ADD_TC(tp, multibind); 685 ATF_TP_ADD_TC(tp, bind_connected_port); 686 687 return atf_no_error(); 688 } 689