xref: /freebsd/tests/sys/kern/procdesc.c (revision b3734c1386dd2b0ade1a7f20d9ebf5f62c01819e)
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