1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2025 Gleb Smirnoff <glebius@FreeBSD.org> 5 * Copyright (c) 2018 Alan Somers 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 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 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/cdefs.h> 30 #include <sys/socket.h> 31 #include <sys/event.h> 32 #include <sys/select.h> 33 #include <sys/sysctl.h> 34 #include <sys/time.h> 35 #include <sys/un.h> 36 #include <errno.h> 37 #include <fcntl.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <poll.h> 41 #include <pthread.h> 42 #include <pthread_np.h> 43 44 #include <atf-c.h> 45 46 static void 47 do_socketpair(int *sv) 48 { 49 int s; 50 51 s = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv); 52 ATF_REQUIRE_EQ(0, s); 53 ATF_REQUIRE(sv[0] >= 0); 54 ATF_REQUIRE(sv[1] >= 0); 55 ATF_REQUIRE(sv[0] != sv[1]); 56 } 57 58 static u_long 59 getsendspace(void) 60 { 61 u_long sendspace; 62 63 ATF_REQUIRE_MSG(sysctlbyname("net.local.stream.sendspace", &sendspace, 64 &(size_t){sizeof(u_long)}, NULL, 0) != -1, 65 "sysctl net.local.stream.sendspace failed: %s", strerror(errno)); 66 67 return (sendspace); 68 } 69 70 /* getpeereid(3) should work with stream sockets created via socketpair(2) */ 71 ATF_TC_WITHOUT_HEAD(getpeereid); 72 ATF_TC_BODY(getpeereid, tc) 73 { 74 int sv[2]; 75 uid_t real_euid, euid; 76 gid_t real_egid, egid; 77 78 real_euid = geteuid(); 79 real_egid = getegid(); 80 81 do_socketpair(sv); 82 83 ATF_REQUIRE_EQ(0, getpeereid(sv[0], &euid, &egid)); 84 ATF_CHECK_EQ(real_euid, euid); 85 ATF_CHECK_EQ(real_egid, egid); 86 87 ATF_REQUIRE_EQ(0, getpeereid(sv[1], &euid, &egid)); 88 ATF_CHECK_EQ(real_euid, euid); 89 ATF_CHECK_EQ(real_egid, egid); 90 91 close(sv[0]); 92 close(sv[1]); 93 } 94 95 /* Sending zero bytes should succeed (once regressed in aba79b0f4a3f). */ 96 ATF_TC_WITHOUT_HEAD(send_0); 97 ATF_TC_BODY(send_0, tc) 98 { 99 int sv[2]; 100 101 do_socketpair(sv); 102 ATF_REQUIRE(send(sv[0], sv, 0, 0) == 0); 103 close(sv[0]); 104 close(sv[1]); 105 } 106 107 struct check_ctx; 108 typedef void check_func_t(struct check_ctx *); 109 struct check_ctx { 110 check_func_t *method; 111 int sv[2]; 112 bool timeout; 113 union { 114 enum { SELECT_RD, SELECT_WR } select_what; 115 short poll_events; 116 short kev_filter; 117 }; 118 int nfds; 119 union { 120 short poll_revents; 121 unsigned short kev_flags; 122 }; 123 }; 124 125 static void 126 check_select(struct check_ctx *ctx) 127 { 128 fd_set fds; 129 int nfds; 130 131 FD_ZERO(&fds); 132 FD_SET(ctx->sv[0], &fds); 133 nfds = select(ctx->sv[0] + 1, 134 ctx->select_what == SELECT_RD ? &fds : NULL, 135 ctx->select_what == SELECT_WR ? &fds : NULL, 136 NULL, 137 ctx->timeout ? &(struct timeval){.tv_usec = 1000} : NULL); 138 ATF_REQUIRE_MSG(nfds == ctx->nfds, 139 "select() returns %d errno %d", nfds, errno); 140 } 141 142 static void 143 check_poll(struct check_ctx *ctx) 144 { 145 struct pollfd pfd[1]; 146 int nfds; 147 148 pfd[0] = (struct pollfd){ 149 .fd = ctx->sv[0], 150 .events = ctx->poll_events, 151 }; 152 nfds = poll(pfd, 1, ctx->timeout ? 1 : INFTIM); 153 ATF_REQUIRE_MSG(nfds == ctx->nfds, 154 "poll() returns %d errno %d", nfds, errno); 155 ATF_REQUIRE((pfd[0].revents & ctx->poll_revents) == ctx->poll_revents); 156 } 157 158 static void 159 check_kevent(struct check_ctx *ctx) 160 { 161 struct kevent kev; 162 int nfds, kq; 163 164 ATF_REQUIRE(kq = kqueue()); 165 EV_SET(&kev, ctx->sv[0], ctx->kev_filter, EV_ADD, 0, 0, NULL); 166 nfds = kevent(kq, &kev, 1, NULL, 0, NULL); 167 ATF_REQUIRE_MSG(nfds == 0, 168 "kevent() returns %d errno %d", nfds, errno); 169 nfds = kevent(kq, NULL, 0, &kev, 1, ctx->timeout ? 170 &(struct timespec){.tv_nsec = 1000000} : NULL); 171 ATF_REQUIRE_MSG(nfds == ctx->nfds, 172 "kevent() returns %d errno %d", nfds, errno); 173 ATF_REQUIRE(kev.ident == (uintptr_t)ctx->sv[0] && 174 kev.filter == ctx->kev_filter && 175 (kev.flags & ctx->kev_flags) == ctx->kev_flags); 176 close(kq); 177 } 178 179 static void 180 full_socketpair(int *sv) 181 { 182 void *buf; 183 u_long sendspace; 184 185 sendspace = getsendspace(); 186 ATF_REQUIRE((buf = malloc(sendspace)) != NULL); 187 do_socketpair(sv); 188 ATF_REQUIRE(fcntl(sv[0], F_SETFL, O_NONBLOCK) != -1); 189 do {} while (send(sv[0], buf, sendspace, 0) == (ssize_t)sendspace); 190 ATF_REQUIRE(errno == EAGAIN); 191 ATF_REQUIRE(fcntl(sv[0], F_SETFL, 0) != -1); 192 free(buf); 193 } 194 195 static void * 196 pthread_wrap(void *arg) 197 { 198 struct check_ctx *ctx = arg; 199 200 ctx->method(ctx); 201 202 return (NULL); 203 } 204 205 /* 206 * Launch a thread that would block in event mech and return it. 207 */ 208 static pthread_t 209 pthread_create_blocked(struct check_ctx *ctx) 210 { 211 pthread_t thr; 212 213 ctx->timeout = false; 214 ctx->nfds = 1; 215 ATF_REQUIRE(pthread_create(&thr, NULL, pthread_wrap, ctx) == 0); 216 217 /* Sleep a bit to make sure that thread is put to sleep. */ 218 usleep(10000); 219 ATF_REQUIRE(pthread_peekjoin_np(thr, NULL) == EBUSY); 220 221 return (thr); 222 } 223 224 static void 225 full_writability_check(struct check_ctx *ctx) 226 { 227 pthread_t thr; 228 void *buf; 229 u_long space; 230 231 space = getsendspace() / 2; 232 ATF_REQUIRE((buf = malloc(space)) != NULL); 233 234 /* First check with timeout, expecting 0 fds returned. */ 235 ctx->timeout = true; 236 ctx->nfds = 0; 237 ctx->method(ctx); 238 239 thr = pthread_create_blocked(ctx); 240 241 /* Read some data and re-check, the fd is expected to be returned. */ 242 ATF_REQUIRE(read(ctx->sv[1], buf, space) == (ssize_t)space); 243 244 /* Now check that thread was successfully woken up and exited. */ 245 ATF_REQUIRE(pthread_join(thr, NULL) == 0); 246 247 /* Extra check repeating what joined thread already did. */ 248 ctx->method(ctx); 249 250 close(ctx->sv[0]); 251 close(ctx->sv[1]); 252 free(buf); 253 } 254 255 /* 256 * Make sure that a full socket is not reported as writable by event APIs. 257 */ 258 ATF_TC_WITHOUT_HEAD(full_writability_select); 259 ATF_TC_BODY(full_writability_select, tc) 260 { 261 struct check_ctx ctx = { 262 .method = check_select, 263 .select_what = SELECT_WR, 264 }; 265 266 full_socketpair(ctx.sv); 267 full_writability_check(&ctx); 268 close(ctx.sv[0]); 269 close(ctx.sv[1]); 270 } 271 272 ATF_TC_WITHOUT_HEAD(full_writability_poll); 273 ATF_TC_BODY(full_writability_poll, tc) 274 { 275 struct check_ctx ctx = { 276 .method = check_poll, 277 .poll_events = POLLOUT | POLLWRNORM, 278 }; 279 280 full_socketpair(ctx.sv); 281 full_writability_check(&ctx); 282 close(ctx.sv[0]); 283 close(ctx.sv[1]); 284 } 285 286 ATF_TC_WITHOUT_HEAD(full_writability_kevent); 287 ATF_TC_BODY(full_writability_kevent, tc) 288 { 289 struct check_ctx ctx = { 290 .method = check_kevent, 291 .kev_filter = EVFILT_WRITE, 292 }; 293 294 full_socketpair(ctx.sv); 295 full_writability_check(&ctx); 296 close(ctx.sv[0]); 297 close(ctx.sv[1]); 298 } 299 300 ATF_TC_WITHOUT_HEAD(connected_writability); 301 ATF_TC_BODY(connected_writability, tc) 302 { 303 struct check_ctx ctx = { 304 .timeout = true, 305 .nfds = 1, 306 }; 307 308 do_socketpair(ctx.sv); 309 310 ctx.select_what = SELECT_WR; 311 check_select(&ctx); 312 ctx.poll_events = POLLOUT | POLLWRNORM; 313 check_poll(&ctx); 314 ctx.kev_filter = EVFILT_WRITE; 315 check_kevent(&ctx); 316 317 close(ctx.sv[0]); 318 close(ctx.sv[1]); 319 } 320 321 ATF_TC_WITHOUT_HEAD(unconnected_writability); 322 ATF_TC_BODY(unconnected_writability, tc) 323 { 324 struct check_ctx ctx = { 325 .timeout = true, 326 .nfds = 0, 327 }; 328 329 ATF_REQUIRE((ctx.sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0); 330 331 ctx.select_what = SELECT_WR; 332 check_select(&ctx); 333 ctx.poll_events = POLLOUT | POLLWRNORM; 334 check_poll(&ctx); 335 ctx.kev_filter = EVFILT_WRITE; 336 check_kevent(&ctx); 337 338 close(ctx.sv[0]); 339 } 340 341 ATF_TC_WITHOUT_HEAD(peerclosed_writability); 342 ATF_TC_BODY(peerclosed_writability, tc) 343 { 344 struct check_ctx ctx = { 345 .timeout = false, 346 .nfds = 1, 347 }; 348 349 do_socketpair(ctx.sv); 350 close(ctx.sv[1]); 351 352 ctx.select_what = SELECT_WR; 353 check_select(&ctx); 354 ctx.poll_events = POLLOUT | POLLWRNORM; 355 check_poll(&ctx); 356 ctx.kev_filter = EVFILT_WRITE; 357 ctx.kev_flags = EV_EOF; 358 check_kevent(&ctx); 359 360 close(ctx.sv[0]); 361 } 362 363 ATF_TC_WITHOUT_HEAD(peershutdown_writability); 364 ATF_TC_BODY(peershutdown_writability, tc) 365 { 366 struct check_ctx ctx = { 367 .timeout = false, 368 .nfds = 1, 369 }; 370 371 do_socketpair(ctx.sv); 372 shutdown(ctx.sv[1], SHUT_RD); 373 374 ctx.select_what = SELECT_WR; 375 check_select(&ctx); 376 ctx.poll_events = POLLOUT | POLLWRNORM; 377 check_poll(&ctx); 378 /* 379 * XXXGL: historically unix(4) sockets were not reporting peer's 380 * shutdown(SHUT_RD) as our EV_EOF. The kevent(2) manual page says 381 * "filter will set EV_EOF when the reader disconnects", which is hard 382 * to interpret unambigously. For now leave the historic behavior, 383 * but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(), 384 * and then this test will also expect EV_EOF in returned flags. 385 */ 386 ctx.kev_filter = EVFILT_WRITE; 387 check_kevent(&ctx); 388 389 close(ctx.sv[0]); 390 close(ctx.sv[1]); 391 } 392 393 ATF_TC_WITHOUT_HEAD(peershutdown_readability); 394 ATF_TC_BODY(peershutdown_readability, tc) 395 { 396 struct check_ctx ctx = { 397 .timeout = false, 398 .nfds = 1, 399 }; 400 ssize_t readsz; 401 char c; 402 403 do_socketpair(ctx.sv); 404 shutdown(ctx.sv[1], SHUT_WR); 405 406 /* 407 * The other side should flag as readable in select(2) to allow it to 408 * read(2) and observe EOF. Ensure that both poll(2) and select(2) 409 * are consistent here. 410 */ 411 ctx.select_what = SELECT_RD; 412 check_select(&ctx); 413 ctx.poll_events = POLLIN | POLLRDNORM; 414 check_poll(&ctx); 415 416 /* 417 * Also check that read doesn't block. 418 */ 419 readsz = read(ctx.sv[0], &c, sizeof(c)); 420 ATF_REQUIRE_INTEQ(0, readsz); 421 422 close(ctx.sv[0]); 423 close(ctx.sv[1]); 424 } 425 426 static void 427 peershutdown_wakeup(struct check_ctx *ctx) 428 { 429 pthread_t thr; 430 431 ctx->timeout = false; 432 ctx->nfds = 1; 433 434 do_socketpair(ctx->sv); 435 thr = pthread_create_blocked(ctx); 436 shutdown(ctx->sv[1], SHUT_WR); 437 ATF_REQUIRE(pthread_join(thr, NULL) == 0); 438 439 close(ctx->sv[0]); 440 close(ctx->sv[1]); 441 } 442 443 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_select); 444 ATF_TC_BODY(peershutdown_wakeup_select, tc) 445 { 446 peershutdown_wakeup(&(struct check_ctx){ 447 .method = check_select, 448 .select_what = SELECT_RD, 449 }); 450 } 451 452 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_poll); 453 ATF_TC_BODY(peershutdown_wakeup_poll, tc) 454 { 455 peershutdown_wakeup(&(struct check_ctx){ 456 .method = check_poll, 457 .poll_events = POLLIN | POLLRDNORM | POLLRDHUP, 458 .poll_revents = POLLRDHUP, 459 }); 460 } 461 462 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_kevent); 463 ATF_TC_BODY(peershutdown_wakeup_kevent, tc) 464 { 465 peershutdown_wakeup(&(struct check_ctx){ 466 .method = check_kevent, 467 .kev_filter = EVFILT_READ, 468 .kev_flags = EV_EOF, 469 }); 470 } 471 472 ATF_TC_WITHOUT_HEAD(ourshutdown_kevent); 473 ATF_TC_BODY(ourshutdown_kevent, tc) 474 { 475 struct kevent kev; 476 int sv[2], kq; 477 478 do_socketpair(sv); 479 ATF_REQUIRE(kq = kqueue()); 480 481 EV_SET(&kev, sv[1], EVFILT_WRITE, EV_ADD, 0, 0, NULL); 482 ATF_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0); 483 484 ATF_REQUIRE(shutdown(sv[1], SHUT_WR) == 0); 485 486 ATF_REQUIRE(kevent(kq, NULL, 0, &kev, 1, NULL) == 1); 487 ATF_REQUIRE(kev.ident == (uintptr_t)sv[1] && 488 kev.filter == EVFILT_WRITE && 489 kev.flags == EV_EOF); 490 491 close(sv[0]); 492 close(sv[1]); 493 } 494 495 ATF_TC_WITHOUT_HEAD(SO_SNDTIMEO); 496 ATF_TC_BODY(SO_SNDTIMEO, tc) 497 { 498 struct timespec tp1, tp2, rtp, sleep = { .tv_nsec = 100000000 }; 499 int sv[2]; 500 char buf[10]; 501 502 full_socketpair(sv); 503 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDTIMEO, 504 &(struct timeval){ .tv_usec = sleep.tv_nsec / 1000 }, 505 sizeof(struct timeval))); 506 ATF_REQUIRE_EQ(0, clock_gettime(CLOCK_MONOTONIC_PRECISE, &tp1)); 507 ATF_REQUIRE_EQ(-1, send(sv[0], buf, sizeof(buf), 0)); 508 ATF_REQUIRE(errno == EAGAIN); 509 ATF_REQUIRE_EQ(0, clock_gettime(CLOCK_MONOTONIC_PRECISE, &tp2)); 510 timespecsub(&tp2, &tp1, &rtp); 511 ATF_REQUIRE(timespeccmp(&rtp, &sleep, >=)); 512 ATF_REQUIRE_EQ(sizeof(buf), recv(sv[1], buf, sizeof(buf), 0)); 513 ATF_REQUIRE_EQ(sizeof(buf), send(sv[0], buf, sizeof(buf), 0)); 514 515 close(sv[0]); 516 close(sv[1]); 517 } 518 519 ATF_TP_ADD_TCS(tp) 520 { 521 ATF_TP_ADD_TC(tp, getpeereid); 522 ATF_TP_ADD_TC(tp, send_0); 523 ATF_TP_ADD_TC(tp, connected_writability); 524 ATF_TP_ADD_TC(tp, unconnected_writability); 525 ATF_TP_ADD_TC(tp, full_writability_select); 526 ATF_TP_ADD_TC(tp, full_writability_poll); 527 ATF_TP_ADD_TC(tp, full_writability_kevent); 528 ATF_TP_ADD_TC(tp, peerclosed_writability); 529 ATF_TP_ADD_TC(tp, peershutdown_writability); 530 ATF_TP_ADD_TC(tp, peershutdown_readability); 531 ATF_TP_ADD_TC(tp, peershutdown_wakeup_select); 532 ATF_TP_ADD_TC(tp, peershutdown_wakeup_poll); 533 ATF_TP_ADD_TC(tp, peershutdown_wakeup_kevent); 534 ATF_TP_ADD_TC(tp, ourshutdown_kevent); 535 ATF_TP_ADD_TC(tp, SO_SNDTIMEO); 536 537 return atf_no_error(); 538 } 539