1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2018 Alan Somers 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 #include <sys/socket.h> 30 #include <sys/event.h> 31 #include <sys/select.h> 32 #include <sys/sysctl.h> 33 #include <sys/un.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <poll.h> 39 #include <pthread.h> 40 #include <pthread_np.h> 41 42 #include <atf-c.h> 43 44 static void 45 do_socketpair(int *sv) 46 { 47 int s; 48 49 s = socketpair(PF_LOCAL, SOCK_STREAM, 0, sv); 50 ATF_REQUIRE_EQ(0, s); 51 ATF_REQUIRE(sv[0] >= 0); 52 ATF_REQUIRE(sv[1] >= 0); 53 ATF_REQUIRE(sv[0] != sv[1]); 54 } 55 56 static u_long 57 getsendspace(void) 58 { 59 u_long sendspace; 60 61 ATF_REQUIRE_MSG(sysctlbyname("net.local.stream.sendspace", &sendspace, 62 &(size_t){sizeof(u_long)}, NULL, 0) != -1, 63 "sysctl net.local.stream.sendspace failed: %s", strerror(errno)); 64 65 return (sendspace); 66 } 67 68 /* getpeereid(3) should work with stream sockets created via socketpair(2) */ 69 ATF_TC_WITHOUT_HEAD(getpeereid); 70 ATF_TC_BODY(getpeereid, tc) 71 { 72 int sv[2]; 73 uid_t real_euid, euid; 74 gid_t real_egid, egid; 75 76 real_euid = geteuid(); 77 real_egid = getegid(); 78 79 do_socketpair(sv); 80 81 ATF_REQUIRE_EQ(0, getpeereid(sv[0], &euid, &egid)); 82 ATF_CHECK_EQ(real_euid, euid); 83 ATF_CHECK_EQ(real_egid, egid); 84 85 ATF_REQUIRE_EQ(0, getpeereid(sv[1], &euid, &egid)); 86 ATF_CHECK_EQ(real_euid, euid); 87 ATF_CHECK_EQ(real_egid, egid); 88 89 close(sv[0]); 90 close(sv[1]); 91 } 92 93 /* Sending zero bytes should succeed (once regressed in aba79b0f4a3f). */ 94 ATF_TC_WITHOUT_HEAD(send_0); 95 ATF_TC_BODY(send_0, tc) 96 { 97 int sv[2]; 98 99 do_socketpair(sv); 100 ATF_REQUIRE(send(sv[0], sv, 0, 0) == 0); 101 close(sv[0]); 102 close(sv[1]); 103 } 104 105 struct check_ctx; 106 typedef void check_func_t(struct check_ctx *); 107 struct check_ctx { 108 check_func_t *method; 109 int sv[2]; 110 bool timeout; 111 union { 112 enum { SELECT_RD, SELECT_WR } select_what; 113 short poll_events; 114 short kev_filter; 115 }; 116 int nfds; 117 union { 118 short poll_revents; 119 unsigned short kev_flags; 120 }; 121 }; 122 123 static void 124 check_select(struct check_ctx *ctx) 125 { 126 fd_set fds; 127 int nfds; 128 129 FD_ZERO(&fds); 130 FD_SET(ctx->sv[0], &fds); 131 nfds = select(ctx->sv[0] + 1, 132 ctx->select_what == SELECT_RD ? &fds : NULL, 133 ctx->select_what == SELECT_WR ? &fds : NULL, 134 NULL, 135 ctx->timeout ? &(struct timeval){.tv_usec = 1000} : NULL); 136 ATF_REQUIRE_MSG(nfds == ctx->nfds, 137 "select() returns %d errno %d", nfds, errno); 138 } 139 140 static void 141 check_poll(struct check_ctx *ctx) 142 { 143 struct pollfd pfd[1]; 144 int nfds; 145 146 pfd[0] = (struct pollfd){ 147 .fd = ctx->sv[0], 148 .events = ctx->poll_events, 149 }; 150 nfds = poll(pfd, 1, ctx->timeout ? 1 : INFTIM); 151 ATF_REQUIRE_MSG(nfds == ctx->nfds, 152 "poll() returns %d errno %d", nfds, errno); 153 ATF_REQUIRE((pfd[0].revents & ctx->poll_revents) == ctx->poll_revents); 154 } 155 156 static void 157 check_kevent(struct check_ctx *ctx) 158 { 159 struct kevent kev; 160 int nfds, kq; 161 162 ATF_REQUIRE(kq = kqueue()); 163 EV_SET(&kev, ctx->sv[0], ctx->kev_filter, EV_ADD, 0, 0, NULL); 164 nfds = kevent(kq, &kev, 1, NULL, 0, NULL); 165 ATF_REQUIRE_MSG(nfds == 0, 166 "kevent() returns %d errno %d", nfds, errno); 167 nfds = kevent(kq, NULL, 0, &kev, 1, ctx->timeout ? 168 &(struct timespec){.tv_nsec = 1000000} : NULL); 169 ATF_REQUIRE_MSG(nfds == ctx->nfds, 170 "kevent() returns %d errno %d", nfds, errno); 171 ATF_REQUIRE(kev.ident == (uintptr_t)ctx->sv[0] && 172 kev.filter == ctx->kev_filter && 173 (kev.flags & ctx->kev_flags) == ctx->kev_flags); 174 close(kq); 175 } 176 177 static void 178 full_socketpair(int *sv) 179 { 180 void *buf; 181 u_long sendspace; 182 183 sendspace = getsendspace(); 184 ATF_REQUIRE((buf = malloc(sendspace)) != NULL); 185 do_socketpair(sv); 186 ATF_REQUIRE(fcntl(sv[0], F_SETFL, O_NONBLOCK) != -1); 187 do {} while (send(sv[0], buf, sendspace, 0) == (ssize_t)sendspace); 188 ATF_REQUIRE(errno == EAGAIN); 189 ATF_REQUIRE(fcntl(sv[0], F_SETFL, 0) != -1); 190 free(buf); 191 } 192 193 static void * 194 pthread_wrap(void *arg) 195 { 196 struct check_ctx *ctx = arg; 197 198 ctx->method(ctx); 199 200 return (NULL); 201 } 202 203 /* 204 * Launch a thread that would block in event mech and return it. 205 */ 206 static pthread_t 207 pthread_create_blocked(struct check_ctx *ctx) 208 { 209 pthread_t thr; 210 211 ctx->timeout = false; 212 ctx->nfds = 1; 213 ATF_REQUIRE(pthread_create(&thr, NULL, pthread_wrap, ctx) == 0); 214 215 /* Sleep a bit to make sure that thread is put to sleep. */ 216 usleep(10000); 217 ATF_REQUIRE(pthread_peekjoin_np(thr, NULL) == EBUSY); 218 219 return (thr); 220 } 221 222 static void 223 full_writability_check(struct check_ctx *ctx) 224 { 225 pthread_t thr; 226 void *buf; 227 u_long space; 228 229 space = getsendspace() / 2; 230 ATF_REQUIRE((buf = malloc(space)) != NULL); 231 232 /* First check with timeout, expecting 0 fds returned. */ 233 ctx->timeout = true; 234 ctx->nfds = 0; 235 ctx->method(ctx); 236 237 thr = pthread_create_blocked(ctx); 238 239 /* Read some data and re-check, the fd is expected to be returned. */ 240 ATF_REQUIRE(read(ctx->sv[1], buf, space) == (ssize_t)space); 241 242 /* Now check that thread was successfully woken up and exited. */ 243 ATF_REQUIRE(pthread_join(thr, NULL) == 0); 244 245 /* Extra check repeating what joined thread already did. */ 246 ctx->method(ctx); 247 248 close(ctx->sv[0]); 249 close(ctx->sv[1]); 250 free(buf); 251 } 252 253 /* 254 * Make sure that a full socket is not reported as writable by event APIs. 255 */ 256 ATF_TC_WITHOUT_HEAD(full_writability_select); 257 ATF_TC_BODY(full_writability_select, tc) 258 { 259 struct check_ctx ctx = { 260 .method = check_select, 261 .select_what = SELECT_WR, 262 }; 263 264 full_socketpair(ctx.sv); 265 full_writability_check(&ctx); 266 close(ctx.sv[0]); 267 close(ctx.sv[1]); 268 } 269 270 ATF_TC_WITHOUT_HEAD(full_writability_poll); 271 ATF_TC_BODY(full_writability_poll, tc) 272 { 273 struct check_ctx ctx = { 274 .method = check_poll, 275 .poll_events = POLLOUT | POLLWRNORM, 276 }; 277 278 full_socketpair(ctx.sv); 279 full_writability_check(&ctx); 280 close(ctx.sv[0]); 281 close(ctx.sv[1]); 282 } 283 284 ATF_TC_WITHOUT_HEAD(full_writability_kevent); 285 ATF_TC_BODY(full_writability_kevent, tc) 286 { 287 struct check_ctx ctx = { 288 .method = check_kevent, 289 .kev_filter = EVFILT_WRITE, 290 }; 291 292 full_socketpair(ctx.sv); 293 full_writability_check(&ctx); 294 close(ctx.sv[0]); 295 close(ctx.sv[1]); 296 } 297 298 ATF_TC_WITHOUT_HEAD(connected_writability); 299 ATF_TC_BODY(connected_writability, tc) 300 { 301 struct check_ctx ctx = { 302 .timeout = true, 303 .nfds = 1, 304 }; 305 306 do_socketpair(ctx.sv); 307 308 ctx.select_what = SELECT_WR; 309 check_select(&ctx); 310 ctx.poll_events = POLLOUT | POLLWRNORM; 311 check_poll(&ctx); 312 ctx.kev_filter = EVFILT_WRITE; 313 check_kevent(&ctx); 314 315 close(ctx.sv[0]); 316 close(ctx.sv[1]); 317 } 318 319 ATF_TC_WITHOUT_HEAD(unconnected_writability); 320 ATF_TC_BODY(unconnected_writability, tc) 321 { 322 struct check_ctx ctx = { 323 .timeout = true, 324 .nfds = 0, 325 }; 326 327 ATF_REQUIRE((ctx.sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0); 328 329 ctx.select_what = SELECT_WR; 330 check_select(&ctx); 331 ctx.poll_events = POLLOUT | POLLWRNORM; 332 check_poll(&ctx); 333 ctx.kev_filter = EVFILT_WRITE; 334 check_kevent(&ctx); 335 336 close(ctx.sv[0]); 337 } 338 339 ATF_TC_WITHOUT_HEAD(peerclosed_writability); 340 ATF_TC_BODY(peerclosed_writability, tc) 341 { 342 struct check_ctx ctx = { 343 .timeout = false, 344 .nfds = 1, 345 }; 346 347 do_socketpair(ctx.sv); 348 close(ctx.sv[1]); 349 350 ctx.select_what = SELECT_WR; 351 check_select(&ctx); 352 ctx.poll_events = POLLOUT | POLLWRNORM; 353 check_poll(&ctx); 354 ctx.kev_filter = EVFILT_WRITE; 355 ctx.kev_flags = EV_EOF; 356 check_kevent(&ctx); 357 358 close(ctx.sv[0]); 359 } 360 361 ATF_TC_WITHOUT_HEAD(peershutdown_writability); 362 ATF_TC_BODY(peershutdown_writability, tc) 363 { 364 struct check_ctx ctx = { 365 .timeout = false, 366 .nfds = 1, 367 }; 368 369 do_socketpair(ctx.sv); 370 shutdown(ctx.sv[1], SHUT_RD); 371 372 ctx.select_what = SELECT_WR; 373 check_select(&ctx); 374 ctx.poll_events = POLLOUT | POLLWRNORM; 375 check_poll(&ctx); 376 /* 377 * XXXGL: historically unix(4) sockets were not reporting peer's 378 * shutdown(SHUT_RD) as our EV_EOF. The kevent(2) manual page says 379 * "filter will set EV_EOF when the reader disconnects", which is hard 380 * to interpret unambigously. For now leave the historic behavior, 381 * but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(), 382 * and then this test will also expect EV_EOF in returned flags. 383 */ 384 ctx.kev_filter = EVFILT_WRITE; 385 check_kevent(&ctx); 386 387 close(ctx.sv[0]); 388 close(ctx.sv[1]); 389 } 390 391 ATF_TC_WITHOUT_HEAD(peershutdown_readability); 392 ATF_TC_BODY(peershutdown_readability, tc) 393 { 394 struct check_ctx ctx = { 395 .timeout = false, 396 .nfds = 1, 397 }; 398 ssize_t readsz; 399 char c; 400 401 do_socketpair(ctx.sv); 402 shutdown(ctx.sv[1], SHUT_WR); 403 404 /* 405 * The other side should flag as readable in select(2) to allow it to 406 * read(2) and observe EOF. Ensure that both poll(2) and select(2) 407 * are consistent here. 408 */ 409 ctx.select_what = SELECT_RD; 410 check_select(&ctx); 411 ctx.poll_events = POLLIN | POLLRDNORM; 412 check_poll(&ctx); 413 414 /* 415 * Also check that read doesn't block. 416 */ 417 readsz = read(ctx.sv[0], &c, sizeof(c)); 418 ATF_REQUIRE_INTEQ(0, readsz); 419 420 close(ctx.sv[0]); 421 close(ctx.sv[1]); 422 } 423 424 static void 425 peershutdown_wakeup(struct check_ctx *ctx) 426 { 427 pthread_t thr; 428 429 ctx->timeout = false; 430 ctx->nfds = 1; 431 432 do_socketpair(ctx->sv); 433 thr = pthread_create_blocked(ctx); 434 shutdown(ctx->sv[1], SHUT_WR); 435 ATF_REQUIRE(pthread_join(thr, NULL) == 0); 436 437 close(ctx->sv[0]); 438 close(ctx->sv[1]); 439 } 440 441 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_select); 442 ATF_TC_BODY(peershutdown_wakeup_select, tc) 443 { 444 peershutdown_wakeup(&(struct check_ctx){ 445 .method = check_select, 446 .select_what = SELECT_RD, 447 }); 448 } 449 450 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_poll); 451 ATF_TC_BODY(peershutdown_wakeup_poll, tc) 452 { 453 peershutdown_wakeup(&(struct check_ctx){ 454 .method = check_poll, 455 .poll_events = POLLIN | POLLRDNORM | POLLRDHUP, 456 .poll_revents = POLLRDHUP, 457 }); 458 } 459 460 ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_kevent); 461 ATF_TC_BODY(peershutdown_wakeup_kevent, tc) 462 { 463 peershutdown_wakeup(&(struct check_ctx){ 464 .method = check_kevent, 465 .kev_filter = EVFILT_READ, 466 .kev_flags = EV_EOF, 467 }); 468 } 469 470 ATF_TP_ADD_TCS(tp) 471 { 472 ATF_TP_ADD_TC(tp, getpeereid); 473 ATF_TP_ADD_TC(tp, send_0); 474 ATF_TP_ADD_TC(tp, connected_writability); 475 ATF_TP_ADD_TC(tp, unconnected_writability); 476 ATF_TP_ADD_TC(tp, full_writability_select); 477 ATF_TP_ADD_TC(tp, full_writability_poll); 478 ATF_TP_ADD_TC(tp, full_writability_kevent); 479 ATF_TP_ADD_TC(tp, peerclosed_writability); 480 ATF_TP_ADD_TC(tp, peershutdown_writability); 481 ATF_TP_ADD_TC(tp, peershutdown_readability); 482 ATF_TP_ADD_TC(tp, peershutdown_wakeup_select); 483 ATF_TP_ADD_TC(tp, peershutdown_wakeup_poll); 484 ATF_TP_ADD_TC(tp, peershutdown_wakeup_kevent); 485 486 return atf_no_error(); 487 } 488