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 35 #include <errno.h> 36 #include <poll.h> 37 #include <pwd.h> 38 #include <stdio.h> 39 #include <unistd.h> 40 41 #include <atf-c.h> 42 43 ATF_TC_WITHOUT_HEAD(socket_afinet); 44 ATF_TC_BODY(socket_afinet, tc) 45 { 46 int sd; 47 48 sd = socket(PF_INET, SOCK_DGRAM, 0); 49 ATF_CHECK(sd >= 0); 50 51 close(sd); 52 } 53 54 ATF_TC_WITHOUT_HEAD(socket_afinet_bind_zero); 55 ATF_TC_BODY(socket_afinet_bind_zero, tc) 56 { 57 int sd, rc; 58 struct sockaddr_in sin; 59 60 if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false)) 61 atf_tc_skip("doesn't work when mac_portacl(4) loaded (https://bugs.freebsd.org/238781)"); 62 63 sd = socket(PF_INET, SOCK_DGRAM, 0); 64 ATF_CHECK(sd >= 0); 65 66 bzero(&sin, sizeof(sin)); 67 /* 68 * For AF_INET we do not check the family in in_pcbbind_setup(9), 69 * sa_len gets set from the syscall argument in getsockaddr(9), 70 * so we bind to 0:0. 71 */ 72 rc = bind(sd, (struct sockaddr *)&sin, sizeof(sin)); 73 ATF_CHECK_EQ(0, rc); 74 75 close(sd); 76 } 77 78 ATF_TC_WITHOUT_HEAD(socket_afinet_bind_ok); 79 ATF_TC_BODY(socket_afinet_bind_ok, tc) 80 { 81 int sd, rc; 82 struct sockaddr_in sin; 83 84 sd = socket(PF_INET, SOCK_DGRAM, 0); 85 ATF_CHECK(sd >= 0); 86 87 bzero(&sin, sizeof(sin)); 88 sin.sin_family = AF_INET; 89 sin.sin_len = sizeof(sin); 90 sin.sin_port = htons(0); 91 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 92 rc = bind(sd, (struct sockaddr *)&sin, sizeof(sin)); 93 ATF_CHECK_EQ(0, rc); 94 95 close(sd); 96 } 97 98 ATF_TC_WITHOUT_HEAD(socket_afinet_poll_no_rdhup); 99 ATF_TC_BODY(socket_afinet_poll_no_rdhup, tc) 100 { 101 int ss, ss2, cs, rc; 102 struct sockaddr_in sin; 103 socklen_t slen; 104 struct pollfd pfd; 105 int one = 1; 106 107 /* Verify that we don't expose POLLRDHUP if not requested. */ 108 109 /* Server setup. */ 110 ss = socket(PF_INET, SOCK_STREAM, 0); 111 ATF_CHECK(ss >= 0); 112 rc = setsockopt(ss, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); 113 ATF_CHECK_EQ(0, rc); 114 bzero(&sin, sizeof(sin)); 115 sin.sin_family = AF_INET; 116 sin.sin_len = sizeof(sin); 117 sin.sin_port = htons(0); 118 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 119 rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin)); 120 ATF_CHECK_EQ(0, rc); 121 rc = listen(ss, 1); 122 ATF_CHECK_EQ(0, rc); 123 slen = sizeof(sin); 124 rc = getsockname(ss, (struct sockaddr *)&sin, &slen); 125 ATF_CHECK_EQ(0, rc); 126 127 /* Client connects, server accepts. */ 128 cs = socket(PF_INET, SOCK_STREAM, 0); 129 ATF_CHECK(cs >= 0); 130 rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin)); 131 ATF_CHECK_EQ(0, rc); 132 ss2 = accept(ss, NULL, NULL); 133 ATF_CHECK(ss2 >= 0); 134 135 /* Server can write, sees only POLLOUT. */ 136 pfd.fd = ss2; 137 pfd.events = POLLIN | POLLOUT; 138 rc = poll(&pfd, 1, 0); 139 ATF_CHECK_EQ(1, rc); 140 ATF_CHECK_EQ(POLLOUT, pfd.revents); 141 142 /* Client closes socket! */ 143 rc = close(cs); 144 ATF_CHECK_EQ(0, rc); 145 146 /* 147 * Server now sees POLLIN, but not POLLRDHUP because we didn't ask. 148 * Need non-zero timeout to wait for the FIN to arrive and trigger the 149 * socket to become readable. 150 */ 151 pfd.fd = ss2; 152 pfd.events = POLLIN; 153 rc = poll(&pfd, 1, 60000); 154 ATF_CHECK_EQ(1, rc); 155 ATF_CHECK_EQ(POLLIN, pfd.revents); 156 157 close(ss2); 158 close(ss); 159 } 160 161 ATF_TC_WITHOUT_HEAD(socket_afinet_poll_rdhup); 162 ATF_TC_BODY(socket_afinet_poll_rdhup, tc) 163 { 164 int ss, ss2, cs, rc; 165 struct sockaddr_in sin; 166 socklen_t slen; 167 struct pollfd pfd; 168 char buffer; 169 int one = 1; 170 171 /* Verify that server sees POLLRDHUP if it asks for it. */ 172 173 /* Server setup. */ 174 ss = socket(PF_INET, SOCK_STREAM, 0); 175 ATF_CHECK(ss >= 0); 176 rc = setsockopt(ss, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); 177 ATF_CHECK_EQ(0, rc); 178 bzero(&sin, sizeof(sin)); 179 sin.sin_family = AF_INET; 180 sin.sin_len = sizeof(sin); 181 sin.sin_port = htons(0); 182 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 183 rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin)); 184 ATF_CHECK_EQ(0, rc); 185 rc = listen(ss, 1); 186 ATF_CHECK_EQ(0, rc); 187 slen = sizeof(sin); 188 rc = getsockname(ss, (struct sockaddr *)&sin, &slen); 189 ATF_CHECK_EQ(0, rc); 190 191 /* Client connects, server accepts. */ 192 cs = socket(PF_INET, SOCK_STREAM, 0); 193 ATF_CHECK(cs >= 0); 194 rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin)); 195 ATF_CHECK_EQ(0, rc); 196 ss2 = accept(ss, NULL, NULL); 197 ATF_CHECK(ss2 >= 0); 198 199 /* Server can write, so sees POLLOUT. */ 200 pfd.fd = ss2; 201 pfd.events = POLLIN | POLLOUT | POLLRDHUP; 202 rc = poll(&pfd, 1, 0); 203 ATF_CHECK_EQ(1, rc); 204 ATF_CHECK_EQ(POLLOUT, pfd.revents); 205 206 /* Client writes two bytes, server reads only one of them. */ 207 rc = write(cs, "xx", 2); 208 ATF_CHECK_EQ(2, rc); 209 rc = read(ss2, &buffer, 1); 210 ATF_CHECK_EQ(1, rc); 211 212 /* Server can read, so sees POLLIN. */ 213 pfd.fd = ss2; 214 pfd.events = POLLIN | POLLOUT | POLLRDHUP; 215 rc = poll(&pfd, 1, 0); 216 ATF_CHECK_EQ(1, rc); 217 ATF_CHECK_EQ(POLLIN | POLLOUT, pfd.revents); 218 219 /* Client closes socket! */ 220 rc = close(cs); 221 ATF_CHECK_EQ(0, rc); 222 223 /* 224 * Server sees Linux-style POLLRDHUP. Note that this is the case even 225 * though one byte of data remains unread. 226 * 227 * This races against the delivery of FIN caused by the close() above. 228 * Sometimes (more likely when run under truss or if another system 229 * call is added in between) it hits the path where sopoll_generic() 230 * immediately sees SBS_CANTRCVMORE, and sometimes it sleeps with flag 231 * SB_SEL so that it's woken up almost immediately and runs again, 232 * which is why we need a non-zero timeout here. 233 */ 234 pfd.fd = ss2; 235 pfd.events = POLLRDHUP; 236 rc = poll(&pfd, 1, 60000); 237 ATF_CHECK_EQ(1, rc); 238 ATF_CHECK_EQ(POLLRDHUP, pfd.revents); 239 240 close(ss2); 241 close(ss); 242 } 243 244 ATF_TC_WITHOUT_HEAD(socket_afinet_stream_reconnect); 245 ATF_TC_BODY(socket_afinet_stream_reconnect, tc) 246 { 247 struct sockaddr_in sin; 248 socklen_t slen; 249 int ss, cs, rc; 250 251 /* 252 * Make sure that an attempt to connect(2) a connected or disconnected 253 * stream socket fails with EISCONN. 254 */ 255 256 /* Server setup. */ 257 ss = socket(PF_INET, SOCK_STREAM, 0); 258 ATF_CHECK(ss >= 0); 259 bzero(&sin, sizeof(sin)); 260 sin.sin_family = AF_INET; 261 sin.sin_len = sizeof(sin); 262 sin.sin_port = htons(0); 263 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 264 rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin)); 265 ATF_CHECK_EQ(0, rc); 266 rc = listen(ss, 1); 267 ATF_CHECK_EQ(0, rc); 268 slen = sizeof(sin); 269 rc = getsockname(ss, (struct sockaddr *)&sin, &slen); 270 ATF_CHECK_EQ(0, rc); 271 272 /* Client connects, shuts down. */ 273 cs = socket(PF_INET, SOCK_STREAM, 0); 274 ATF_CHECK(cs >= 0); 275 rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin)); 276 ATF_CHECK_EQ(0, rc); 277 rc = shutdown(cs, SHUT_RDWR); 278 ATF_CHECK_EQ(0, rc); 279 280 /* A subsequent connect(2) fails with EISCONN. */ 281 rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin)); 282 ATF_CHECK_EQ(-1, rc); 283 ATF_CHECK_EQ(errno, EISCONN); 284 285 rc = close(cs); 286 ATF_CHECK_EQ(0, rc); 287 rc = close(ss); 288 ATF_CHECK_EQ(0, rc); 289 } 290 291 /* 292 * Make sure that unprivileged users can't set the IP_BINDANY or IPV6_BINDANY 293 * socket options. 294 */ 295 ATF_TC(socket_afinet_bindany); 296 ATF_TC_HEAD(socket_afinet_bindany, tc) 297 { 298 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 299 } 300 ATF_TC_BODY(socket_afinet_bindany, tc) 301 { 302 int s; 303 304 s = socket(AF_INET, SOCK_STREAM, 0); 305 ATF_REQUIRE(s >= 0); 306 ATF_REQUIRE_ERRNO(EPERM, 307 setsockopt(s, IPPROTO_IP, IP_BINDANY, &(int){1}, sizeof(int)) == 308 -1); 309 ATF_REQUIRE(close(s) == 0); 310 311 s = socket(AF_INET, SOCK_DGRAM, 0); 312 ATF_REQUIRE(s >= 0); 313 ATF_REQUIRE_ERRNO(EPERM, 314 setsockopt(s, IPPROTO_IP, IP_BINDANY, &(int){1}, sizeof(int)) == 315 -1); 316 ATF_REQUIRE(close(s) == 0); 317 318 s = socket(AF_INET6, SOCK_STREAM, 0); 319 ATF_REQUIRE(s >= 0); 320 ATF_REQUIRE_ERRNO(EPERM, 321 setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY, &(int){1}, sizeof(int)) == 322 -1); 323 ATF_REQUIRE(close(s) == 0); 324 325 s = socket(AF_INET6, SOCK_DGRAM, 0); 326 ATF_REQUIRE(s >= 0); 327 ATF_REQUIRE_ERRNO(EPERM, 328 setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY, &(int){1}, sizeof(int)) == 329 -1); 330 ATF_REQUIRE(close(s) == 0); 331 } 332 333 /* 334 * Bind a socket to the specified address, optionally dropping privileges and 335 * setting one of the SO_REUSE* options first. 336 * 337 * Returns true if the bind succeeded, and false if it failed with EADDRINUSE. 338 */ 339 static bool 340 child_bind(const atf_tc_t *tc, int type, struct sockaddr *sa, int opt, bool unpriv) 341 { 342 const char *user; 343 pid_t child; 344 345 if (unpriv) { 346 if (!atf_tc_has_config_var(tc, "unprivileged_user")) 347 atf_tc_skip("unprivileged_user not set"); 348 user = atf_tc_get_config_var(tc, "unprivileged_user"); 349 } else { 350 user = NULL; 351 } 352 353 child = fork(); 354 ATF_REQUIRE(child != -1); 355 if (child == 0) { 356 int s; 357 358 if (user != NULL) { 359 struct passwd *passwd; 360 361 passwd = getpwnam(user); 362 if (seteuid(passwd->pw_uid) != 0) 363 _exit(1); 364 } 365 366 s = socket(sa->sa_family, type, 0); 367 if (s < 0) 368 _exit(2); 369 if (bind(s, sa, sa->sa_len) == 0) 370 _exit(3); 371 if (errno != EADDRINUSE) 372 _exit(4); 373 if (opt != 0) { 374 if (setsockopt(s, SOL_SOCKET, opt, &(int){1}, 375 sizeof(int)) != 0) 376 _exit(5); 377 } 378 if (bind(s, sa, sa->sa_len) == 0) 379 _exit(6); 380 if (errno != EADDRINUSE) 381 _exit(7); 382 _exit(0); 383 } else { 384 int status; 385 386 ATF_REQUIRE_EQ(waitpid(child, &status, 0), child); 387 ATF_REQUIRE(WIFEXITED(status)); 388 status = WEXITSTATUS(status); 389 ATF_REQUIRE_MSG(status == 0 || status == 6, 390 "child exited with %d", status); 391 return (status == 6); 392 } 393 } 394 395 static bool 396 child_bind_priv(const atf_tc_t *tc, int type, struct sockaddr *sa, int opt) 397 { 398 return (child_bind(tc, type, sa, opt, false)); 399 } 400 401 static bool 402 child_bind_unpriv(const atf_tc_t *tc, int type, struct sockaddr *sa, int opt) 403 { 404 return (child_bind(tc, type, sa, opt, true)); 405 } 406 407 static int 408 bind_socket(int domain, int type, int opt, bool unspec, struct sockaddr *sa) 409 { 410 socklen_t slen; 411 int s; 412 413 s = socket(domain, type, 0); 414 ATF_REQUIRE(s >= 0); 415 416 if (domain == AF_INET) { 417 struct sockaddr_in sin; 418 419 bzero(&sin, sizeof(sin)); 420 sin.sin_family = AF_INET; 421 sin.sin_len = sizeof(sin); 422 sin.sin_addr.s_addr = htonl(unspec ? 423 INADDR_ANY : INADDR_LOOPBACK); 424 sin.sin_port = htons(0); 425 ATF_REQUIRE(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0); 426 427 slen = sizeof(sin); 428 } else /* if (domain == AF_INET6) */ { 429 struct sockaddr_in6 sin6; 430 431 bzero(&sin6, sizeof(sin6)); 432 sin6.sin6_family = AF_INET6; 433 sin6.sin6_len = sizeof(sin6); 434 sin6.sin6_addr = unspec ? in6addr_any : in6addr_loopback; 435 sin6.sin6_port = htons(0); 436 ATF_REQUIRE(bind(s, (struct sockaddr *)&sin6, sizeof(sin6)) == 0); 437 438 slen = sizeof(sin6); 439 } 440 441 if (opt != 0) { 442 ATF_REQUIRE(setsockopt(s, SOL_SOCKET, opt, &(int){1}, 443 sizeof(int)) == 0); 444 } 445 446 ATF_REQUIRE(getsockname(s, sa, &slen) == 0); 447 448 return (s); 449 } 450 451 static void 452 multibind_test(const atf_tc_t *tc, int domain, int type) 453 { 454 struct sockaddr_storage ss; 455 int opts[4] = { 0, SO_REUSEADDR, SO_REUSEPORT, SO_REUSEPORT_LB }; 456 int s; 457 bool flags[2] = { false, true }; 458 bool res; 459 460 for (size_t flagi = 0; flagi < nitems(flags); flagi++) { 461 for (size_t opti = 0; opti < nitems(opts); opti++) { 462 s = bind_socket(domain, type, opts[opti], flags[flagi], 463 (struct sockaddr *)&ss); 464 for (size_t optj = 0; optj < nitems(opts); optj++) { 465 int opt; 466 467 opt = opts[optj]; 468 res = child_bind_priv(tc, type, 469 (struct sockaddr *)&ss, opt); 470 /* 471 * Multi-binding is only allowed when both 472 * sockets have SO_REUSEPORT or SO_REUSEPORT_LB 473 * set. 474 */ 475 if (opts[opti] != 0 && 476 opts[opti] != SO_REUSEADDR && opti == optj) 477 ATF_REQUIRE(res); 478 else 479 ATF_REQUIRE(!res); 480 481 res = child_bind_unpriv(tc, type, 482 (struct sockaddr *)&ss, opt); 483 /* 484 * Multi-binding is only allowed when both 485 * sockets have the same owner. 486 * 487 * XXX-MJ we for some reason permit this when 488 * binding to the unspecified address, but I 489 * don't think that's right 490 */ 491 if (flags[flagi] && opts[opti] != 0 && 492 opts[opti] != SO_REUSEADDR && opti == optj) 493 ATF_REQUIRE(res); 494 else 495 ATF_REQUIRE(!res); 496 } 497 ATF_REQUIRE(close(s) == 0); 498 } 499 } 500 } 501 502 /* 503 * Try to bind two sockets to the same address/port tuple. Under some 504 * conditions this is permitted. 505 */ 506 ATF_TC(socket_afinet_multibind); 507 ATF_TC_HEAD(socket_afinet_multibind, tc) 508 { 509 atf_tc_set_md_var(tc, "require.user", "root"); 510 atf_tc_set_md_var(tc, "require.config", "unprivileged_user"); 511 } 512 ATF_TC_BODY(socket_afinet_multibind, tc) 513 { 514 multibind_test(tc, AF_INET, SOCK_STREAM); 515 multibind_test(tc, AF_INET, SOCK_DGRAM); 516 multibind_test(tc, AF_INET6, SOCK_STREAM); 517 multibind_test(tc, AF_INET6, SOCK_DGRAM); 518 } 519 520 ATF_TP_ADD_TCS(tp) 521 { 522 ATF_TP_ADD_TC(tp, socket_afinet); 523 ATF_TP_ADD_TC(tp, socket_afinet_bind_zero); 524 ATF_TP_ADD_TC(tp, socket_afinet_bind_ok); 525 ATF_TP_ADD_TC(tp, socket_afinet_poll_no_rdhup); 526 ATF_TP_ADD_TC(tp, socket_afinet_poll_rdhup); 527 ATF_TP_ADD_TC(tp, socket_afinet_stream_reconnect); 528 ATF_TP_ADD_TC(tp, socket_afinet_bindany); 529 ATF_TP_ADD_TC(tp, socket_afinet_multibind); 530 531 return atf_no_error(); 532 } 533