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
wait_for_naptime(pid_t pid,const char * wmesg)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);
ATF_TC_BODY(pid_recycle,tc)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 *
poll_procdesc(void * arg)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);
ATF_TC_BODY(poll_close_race,tc)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);
ATF_TC_BODY(poll_exit_wakeup,tc)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);
ATF_TC_BODY(pdopenpid_basic,tc)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);
ATF_TC_BODY(pdopenpid_cloexec,tc)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);
ATF_TC_BODY(pdopenpid_einval,tc)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);
ATF_TC_BODY(pdopenpid_emfile,tc)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);
ATF_TC_BODY(pdopenpid_esrch,tc)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);
ATF_TC_BODY(pdopenpid_child,tc)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);
ATF_TC_BODY(pdopenpid_capmode,tc)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);
ATF_TC_BODY(pdopenpid_pdfork_then_open,tc)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);
ATF_TC_BODY(pdopenpid_fork_then_open,tc)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);
ATF_TC_BODY(pdopenpid_close_one_of_two,tc)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);
ATF_TC_BODY(pdopenpid_open_twice,tc)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);
ATF_TC_BODY(pdopenpid_pdwait_only_one,tc)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);
ATF_TC_BODY(pdopenpid_self,tc)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);
ATF_TC_BODY(pdopenpid_exiting,tc)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);
ATF_TC_BODY(pdopenpid_no_wakeup,tc)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);
ATF_TC_BODY(pddupfd_basic,tc)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
ATF_TP_ADD_TCS(tp)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