1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2026 ConnectWise 5 * Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org> 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/types.h> 30 #include <sys/capsicum.h> 31 #include <sys/mman.h> 32 #include <sys/resource.h> 33 #include <sys/user.h> 34 #include <sys/proc.h> 35 #include <sys/procdesc.h> 36 #include <sys/sysctl.h> 37 #include <sys/wait.h> 38 #include <machine/atomic.h> 39 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <poll.h> 43 #include <pthread.h> 44 #include <signal.h> 45 #include <stdio.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #include <atf-c.h> 50 #include <kvm.h> 51 52 #include "freebsd_test_suite/macros.h" 53 54 /* Tests for procdesc(4) that aren't specific to any one syscall */ 55 56 /* 57 * Block until a thread in the specified process is sleeping in the specified 58 * wait message. 59 */ 60 static void 61 wait_for_naptime(pid_t pid, const char *wmesg) 62 { 63 kvm_t *kd; 64 int count; 65 66 kd = kvm_openfiles(NULL, "/dev/null", NULL, O_RDONLY, NULL); 67 ATF_REQUIRE(kd != NULL); 68 for (;;) { 69 struct kinfo_proc *kip; 70 int i; 71 72 usleep(1000); 73 kip = kvm_getprocs(kd, KERN_PROC_PID | KERN_PROC_INC_THREAD, 74 pid, &count); 75 ATF_REQUIRE(kip != NULL); 76 for (i = 0; i < count; i++) { 77 ATF_REQUIRE(kip[i].ki_stat != SZOMB); 78 if (kip[i].ki_stat == SSLEEP && 79 strcmp(kip[i].ki_wmesg, wmesg) == 0) 80 break; 81 } 82 if (i < count) 83 break; 84 } 85 86 kvm_close(kd); 87 } 88 89 /* 90 * Even after waiting on a process descriptor with waitpid(2), the kernel will 91 * not recycle the pid until after the process descriptor is closed. That is 92 * important to prevent users from trying to wait() twice, the second time 93 * using a dangling pid. 94 * 95 * Whether this same anti-recycling behavior is used with pdwait() is 96 * unimportant, because pdwait _always_ uses a process descriptor. 97 */ 98 ATF_TC_WITHOUT_HEAD(pid_recycle); 99 ATF_TC_BODY(pid_recycle, tc) 100 { 101 size_t len; 102 int i, pd, pid_max; 103 pid_t dangle_pid; 104 105 len = sizeof(pid_max); 106 ATF_REQUIRE_EQ_MSG(0, 107 sysctlbyname("kern.pid_max", &pid_max, &len, NULL, 0), 108 "sysctlbyname: %s", strerror(errno)); 109 110 /* Create a process descriptor */ 111 dangle_pid = pdfork(&pd, PD_CLOEXEC | PD_DAEMON); 112 ATF_REQUIRE_MSG(dangle_pid >= 0, "pdfork: %s", strerror(errno)); 113 if (dangle_pid == 0) { 114 // In child 115 _exit(0); 116 } 117 /* 118 * Reap the child, but don't close the pd, creating a dangling pid. 119 * Notably, it isn't a Zombie, because the process is reaped. 120 */ 121 ATF_REQUIRE_EQ(dangle_pid, waitpid(dangle_pid, NULL, WEXITED)); 122 123 /* 124 * Now create and kill pid_max additional children. Test to see if pid 125 * gets reused. If not, that means the kernel is correctly reserving 126 * the dangling pid from reuse. 127 */ 128 for (i = 0; i < pid_max; i++) { 129 pid_t pid; 130 131 pid = vfork(); 132 ATF_REQUIRE_MSG(pid >= 0, "vfork: %s", strerror(errno)); 133 if (pid == 0) 134 _exit(0); 135 ATF_REQUIRE_MSG(pid != dangle_pid, 136 "pid got recycled after %d forks", i); 137 ATF_REQUIRE_EQ(pid, waitpid(pid, NULL, WEXITED)); 138 } 139 close(pd); 140 } 141 142 static void * 143 poll_procdesc(void *arg) 144 { 145 struct pollfd pfd; 146 147 pfd.fd = *(int *)arg; 148 pfd.events = POLLHUP; 149 (void)poll(&pfd, 1, 5000); 150 return ((void *)(uintptr_t)pfd.revents); 151 } 152 153 /* 154 * Regression test to exercise the case where a procdesc is closed while a 155 * thread is poll()ing it. 156 */ 157 ATF_TC_WITHOUT_HEAD(poll_close_race); 158 ATF_TC_BODY(poll_close_race, tc) 159 { 160 pthread_t thr; 161 pid_t pid; 162 uintptr_t revents; 163 int error, pd; 164 165 pid = pdfork(&pd, PD_DAEMON); 166 ATF_REQUIRE_MSG(pid >= 0, "pdfork: %s", strerror(errno)); 167 if (pid == 0) { 168 pause(); 169 _exit(0); 170 } 171 172 error = pthread_create(&thr, NULL, poll_procdesc, &pd); 173 ATF_REQUIRE_MSG(error == 0, "pthread_create: %s", strerror(error)); 174 175 wait_for_naptime(getpid(), "select"); 176 177 ATF_REQUIRE_MSG(close(pd) == 0, "close: %s", strerror(errno)); 178 179 error = pthread_join(thr, (void *)&revents); 180 ATF_REQUIRE_MSG(error == 0, "pthread_join: %s", strerror(error)); 181 ATF_REQUIRE_EQ(revents, POLLNVAL); 182 } 183 184 /* 185 * Verify that poll(2) of a procdesc returns POLLHUP when the process exits. 186 */ 187 ATF_TC_WITHOUT_HEAD(poll_exit_wakeup); 188 ATF_TC_BODY(poll_exit_wakeup, tc) 189 { 190 pthread_t thr; 191 uintptr_t revents; 192 pid_t pid; 193 int error, pd; 194 195 pid = pdfork(&pd, PD_DAEMON); 196 ATF_REQUIRE_MSG(pid >= 0, "pdfork: %s", strerror(errno)); 197 if (pid == 0) { 198 pause(); 199 _exit(0); 200 } 201 202 error = pthread_create(&thr, NULL, poll_procdesc, &pd); 203 ATF_REQUIRE_MSG(error == 0, "pthread_create: %s", strerror(error)); 204 205 wait_for_naptime(getpid(), "select"); 206 207 ATF_REQUIRE_MSG(pdkill(pd, SIGKILL) == 0, 208 "pdkill: %s", strerror(errno)); 209 210 error = pthread_join(thr, (void *)&revents); 211 ATF_REQUIRE_MSG(error == 0, "pthread_join: %s", strerror(error)); 212 ATF_REQUIRE_EQ(revents, POLLHUP); 213 214 ATF_REQUIRE_MSG(close(pd) == 0, "close: %s", strerror(errno)); 215 } 216 217 /* Tests for pdopenpid(2) */ 218 219 /* 220 * Basic: open a process descriptor for a child, verify pdgetpid() returns the 221 * right pid. 222 */ 223 ATF_TC_WITHOUT_HEAD(pdopenpid_basic); 224 ATF_TC_BODY(pdopenpid_basic, tc) 225 { 226 pid_t child, queried; 227 int fd; 228 229 child = fork(); 230 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 231 if (child == 0) { 232 for (;;) 233 pause(); 234 _exit(0); 235 } 236 237 fd = pdopenpid(child, 0); 238 ATF_REQUIRE_MSG(fd >= 0, "pdopenpid: %s", strerror(errno)); 239 240 ATF_REQUIRE_MSG(pdgetpid(fd, &queried) == 0, 241 "pdgetpid: %s", strerror(errno)); 242 ATF_REQUIRE_EQ(child, queried); 243 244 ATF_REQUIRE_MSG(pdkill(fd, SIGKILL) == 0, 245 "pdkill: %s", strerror(errno)); 246 ATF_REQUIRE_EQ(child, waitpid(child, NULL, 0)); 247 ATF_REQUIRE(close(fd) == 0); 248 } 249 250 /* 251 * pdopenpid with PD_CLOEXEC should set the close-on-exec flag. 252 */ 253 ATF_TC_WITHOUT_HEAD(pdopenpid_cloexec); 254 ATF_TC_BODY(pdopenpid_cloexec, tc) 255 { 256 pid_t child; 257 int fd, flags; 258 259 child = fork(); 260 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 261 if (child == 0) { 262 for (;;) 263 pause(); 264 _exit(0); 265 } 266 267 fd = pdopenpid(child, PD_CLOEXEC); 268 ATF_REQUIRE_MSG(fd >= 0, "pdopenpid: %s", strerror(errno)); 269 270 flags = fcntl(fd, F_GETFD); 271 ATF_REQUIRE(flags >= 0); 272 ATF_REQUIRE(flags & FD_CLOEXEC); 273 274 ATF_REQUIRE_MSG(pdkill(fd, SIGKILL) == 0, 275 "pdkill: %s", strerror(errno)); 276 ATF_REQUIRE_EQ(child, waitpid(child, NULL, 0)); 277 ATF_REQUIRE(close(fd) == 0); 278 } 279 280 /* 281 * Invalid flags should return EINVAL. 282 */ 283 ATF_TC_WITHOUT_HEAD(pdopenpid_einval); 284 ATF_TC_BODY(pdopenpid_einval, tc) 285 { 286 ATF_REQUIRE_ERRNO(EINVAL, pdopenpid(getpid(), 0xdeadbeef) < 0); 287 ATF_REQUIRE_ERRNO(EINVAL, pdopenpid(getpid(), ~PD_ALLOWED_AT_FORK) < 0); 288 } 289 290 /* 291 * Validate handling of EMFILE. 292 */ 293 ATF_TC_WITHOUT_HEAD(pdopenpid_emfile); 294 ATF_TC_BODY(pdopenpid_emfile, tc) 295 { 296 pid_t child; 297 struct rlimit rl; 298 int fd; 299 300 child = fork(); 301 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 302 if (child == 0) { 303 for (;;) 304 pause(); 305 _exit(0); 306 } 307 308 /* 309 * Determine the lowest unused fd, then set the fd limit to that 310 * value so that no new fds can be allocated. 311 */ 312 fd = dup(STDIN_FILENO); 313 ATF_REQUIRE(fd >= 0); 314 ATF_REQUIRE(close(fd) == 0); 315 316 ATF_REQUIRE_EQ(getrlimit(RLIMIT_NOFILE, &rl), 0); 317 rl.rlim_cur = fd; 318 ATF_REQUIRE_EQ(setrlimit(RLIMIT_NOFILE, &rl), 0); 319 320 ATF_REQUIRE_ERRNO(EMFILE, pdopenpid(child, 0) < 0); 321 322 /* 323 * The child should not have been killed or reparented as a side 324 * effect of the failed syscall. 325 */ 326 ATF_REQUIRE_MSG(kill(child, 0) == 0, 327 "child was killed: %s", strerror(errno)); 328 ATF_REQUIRE_MSG(waitpid(child, NULL, WNOHANG) == 0, 329 "child was reparented"); 330 331 ATF_REQUIRE_MSG(kill(child, SIGKILL) == 0, 332 "kill: %s", strerror(errno)); 333 ATF_REQUIRE_EQ(child, waitpid(child, NULL, 0)); 334 } 335 336 /* 337 * Opening a nonexistent pid should return ESRCH. 338 */ 339 ATF_TC_WITHOUT_HEAD(pdopenpid_esrch); 340 ATF_TC_BODY(pdopenpid_esrch, tc) 341 { 342 ATF_REQUIRE_ERRNO(ESRCH, pdopenpid(123456789, 0) < 0); 343 } 344 345 /* 346 * pdopenpid works for children in capability mode. 347 */ 348 ATF_TC_WITHOUT_HEAD(pdopenpid_child); 349 ATF_TC_BODY(pdopenpid_child, tc) 350 { 351 pid_t child, parent; 352 353 ATF_REQUIRE_FEATURE("security_capability_mode"); 354 355 parent = getpid(); 356 child = fork(); 357 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 358 if (child == 0) { 359 while (getppid() == parent) 360 sleep(1); 361 _exit(0); 362 } 363 364 ATF_REQUIRE_MSG(cap_enter() == 0, "cap_enter: %s", strerror(errno)); 365 ATF_REQUIRE_MSG(pdopenpid(child, 0) >= 0, "pdopenpid: %s", 366 strerror(errno)); 367 } 368 369 /* 370 * pdopenpid should fail in capability mode. 371 */ 372 ATF_TC_WITHOUT_HEAD(pdopenpid_capmode); 373 ATF_TC_BODY(pdopenpid_capmode, tc) 374 { 375 pid_t child; 376 volatile pid_t grandchild; 377 378 ATF_REQUIRE_FEATURE("security_capability_mode"); 379 380 child = vfork(); 381 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 382 if (child == 0) { 383 grandchild = fork(); 384 ATF_REQUIRE_MSG(grandchild >= 0, "fork: %s", strerror(errno)); 385 if (grandchild == 0) { 386 for (;;) 387 sleep(1); 388 } else { 389 _exit(0); 390 } 391 } 392 393 ATF_REQUIRE_MSG(cap_enter() == 0, "cap_enter: %s", strerror(errno)); 394 ATF_REQUIRE_ERRNO(ECAPMODE, pdopenpid(grandchild, 0) < 0); 395 kill(grandchild, SIGKILL); 396 } 397 398 /* 399 * Open a process descriptor for a child that already has one from pdfork(). 400 * Both fds should refer to the same process. 401 */ 402 ATF_TC_WITHOUT_HEAD(pdopenpid_pdfork_then_open); 403 ATF_TC_BODY(pdopenpid_pdfork_then_open, tc) 404 { 405 pid_t child, pid1, pid2; 406 int fd1, fd2; 407 408 child = pdfork(&fd1, PD_DAEMON); 409 ATF_REQUIRE_MSG(child >= 0, "pdfork: %s", strerror(errno)); 410 if (child == 0) { 411 for (;;) 412 pause(); 413 _exit(0); 414 } 415 416 fd2 = pdopenpid(child, 0); 417 ATF_REQUIRE_MSG(fd2 >= 0, "pdopenpid: %s", strerror(errno)); 418 419 ATF_REQUIRE(pdgetpid(fd1, &pid1) == 0); 420 ATF_REQUIRE(pdgetpid(fd2, &pid2) == 0); 421 ATF_REQUIRE_EQ(pid1, pid2); 422 ATF_REQUIRE_EQ(child, pid1); 423 424 /* Kill via the second fd, wait via the first. */ 425 ATF_REQUIRE_MSG(pdkill(fd2, SIGKILL) == 0, 426 "pdkill: %s", strerror(errno)); 427 ATF_REQUIRE_MSG(pdwait(fd1, NULL, WEXITED, NULL, NULL) == 0, 428 "pdwait: %s", strerror(errno)); 429 430 ATF_REQUIRE(close(fd1) == 0); 431 ATF_REQUIRE(close(fd2) == 0); 432 } 433 434 /* 435 * Open a process descriptor for a child created with fork(), which has no 436 * pre-existing procdesc. Then use pdkill() and pdwait() on it. 437 */ 438 ATF_TC_WITHOUT_HEAD(pdopenpid_fork_then_open); 439 ATF_TC_BODY(pdopenpid_fork_then_open, tc) 440 { 441 pid_t child; 442 int fd, status; 443 444 child = fork(); 445 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 446 if (child == 0) { 447 for (;;) 448 pause(); 449 _exit(0); 450 } 451 452 fd = pdopenpid(child, 0); 453 ATF_REQUIRE_MSG(fd >= 0, "pdopenpid: %s", strerror(errno)); 454 455 ATF_REQUIRE_MSG(pdkill(fd, SIGKILL) == 0, 456 "pdkill: %s", strerror(errno)); 457 ATF_REQUIRE_MSG(pdwait(fd, &status, WEXITED, NULL, NULL) == 0, 458 "pdwait: %s", strerror(errno)); 459 ATF_REQUIRE(WIFSIGNALED(status)); 460 ATF_REQUIRE_EQ(WTERMSIG(status), SIGKILL); 461 462 ATF_REQUIRE(close(fd) == 0); 463 } 464 465 /* 466 * Closing one fd should not kill the process when another fd still references 467 * the same procdesc. 468 */ 469 ATF_TC_WITHOUT_HEAD(pdopenpid_close_one_of_two); 470 ATF_TC_BODY(pdopenpid_close_one_of_two, tc) 471 { 472 pid_t child, queried; 473 int fd1, fd2, status; 474 475 child = pdfork(&fd1, PD_DAEMON); 476 ATF_REQUIRE_MSG(child >= 0, "pdfork: %s", strerror(errno)); 477 if (child == 0) { 478 for (;;) 479 pause(); 480 _exit(0); 481 } 482 483 fd2 = pdopenpid(child, 0); 484 ATF_REQUIRE_MSG(fd2 >= 0, "pdopenpid: %s", strerror(errno)); 485 486 /* Close the first fd; the process should remain alive. */ 487 ATF_REQUIRE(close(fd1) == 0); 488 489 /* 490 * Verify the process is still reachable via the second fd and still 491 * alive. 492 */ 493 ATF_REQUIRE_EQ(0, pdgetpid(fd2, &queried)); 494 ATF_REQUIRE_EQ(child, queried); 495 ATF_REQUIRE_MSG(pdkill(fd2, 0) == 0, 496 "pdkill(0) after closing first fd: %s", strerror(errno)); 497 498 /* Now kill and reap via the second fd. */ 499 ATF_REQUIRE_MSG(pdkill(fd2, SIGKILL) == 0, 500 "pdkill: %s", strerror(errno)); 501 ATF_REQUIRE_MSG(pdwait(fd2, &status, WEXITED, NULL, NULL) == 0, 502 "pdwait: %s", strerror(errno)); 503 ATF_REQUIRE(WIFSIGNALED(status)); 504 ATF_REQUIRE_EQ(WTERMSIG(status), SIGKILL); 505 506 ATF_REQUIRE(close(fd2) == 0); 507 } 508 509 /* 510 * Two calls to pdopenpid for the same process (no pdfork) should both work. 511 */ 512 ATF_TC_WITHOUT_HEAD(pdopenpid_open_twice); 513 ATF_TC_BODY(pdopenpid_open_twice, tc) 514 { 515 pid_t child, pid1, pid2; 516 int fd1, fd2; 517 518 child = fork(); 519 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 520 if (child == 0) { 521 for (;;) 522 pause(); 523 _exit(0); 524 } 525 526 fd1 = pdopenpid(child, 0); 527 ATF_REQUIRE_MSG(fd1 >= 0, "pdopenpid(1): %s", strerror(errno)); 528 529 fd2 = pdopenpid(child, 0); 530 ATF_REQUIRE_MSG(fd2 >= 0, "pdopenpid(2): %s", strerror(errno)); 531 532 ATF_REQUIRE_EQ(0, pdgetpid(fd1, &pid1)); 533 ATF_REQUIRE_EQ(0, pdgetpid(fd2, &pid2)); 534 ATF_REQUIRE_EQ(pid1, pid2); 535 536 /* Close the first, process should survive. */ 537 ATF_REQUIRE(close(fd1) == 0); 538 ATF_REQUIRE_MSG(pdkill(fd2, 0) == 0, 539 "pdkill(0) after closing first fd: %s", strerror(errno)); 540 541 ATF_REQUIRE_MSG(pdkill(fd2, SIGKILL) == 0, 542 "pdkill: %s", strerror(errno)); 543 ATF_REQUIRE_MSG(pdwait(fd2, NULL, WEXITED, NULL, NULL) == 0, 544 "pdwait: %s", strerror(errno)); 545 ATF_REQUIRE(close(fd2) == 0); 546 } 547 548 /* 549 * When a process with two procdesc fds exits, only one pdwait should succeed 550 * in collecting the exit status. The other should get ESRCH. 551 */ 552 ATF_TC_WITHOUT_HEAD(pdopenpid_pdwait_only_one); 553 ATF_TC_BODY(pdopenpid_pdwait_only_one, tc) 554 { 555 pid_t child; 556 int fd1, fd2, pip[2], status; 557 558 ATF_REQUIRE_EQ(pipe(pip), 0); 559 560 child = pdfork(&fd1, PD_DAEMON); 561 ATF_REQUIRE_MSG(child >= 0, "pdfork: %s", strerror(errno)); 562 if (child == 0) { 563 char c; 564 565 close(pip[1]); 566 /* Block until the parent has opened the second fd. */ 567 (void)read(pip[0], &c, 1); 568 _exit(42); 569 } 570 ATF_REQUIRE(close(pip[0]) == 0); 571 572 /* Open the second fd while the child is still alive. */ 573 fd2 = pdopenpid(child, 0); 574 ATF_REQUIRE_MSG(fd2 >= 0, "pdopenpid: %s", strerror(errno)); 575 576 /* Release the child so that it exits. */ 577 ATF_REQUIRE(close(pip[1]) == 0); 578 579 /* Collect via the first fd. */ 580 ATF_REQUIRE_MSG(pdwait(fd1, &status, WEXITED, NULL, NULL) == 0, 581 "pdwait(fd1): %s", strerror(errno)); 582 ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42); 583 584 /* The second fd should be able to collect as well. */ 585 ATF_REQUIRE_MSG(pdwait(fd2, &status, WEXITED, NULL, NULL) == 0, 586 "pdwait(fd2): %s", strerror(errno)); 587 ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42); 588 589 ATF_REQUIRE(close(fd1) == 0); 590 ATF_REQUIRE(close(fd2) == 0); 591 } 592 593 /* 594 * Opening a process descriptor for ourselves should work. 595 */ 596 ATF_TC_WITHOUT_HEAD(pdopenpid_self); 597 ATF_TC_BODY(pdopenpid_self, tc) 598 { 599 pid_t child, queried; 600 int childfd, fd, status; 601 602 /* 603 * Closing self-referencing procdesc would steal the exit 604 * status from the parent. Keep one more procdesc for the 605 * child in the parent so that we can query the state. 606 * 607 * For the same reason we must use fork() and test in the 608 * child, otherwise kyua does not get the SIGCHILD nor the 609 * exit status. 610 */ 611 child = pdfork(&childfd, 0); 612 if (child == 0) { 613 fd = pdopenpid(getpid(), PD_DAEMON); 614 if (fd < 0) 615 _exit(21); 616 if (pdgetpid(fd, &queried) == -1) 617 _exit(22); 618 if (getpid() != queried) 619 _exit(23); 620 if (close(fd) != 0) 621 _exit(24); 622 _exit(0); 623 } 624 625 ATF_REQUIRE(pdgetpid(childfd, &queried) == 0); 626 ATF_REQUIRE_EQ(queried, child); 627 ATF_REQUIRE(pdwait(childfd, &status, WEXITED, NULL, NULL) == 0); 628 629 ATF_REQUIRE(WIFEXITED(status)); 630 ATF_REQUIRE_EQ(WEXITSTATUS(status), 0); 631 ATF_REQUIRE(close(childfd) == 0); 632 } 633 634 /* 635 * pdopenpid for a process that is exiting (P_WEXIT set) should fail with EBUSY. 636 */ 637 ATF_TC_WITHOUT_HEAD(pdopenpid_exiting); 638 ATF_TC_BODY(pdopenpid_exiting, tc) 639 { 640 pid_t child; 641 int fd, pip[2], status; 642 643 ATF_REQUIRE_EQ(pipe(pip), 0); 644 645 child = fork(); 646 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 647 if (child == 0) { 648 char c; 649 650 close(pip[1]); 651 (void)read(pip[0], &c, 1); 652 _exit(0); 653 } 654 ATF_REQUIRE(close(pip[0]) == 0); 655 656 /* Tell the child to exit. */ 657 ATF_REQUIRE(close(pip[1]) == 0); 658 659 /* Might still race. */ 660 usleep(1000); 661 fd = pdopenpid(child, 0); 662 if (fd >= 0) { 663 ATF_REQUIRE(close(fd) == 0); 664 } else { 665 ATF_REQUIRE_MSG(errno == EBUSY, 666 "unexpected errno %d (%s)", errno, strerror(errno)); 667 } 668 669 ATF_REQUIRE(waitpid(child, &status, 0) == child); 670 ATF_REQUIRE(WIFEXITED(status)); 671 ATF_REQUIRE_EQ(WEXITSTATUS(status), 0); 672 } 673 674 /* 675 * Make sure that opening a process descriptor doesn't cause a wakeup in the 676 * target process. 677 */ 678 ATF_TC_WITHOUT_HEAD(pdopenpid_no_wakeup); 679 ATF_TC_BODY(pdopenpid_no_wakeup, tc) 680 { 681 pid_t child; 682 int fd, pip[2]; 683 684 ATF_REQUIRE(pipe(pip) == 0); 685 686 child = fork(); 687 ATF_REQUIRE_MSG(child >= 0, "fork: %s", strerror(errno)); 688 if (child == 0) { 689 char buf[1]; 690 691 close(pip[1]); 692 (void)read(pip[0], buf, 1); 693 _exit(0); 694 } 695 close(pip[0]); 696 697 wait_for_naptime(child, "piperd"); 698 699 fd = pdopenpid(child, 0); 700 ATF_REQUIRE_MSG(fd >= 0, "pdopenpid: %s", strerror(errno)); 701 702 /* 703 * If pdopenpid() caused a wakeup, read() returned and the child exited. 704 */ 705 wait_for_naptime(child, "piperd"); 706 707 ATF_REQUIRE(close(pip[1]) == 0); 708 ATF_REQUIRE(close(fd) == 0); 709 } 710 711 /* 712 * basic pddupfd functionality 713 */ 714 715 #define EXPECTED_OFFSET 123 716 717 ATF_TC_WITHOUT_HEAD(pddupfd_basic); 718 ATF_TC_BODY(pddupfd_basic, tc) 719 { 720 int *comm; 721 struct __wrusage wu; 722 struct __siginfo si; 723 int fd, pp, rfd, status, workfd, r, r1; 724 off_t off; 725 pid_t child; 726 727 comm = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | 728 MAP_ANONYMOUS, -1, 0); 729 ATF_REQUIRE(comm != MAP_FAILED); 730 atomic_store_int(comm, -1); 731 732 child = fork(); 733 ATF_REQUIRE(child != -1); 734 if (child == 0) { 735 workfd = open("/etc/passwd", O_RDONLY); 736 ATF_REQUIRE(workfd != -1); 737 atomic_store_int(comm, workfd); 738 while ((r = (int)atomic_load_int(comm)) >= 0) 739 sleep(1); 740 lseek(workfd, EXPECTED_OFFSET, SEEK_SET); 741 r -= 1; 742 atomic_store_int(comm, r); 743 while (r == (int)atomic_load_int(comm)) 744 sleep(1); 745 _exit(0x23); 746 } 747 748 fd = pdopenpid(child, 0); 749 ATF_REQUIRE(fd != -1); 750 ATF_REQUIRE(pdgetpid(fd, &pp) == 0); 751 752 while ((rfd = (int)atomic_load_int(comm)) == -1) 753 ; 754 ATF_REQUIRE(rfd >= 0); 755 workfd = pddupfd(fd, rfd, 0); 756 ATF_REQUIRE(workfd != -1); 757 758 /* 759 * pddupfd-ed file must dup-ed, i.e. the underlying file must 760 * be same between the remote and local filedescriptors. 761 * Check that the initial seek offset is zero. Then observe 762 * the updated offset, which is only possible if the file is 763 * indeed shared. 764 */ 765 off = lseek(workfd, 0, SEEK_CUR); 766 ATF_REQUIRE_EQ(off, 0); 767 r = -1; 768 atomic_store_int(comm, r); 769 while ((r1 = (int)atomic_load_int(comm)) == r) 770 sleep(1); 771 off = lseek(workfd, 0, SEEK_CUR); 772 ATF_REQUIRE_EQ(off, EXPECTED_OFFSET); 773 r1 -= 1; 774 atomic_store_int(comm, r1); 775 ATF_REQUIRE(close(workfd) == 0); 776 777 ATF_REQUIRE(pdwait(fd, &status, WEXITED, &wu, &si) != -1); 778 ATF_REQUIRE(close(fd) == 0); 779 } 780 781 ATF_TP_ADD_TCS(tp) 782 { 783 ATF_TP_ADD_TC(tp, pid_recycle); 784 ATF_TP_ADD_TC(tp, poll_close_race); 785 ATF_TP_ADD_TC(tp, poll_exit_wakeup); 786 787 ATF_TP_ADD_TC(tp, pdopenpid_basic); 788 ATF_TP_ADD_TC(tp, pdopenpid_cloexec); 789 ATF_TP_ADD_TC(tp, pdopenpid_einval); 790 ATF_TP_ADD_TC(tp, pdopenpid_emfile); 791 ATF_TP_ADD_TC(tp, pdopenpid_esrch); 792 ATF_TP_ADD_TC(tp, pdopenpid_child); 793 ATF_TP_ADD_TC(tp, pdopenpid_capmode); 794 ATF_TP_ADD_TC(tp, pdopenpid_pdfork_then_open); 795 ATF_TP_ADD_TC(tp, pdopenpid_fork_then_open); 796 ATF_TP_ADD_TC(tp, pdopenpid_close_one_of_two); 797 ATF_TP_ADD_TC(tp, pdopenpid_open_twice); 798 ATF_TP_ADD_TC(tp, pdopenpid_pdwait_only_one); 799 ATF_TP_ADD_TC(tp, pdopenpid_self); 800 ATF_TP_ADD_TC(tp, pdopenpid_exiting); 801 ATF_TP_ADD_TC(tp, pdopenpid_no_wakeup); 802 803 ATF_TP_ADD_TC(tp, pddupfd_basic); 804 805 return (atf_no_error()); 806 } 807