xref: /freebsd/tests/sys/kern/ptrace_test.c (revision 98685dc8af6354777ae09c5763fe4cbc9f3d99a1)
1c209e3e2SJohn Baldwin /*-
2c209e3e2SJohn Baldwin  * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
3c209e3e2SJohn Baldwin  * All rights reserved.
4c209e3e2SJohn Baldwin  *
5c209e3e2SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
6c209e3e2SJohn Baldwin  * modification, are permitted provided that the following conditions
7c209e3e2SJohn Baldwin  * are met:
8c209e3e2SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
9c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
10c209e3e2SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
11c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
12c209e3e2SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
13c209e3e2SJohn Baldwin  *
14c209e3e2SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15c209e3e2SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16c209e3e2SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c209e3e2SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18c209e3e2SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c209e3e2SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c209e3e2SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c209e3e2SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c209e3e2SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c209e3e2SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24c209e3e2SJohn Baldwin  * SUCH DAMAGE.
25c209e3e2SJohn Baldwin  */
26c209e3e2SJohn Baldwin 
27c209e3e2SJohn Baldwin #include <sys/cdefs.h>
28c209e3e2SJohn Baldwin __FBSDID("$FreeBSD$");
29c209e3e2SJohn Baldwin 
30c209e3e2SJohn Baldwin #include <sys/types.h>
31c209e3e2SJohn Baldwin #include <sys/ptrace.h>
3257c74f5bSJohn Baldwin #include <sys/sysctl.h>
3357c74f5bSJohn Baldwin #include <sys/user.h>
34c209e3e2SJohn Baldwin #include <sys/wait.h>
35c209e3e2SJohn Baldwin #include <errno.h>
36c209e3e2SJohn Baldwin #include <signal.h>
37dfa8ba12SJohn Baldwin #include <stdio.h>
38c209e3e2SJohn Baldwin #include <stdlib.h>
39c209e3e2SJohn Baldwin #include <unistd.h>
40c209e3e2SJohn Baldwin #include <atf-c.h>
41c209e3e2SJohn Baldwin 
42c209e3e2SJohn Baldwin /*
43dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
44dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
45dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
46dfa8ba12SJohn Baldwin  */
47dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {						\
48dfa8ba12SJohn Baldwin 		if (!(exp))						\
49dfa8ba12SJohn Baldwin 			child_fail_require(__FILE__, __LINE__,		\
50dfa8ba12SJohn Baldwin 			    #exp " not met");				\
51dfa8ba12SJohn Baldwin 	} while (0)
52dfa8ba12SJohn Baldwin 
53*98685dc8SJohn Baldwin static __dead2 void
54dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str)
55dfa8ba12SJohn Baldwin {
56dfa8ba12SJohn Baldwin 	char buf[128];
57dfa8ba12SJohn Baldwin 
58dfa8ba12SJohn Baldwin 	snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str);
59dfa8ba12SJohn Baldwin 	write(2, buf, strlen(buf));
60dfa8ba12SJohn Baldwin 	_exit(32);
61dfa8ba12SJohn Baldwin }
62dfa8ba12SJohn Baldwin 
63*98685dc8SJohn Baldwin static void
64*98685dc8SJohn Baldwin trace_me(void)
65*98685dc8SJohn Baldwin {
66*98685dc8SJohn Baldwin 
67*98685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
68*98685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
69*98685dc8SJohn Baldwin 
70*98685dc8SJohn Baldwin 	/* Trigger a stop. */
71*98685dc8SJohn Baldwin 	raise(SIGSTOP);
72*98685dc8SJohn Baldwin }
73*98685dc8SJohn Baldwin 
74*98685dc8SJohn Baldwin static void
75*98685dc8SJohn Baldwin attach_child(pid_t pid)
76*98685dc8SJohn Baldwin {
77*98685dc8SJohn Baldwin 	pid_t wpid;
78*98685dc8SJohn Baldwin 	int status;
79*98685dc8SJohn Baldwin 
80*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
81*98685dc8SJohn Baldwin 
82*98685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
83*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == pid);
84*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
85*98685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
86*98685dc8SJohn Baldwin }
87*98685dc8SJohn Baldwin 
88*98685dc8SJohn Baldwin static void
89*98685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
90*98685dc8SJohn Baldwin {
91*98685dc8SJohn Baldwin 
92*98685dc8SJohn Baldwin 	/*
93*98685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
94*98685dc8SJohn Baldwin 	 * there is not a better way.
95*98685dc8SJohn Baldwin 	 */
96*98685dc8SJohn Baldwin 	for (;;) {
97*98685dc8SJohn Baldwin 		struct kinfo_proc kp;
98*98685dc8SJohn Baldwin 		size_t len;
99*98685dc8SJohn Baldwin 		int mib[4];
100*98685dc8SJohn Baldwin 
101*98685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
102*98685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
103*98685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
104*98685dc8SJohn Baldwin 		mib[3] = pid;
105*98685dc8SJohn Baldwin 		len = sizeof(kp);
106*98685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
107*98685dc8SJohn Baldwin 			/* The KERN_PROC_PID sysctl fails for zombies. */
108*98685dc8SJohn Baldwin 			ATF_REQUIRE(errno == ESRCH);
109*98685dc8SJohn Baldwin 			break;
110*98685dc8SJohn Baldwin 		}
111*98685dc8SJohn Baldwin 		usleep(5000);
112*98685dc8SJohn Baldwin 	}
113*98685dc8SJohn Baldwin }
114*98685dc8SJohn Baldwin 
115dfa8ba12SJohn Baldwin /*
116c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
117c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
118c209e3e2SJohn Baldwin  */
119c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
120c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
121c209e3e2SJohn Baldwin {
122c209e3e2SJohn Baldwin 	pid_t child, wpid;
123c209e3e2SJohn Baldwin 	int status;
124c209e3e2SJohn Baldwin 
125c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
126c209e3e2SJohn Baldwin 	if (child == 0) {
127c209e3e2SJohn Baldwin 		/* Child process. */
128*98685dc8SJohn Baldwin 		trace_me();
129c209e3e2SJohn Baldwin 
130c209e3e2SJohn Baldwin 		exit(1);
131c209e3e2SJohn Baldwin 	}
132c209e3e2SJohn Baldwin 
133c209e3e2SJohn Baldwin 	/* Parent process. */
134c209e3e2SJohn Baldwin 
135c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
136c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
137c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
138c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
139c209e3e2SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
140c209e3e2SJohn Baldwin 
141c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
142c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
143c209e3e2SJohn Baldwin 
144c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
145c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
146c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
147c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
148c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
149c209e3e2SJohn Baldwin 
150c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
151c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
152c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
153c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
154c209e3e2SJohn Baldwin }
155c209e3e2SJohn Baldwin 
156c209e3e2SJohn Baldwin /*
157c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
158c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
159c209e3e2SJohn Baldwin  */
160c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
161c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
162c209e3e2SJohn Baldwin {
163c209e3e2SJohn Baldwin 	pid_t child, wpid;
164c209e3e2SJohn Baldwin 	int cpipe[2], status;
165c209e3e2SJohn Baldwin 	char c;
166c209e3e2SJohn Baldwin 
167c209e3e2SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
168c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
169c209e3e2SJohn Baldwin 	if (child == 0) {
170c209e3e2SJohn Baldwin 		/* Child process. */
171c209e3e2SJohn Baldwin 		close(cpipe[0]);
172c209e3e2SJohn Baldwin 
173c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
174dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0);
175c209e3e2SJohn Baldwin 
176c209e3e2SJohn Baldwin 		exit(1);
177c209e3e2SJohn Baldwin 	}
178c209e3e2SJohn Baldwin 	close(cpipe[1]);
179c209e3e2SJohn Baldwin 
180c209e3e2SJohn Baldwin 	/* Parent process. */
181c209e3e2SJohn Baldwin 
182c209e3e2SJohn Baldwin 	/* Attach to the child process. */
183*98685dc8SJohn Baldwin 	attach_child(child);
184c209e3e2SJohn Baldwin 
185c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
186c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
187c209e3e2SJohn Baldwin 
188c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
189c209e3e2SJohn Baldwin 	close(cpipe[0]);
190c209e3e2SJohn Baldwin 
191c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
192c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
193c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
194c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
195c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
196c209e3e2SJohn Baldwin 
197c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
198c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
199c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
200c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
201c209e3e2SJohn Baldwin }
202c209e3e2SJohn Baldwin 
20357c74f5bSJohn Baldwin /*
20457c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
20557c74f5bSJohn Baldwin  * after the debugger has seen it.
20657c74f5bSJohn Baldwin  */
20757c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
20857c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
20957c74f5bSJohn Baldwin {
21057c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
21157c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
21257c74f5bSJohn Baldwin 	char c;
21357c74f5bSJohn Baldwin 
21457c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
21557c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
21657c74f5bSJohn Baldwin 
21757c74f5bSJohn Baldwin 	if (child == 0) {
21857c74f5bSJohn Baldwin 		/* Child process. */
21957c74f5bSJohn Baldwin 		close(cpipe[0]);
22057c74f5bSJohn Baldwin 
22157c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
222dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
22357c74f5bSJohn Baldwin 
22457c74f5bSJohn Baldwin 		exit(1);
22557c74f5bSJohn Baldwin 	}
22657c74f5bSJohn Baldwin 	close(cpipe[1]);
22757c74f5bSJohn Baldwin 
22857c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
22957c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
23057c74f5bSJohn Baldwin 
23157c74f5bSJohn Baldwin 	if (debugger == 0) {
23257c74f5bSJohn Baldwin 		/* Debugger process. */
23357c74f5bSJohn Baldwin 		close(dpipe[0]);
23457c74f5bSJohn Baldwin 
235dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
23657c74f5bSJohn Baldwin 
23757c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
238dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
239dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
240dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
24157c74f5bSJohn Baldwin 
242dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
24357c74f5bSJohn Baldwin 
24457c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
245dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
24657c74f5bSJohn Baldwin 
24757c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
248dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0);
24957c74f5bSJohn Baldwin 
25057c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
251dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
252dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
253dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
25457c74f5bSJohn Baldwin 
25557c74f5bSJohn Baldwin 		exit(0);
25657c74f5bSJohn Baldwin 	}
25757c74f5bSJohn Baldwin 	close(dpipe[1]);
25857c74f5bSJohn Baldwin 
25957c74f5bSJohn Baldwin 	/* Parent process. */
26057c74f5bSJohn Baldwin 
26157c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
26257c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
26357c74f5bSJohn Baldwin 
26457c74f5bSJohn Baldwin 	/* Release the child. */
26557c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
26657c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
26757c74f5bSJohn Baldwin 	close(cpipe[0]);
26857c74f5bSJohn Baldwin 
269*98685dc8SJohn Baldwin 	wait_for_zombie(child);
27057c74f5bSJohn Baldwin 
27157c74f5bSJohn Baldwin 	/*
2722f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
2732f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
2742f021998SJohn Baldwin 	 * until the debugger sees the exit.
27557c74f5bSJohn Baldwin 	 */
27657c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
27757c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
27857c74f5bSJohn Baldwin 
27957c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
28057c74f5bSJohn Baldwin 	close(dpipe[0]);
28157c74f5bSJohn Baldwin 
28257c74f5bSJohn Baldwin 	/* Wait for the debugger. */
28357c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
28457c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
28557c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
28657c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
28757c74f5bSJohn Baldwin 
28857c74f5bSJohn Baldwin 	/* The child process should now be ready. */
28957c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
29057c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
29157c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
29257c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
29357c74f5bSJohn Baldwin }
29457c74f5bSJohn Baldwin 
29557c74f5bSJohn Baldwin /*
29657c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
29757c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
29857c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
29957c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
30057c74f5bSJohn Baldwin  */
30157c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
30257c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
30357c74f5bSJohn Baldwin {
30457c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
30557c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
30657c74f5bSJohn Baldwin 	char c;
30757c74f5bSJohn Baldwin 
30857c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
30957c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
31057c74f5bSJohn Baldwin 
31157c74f5bSJohn Baldwin 	if (child == 0) {
31257c74f5bSJohn Baldwin 		/* Child process. */
31357c74f5bSJohn Baldwin 		close(cpipe[0]);
31457c74f5bSJohn Baldwin 
31557c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
316dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
31757c74f5bSJohn Baldwin 
31857c74f5bSJohn Baldwin 		exit(1);
31957c74f5bSJohn Baldwin 	}
32057c74f5bSJohn Baldwin 	close(cpipe[1]);
32157c74f5bSJohn Baldwin 
32257c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
32357c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
32457c74f5bSJohn Baldwin 
32557c74f5bSJohn Baldwin 	if (debugger == 0) {
32657c74f5bSJohn Baldwin 		/* Debugger parent. */
32757c74f5bSJohn Baldwin 
32857c74f5bSJohn Baldwin 		/*
32957c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
33057c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
33157c74f5bSJohn Baldwin 		 */
332dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
33357c74f5bSJohn Baldwin 		if (fpid != 0)
33457c74f5bSJohn Baldwin 			exit(2);
33557c74f5bSJohn Baldwin 
33657c74f5bSJohn Baldwin 		/* Debugger process. */
33757c74f5bSJohn Baldwin 		close(dpipe[0]);
33857c74f5bSJohn Baldwin 
339dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
34057c74f5bSJohn Baldwin 
34157c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
342dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
343dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
344dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
34557c74f5bSJohn Baldwin 
346dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
34757c74f5bSJohn Baldwin 
34857c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
349dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
35057c74f5bSJohn Baldwin 
35157c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
352dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c));
35357c74f5bSJohn Baldwin 
35457c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
355dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
356dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
357dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
35857c74f5bSJohn Baldwin 
35957c74f5bSJohn Baldwin 		exit(0);
36057c74f5bSJohn Baldwin 	}
361eddb85c6SJohn Baldwin 	close(dpipe[1]);
36257c74f5bSJohn Baldwin 
36357c74f5bSJohn Baldwin 	/* Parent process. */
36457c74f5bSJohn Baldwin 
36557c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
36657c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
36757c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
36857c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
36957c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
37057c74f5bSJohn Baldwin 
37157c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
37257c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
37357c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
37457c74f5bSJohn Baldwin 
37557c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
37657c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
37757c74f5bSJohn Baldwin 
37857c74f5bSJohn Baldwin 	/* Release the child. */
37957c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
38057c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
38157c74f5bSJohn Baldwin 	close(cpipe[0]);
38257c74f5bSJohn Baldwin 
383*98685dc8SJohn Baldwin 	wait_for_zombie(child);
38457c74f5bSJohn Baldwin 
38557c74f5bSJohn Baldwin 	/*
3862f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3872f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3882f021998SJohn Baldwin 	 * until the debugger sees the exit.
38957c74f5bSJohn Baldwin 	 */
39057c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
39157c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
39257c74f5bSJohn Baldwin 
39357c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
394eddb85c6SJohn Baldwin 	ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c));
39557c74f5bSJohn Baldwin 
39657c74f5bSJohn Baldwin 	/* Wait for the debugger. */
397eddb85c6SJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0);
398eddb85c6SJohn Baldwin 	close(dpipe[0]);
39957c74f5bSJohn Baldwin 
40057c74f5bSJohn Baldwin 	/* The child process should now be ready. */
40157c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
40257c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
40357c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
40457c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
40557c74f5bSJohn Baldwin }
40657c74f5bSJohn Baldwin 
407*98685dc8SJohn Baldwin /*
408*98685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
409*98685dc8SJohn Baldwin  * debugger is attached to it.
410*98685dc8SJohn Baldwin  */
411*98685dc8SJohn Baldwin static __dead2 void
412*98685dc8SJohn Baldwin follow_fork_parent(void)
413*98685dc8SJohn Baldwin {
414*98685dc8SJohn Baldwin 	pid_t fpid, wpid;
415*98685dc8SJohn Baldwin 	int status;
416*98685dc8SJohn Baldwin 
417*98685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
418*98685dc8SJohn Baldwin 
419*98685dc8SJohn Baldwin 	if (fpid == 0)
420*98685dc8SJohn Baldwin 		/* Child */
421*98685dc8SJohn Baldwin 		exit(2);
422*98685dc8SJohn Baldwin 
423*98685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
424*98685dc8SJohn Baldwin 	CHILD_REQUIRE(wpid == fpid);
425*98685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
426*98685dc8SJohn Baldwin 	CHILD_REQUIRE(WEXITSTATUS(status) == 2);
427*98685dc8SJohn Baldwin 
428*98685dc8SJohn Baldwin 	exit(1);
429*98685dc8SJohn Baldwin }
430*98685dc8SJohn Baldwin 
431*98685dc8SJohn Baldwin /*
432*98685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
433*98685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
434*98685dc8SJohn Baldwin  * child process.
435*98685dc8SJohn Baldwin  */
436*98685dc8SJohn Baldwin static pid_t
437*98685dc8SJohn Baldwin handle_fork_events(pid_t parent)
438*98685dc8SJohn Baldwin {
439*98685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
440*98685dc8SJohn Baldwin 	bool fork_reported[2];
441*98685dc8SJohn Baldwin 	pid_t child, wpid;
442*98685dc8SJohn Baldwin 	int i, status;
443*98685dc8SJohn Baldwin 
444*98685dc8SJohn Baldwin 	fork_reported[0] = false;
445*98685dc8SJohn Baldwin 	fork_reported[1] = false;
446*98685dc8SJohn Baldwin 	child = -1;
447*98685dc8SJohn Baldwin 
448*98685dc8SJohn Baldwin 	/*
449*98685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
450*98685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
451*98685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
452*98685dc8SJohn Baldwin 	 */
453*98685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
454*98685dc8SJohn Baldwin 		wpid = wait(&status);
455*98685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
456*98685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
457*98685dc8SJohn Baldwin 
458*98685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
459*98685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
460*98685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
461*98685dc8SJohn Baldwin 		    0);
462*98685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
463*98685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
464*98685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
465*98685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
466*98685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
467*98685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
468*98685dc8SJohn Baldwin 			if (child == -1)
469*98685dc8SJohn Baldwin 				child = wpid;
470*98685dc8SJohn Baldwin 			else
471*98685dc8SJohn Baldwin 				ATF_REQUIRE(child == wpid);
472*98685dc8SJohn Baldwin 			fork_reported[1] = true;
473*98685dc8SJohn Baldwin 		} else {
474*98685dc8SJohn Baldwin 			ATF_REQUIRE(wpid == parent);
475*98685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
476*98685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
477*98685dc8SJohn Baldwin 			if (child == -1)
478*98685dc8SJohn Baldwin 				child = pl.pl_child_pid;
479*98685dc8SJohn Baldwin 			else
480*98685dc8SJohn Baldwin 				ATF_REQUIRE(child == pl.pl_child_pid);
481*98685dc8SJohn Baldwin 			fork_reported[0] = true;
482*98685dc8SJohn Baldwin 		}
483*98685dc8SJohn Baldwin 	}
484*98685dc8SJohn Baldwin 
485*98685dc8SJohn Baldwin 	return (child);
486*98685dc8SJohn Baldwin }
487*98685dc8SJohn Baldwin 
488*98685dc8SJohn Baldwin /*
489*98685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
490*98685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
491*98685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
492*98685dc8SJohn Baldwin  */
493*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
494*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
495*98685dc8SJohn Baldwin {
496*98685dc8SJohn Baldwin 	pid_t children[0], fpid, wpid;
497*98685dc8SJohn Baldwin 	int status;
498*98685dc8SJohn Baldwin 
499*98685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
500*98685dc8SJohn Baldwin 	if (fpid == 0) {
501*98685dc8SJohn Baldwin 		trace_me();
502*98685dc8SJohn Baldwin 		follow_fork_parent();
503*98685dc8SJohn Baldwin 	}
504*98685dc8SJohn Baldwin 
505*98685dc8SJohn Baldwin 	/* Parent process. */
506*98685dc8SJohn Baldwin 	children[0] = fpid;
507*98685dc8SJohn Baldwin 
508*98685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
509*98685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
510*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
511*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
512*98685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
513*98685dc8SJohn Baldwin 
514*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
515*98685dc8SJohn Baldwin 
516*98685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
517*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
518*98685dc8SJohn Baldwin 
519*98685dc8SJohn Baldwin 	children[1] = handle_fork_events(children[0]);
520*98685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
521*98685dc8SJohn Baldwin 
522*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
523*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
524*98685dc8SJohn Baldwin 
525*98685dc8SJohn Baldwin 	/*
526*98685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
527*98685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
528*98685dc8SJohn Baldwin 	 */
529*98685dc8SJohn Baldwin 	wpid = wait(&status);
530*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
531*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
532*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
533*98685dc8SJohn Baldwin 
534*98685dc8SJohn Baldwin 	wpid = wait(&status);
535*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
536*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
537*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
538*98685dc8SJohn Baldwin 
539*98685dc8SJohn Baldwin 	wpid = wait(&status);
540*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
541*98685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
542*98685dc8SJohn Baldwin }
543*98685dc8SJohn Baldwin 
544*98685dc8SJohn Baldwin /*
545*98685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
546*98685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
547*98685dc8SJohn Baldwin  * child process is detached after it reports its fork.
548*98685dc8SJohn Baldwin  */
549*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
550*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
551*98685dc8SJohn Baldwin {
552*98685dc8SJohn Baldwin 	pid_t children[0], fpid, wpid;
553*98685dc8SJohn Baldwin 	int status;
554*98685dc8SJohn Baldwin 
555*98685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
556*98685dc8SJohn Baldwin 	if (fpid == 0) {
557*98685dc8SJohn Baldwin 		trace_me();
558*98685dc8SJohn Baldwin 		follow_fork_parent();
559*98685dc8SJohn Baldwin 	}
560*98685dc8SJohn Baldwin 
561*98685dc8SJohn Baldwin 	/* Parent process. */
562*98685dc8SJohn Baldwin 	children[0] = fpid;
563*98685dc8SJohn Baldwin 
564*98685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
565*98685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
566*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
567*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
568*98685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
569*98685dc8SJohn Baldwin 
570*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
571*98685dc8SJohn Baldwin 
572*98685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
573*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
574*98685dc8SJohn Baldwin 
575*98685dc8SJohn Baldwin 	children[1] = handle_fork_events(children[0]);
576*98685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
577*98685dc8SJohn Baldwin 
578*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
579*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
580*98685dc8SJohn Baldwin 
581*98685dc8SJohn Baldwin 	/*
582*98685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
583*98685dc8SJohn Baldwin 	 * child.
584*98685dc8SJohn Baldwin 	 */
585*98685dc8SJohn Baldwin 	wpid = wait(&status);
586*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
587*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
588*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
589*98685dc8SJohn Baldwin 
590*98685dc8SJohn Baldwin 	wpid = wait(&status);
591*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
592*98685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
593*98685dc8SJohn Baldwin }
594*98685dc8SJohn Baldwin 
595*98685dc8SJohn Baldwin /*
596*98685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
597*98685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
598*98685dc8SJohn Baldwin  * traced parent is detached after the fork.
599*98685dc8SJohn Baldwin  */
600*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
601*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
602*98685dc8SJohn Baldwin {
603*98685dc8SJohn Baldwin 	pid_t children[0], fpid, wpid;
604*98685dc8SJohn Baldwin 	int status;
605*98685dc8SJohn Baldwin 
606*98685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
607*98685dc8SJohn Baldwin 	if (fpid == 0) {
608*98685dc8SJohn Baldwin 		trace_me();
609*98685dc8SJohn Baldwin 		follow_fork_parent();
610*98685dc8SJohn Baldwin 	}
611*98685dc8SJohn Baldwin 
612*98685dc8SJohn Baldwin 	/* Parent process. */
613*98685dc8SJohn Baldwin 	children[0] = fpid;
614*98685dc8SJohn Baldwin 
615*98685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
616*98685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
617*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
618*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
619*98685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
620*98685dc8SJohn Baldwin 
621*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
622*98685dc8SJohn Baldwin 
623*98685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
624*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
625*98685dc8SJohn Baldwin 
626*98685dc8SJohn Baldwin 	children[1] = handle_fork_events(children[0]);
627*98685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
628*98685dc8SJohn Baldwin 
629*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
630*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
631*98685dc8SJohn Baldwin 
632*98685dc8SJohn Baldwin 	/*
633*98685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
634*98685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
635*98685dc8SJohn Baldwin 	 *
636*98685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
637*98685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
638*98685dc8SJohn Baldwin 	 * after the grandchild.
639*98685dc8SJohn Baldwin 	 */
640*98685dc8SJohn Baldwin 	wpid = wait(&status);
641*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
642*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
643*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
644*98685dc8SJohn Baldwin 
645*98685dc8SJohn Baldwin 	wpid = wait(&status);
646*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
647*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
648*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
649*98685dc8SJohn Baldwin 
650*98685dc8SJohn Baldwin 	wpid = wait(&status);
651*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
652*98685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
653*98685dc8SJohn Baldwin }
654*98685dc8SJohn Baldwin 
655*98685dc8SJohn Baldwin static void
656*98685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
657*98685dc8SJohn Baldwin {
658*98685dc8SJohn Baldwin 	pid_t fpid;
659*98685dc8SJohn Baldwin 
660*98685dc8SJohn Baldwin 	close(cpipe[0]);
661*98685dc8SJohn Baldwin 
662*98685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
663*98685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
664*98685dc8SJohn Baldwin 	if (fpid != 0)
665*98685dc8SJohn Baldwin 		exit(3);
666*98685dc8SJohn Baldwin 
667*98685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
668*98685dc8SJohn Baldwin 	fpid = getpid();
669*98685dc8SJohn Baldwin 	CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
670*98685dc8SJohn Baldwin 
671*98685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
672*98685dc8SJohn Baldwin 	CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
673*98685dc8SJohn Baldwin }
674*98685dc8SJohn Baldwin 
675*98685dc8SJohn Baldwin /*
676*98685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
677*98685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
678*98685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
679*98685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
680*98685dc8SJohn Baldwin  */
681*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
682*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
683*98685dc8SJohn Baldwin {
684*98685dc8SJohn Baldwin 	pid_t children[0], fpid, wpid;
685*98685dc8SJohn Baldwin 	int cpipe[2], status;
686*98685dc8SJohn Baldwin 
687*98685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
688*98685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
689*98685dc8SJohn Baldwin 	if (fpid == 0) {
690*98685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
691*98685dc8SJohn Baldwin 		follow_fork_parent();
692*98685dc8SJohn Baldwin 	}
693*98685dc8SJohn Baldwin 
694*98685dc8SJohn Baldwin 	/* Parent process. */
695*98685dc8SJohn Baldwin 	close(cpipe[1]);
696*98685dc8SJohn Baldwin 
697*98685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
698*98685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
699*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
700*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
701*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
702*98685dc8SJohn Baldwin 
703*98685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
704*98685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
705*98685dc8SJohn Baldwin 	    sizeof(children[0]));
706*98685dc8SJohn Baldwin 
707*98685dc8SJohn Baldwin 	/* Attach to the fork parent. */
708*98685dc8SJohn Baldwin 	attach_child(children[0]);
709*98685dc8SJohn Baldwin 
710*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
711*98685dc8SJohn Baldwin 
712*98685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
713*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
714*98685dc8SJohn Baldwin 
715*98685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
716*98685dc8SJohn Baldwin 	close(cpipe[0]);
717*98685dc8SJohn Baldwin 
718*98685dc8SJohn Baldwin 	children[1] = handle_fork_events(children[0]);
719*98685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
720*98685dc8SJohn Baldwin 
721*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
722*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
723*98685dc8SJohn Baldwin 
724*98685dc8SJohn Baldwin 	/*
725*98685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
726*98685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
727*98685dc8SJohn Baldwin 	 */
728*98685dc8SJohn Baldwin 	wpid = wait(&status);
729*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
730*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
731*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
732*98685dc8SJohn Baldwin 
733*98685dc8SJohn Baldwin 	wpid = wait(&status);
734*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
735*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
736*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
737*98685dc8SJohn Baldwin 
738*98685dc8SJohn Baldwin 	wpid = wait(&status);
739*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
740*98685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
741*98685dc8SJohn Baldwin }
742*98685dc8SJohn Baldwin 
743*98685dc8SJohn Baldwin /*
744*98685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
745*98685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
746*98685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
747*98685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
748*98685dc8SJohn Baldwin  */
749*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
750*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
751*98685dc8SJohn Baldwin {
752*98685dc8SJohn Baldwin 	pid_t children[0], fpid, wpid;
753*98685dc8SJohn Baldwin 	int cpipe[2], status;
754*98685dc8SJohn Baldwin 
755*98685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
756*98685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
757*98685dc8SJohn Baldwin 	if (fpid == 0) {
758*98685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
759*98685dc8SJohn Baldwin 		follow_fork_parent();
760*98685dc8SJohn Baldwin 	}
761*98685dc8SJohn Baldwin 
762*98685dc8SJohn Baldwin 	/* Parent process. */
763*98685dc8SJohn Baldwin 	close(cpipe[1]);
764*98685dc8SJohn Baldwin 
765*98685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
766*98685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
767*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
768*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
769*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
770*98685dc8SJohn Baldwin 
771*98685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
772*98685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
773*98685dc8SJohn Baldwin 	    sizeof(children[0]));
774*98685dc8SJohn Baldwin 
775*98685dc8SJohn Baldwin 	/* Attach to the fork parent. */
776*98685dc8SJohn Baldwin 	attach_child(children[0]);
777*98685dc8SJohn Baldwin 
778*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
779*98685dc8SJohn Baldwin 
780*98685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
781*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
782*98685dc8SJohn Baldwin 
783*98685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
784*98685dc8SJohn Baldwin 	close(cpipe[0]);
785*98685dc8SJohn Baldwin 
786*98685dc8SJohn Baldwin 	children[1] = handle_fork_events(children[0]);
787*98685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
788*98685dc8SJohn Baldwin 
789*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
790*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
791*98685dc8SJohn Baldwin 
792*98685dc8SJohn Baldwin 	/*
793*98685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
794*98685dc8SJohn Baldwin 	 * parent.
795*98685dc8SJohn Baldwin 	 */
796*98685dc8SJohn Baldwin 	wpid = wait(&status);
797*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
798*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
799*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
800*98685dc8SJohn Baldwin 
801*98685dc8SJohn Baldwin 	wpid = wait(&status);
802*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
803*98685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
804*98685dc8SJohn Baldwin }
805*98685dc8SJohn Baldwin 
806*98685dc8SJohn Baldwin /*
807*98685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
808*98685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
809*98685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
810*98685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
811*98685dc8SJohn Baldwin  */
812*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
813*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
814*98685dc8SJohn Baldwin {
815*98685dc8SJohn Baldwin 	pid_t children[0], fpid, wpid;
816*98685dc8SJohn Baldwin 	int cpipe[2], status;
817*98685dc8SJohn Baldwin 
818*98685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
819*98685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
820*98685dc8SJohn Baldwin 	if (fpid == 0) {
821*98685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
822*98685dc8SJohn Baldwin 		follow_fork_parent();
823*98685dc8SJohn Baldwin 	}
824*98685dc8SJohn Baldwin 
825*98685dc8SJohn Baldwin 	/* Parent process. */
826*98685dc8SJohn Baldwin 	close(cpipe[1]);
827*98685dc8SJohn Baldwin 
828*98685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
829*98685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
830*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
831*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
832*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
833*98685dc8SJohn Baldwin 
834*98685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
835*98685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
836*98685dc8SJohn Baldwin 	    sizeof(children[0]));
837*98685dc8SJohn Baldwin 
838*98685dc8SJohn Baldwin 	/* Attach to the fork parent. */
839*98685dc8SJohn Baldwin 	attach_child(children[0]);
840*98685dc8SJohn Baldwin 
841*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
842*98685dc8SJohn Baldwin 
843*98685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
844*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
845*98685dc8SJohn Baldwin 
846*98685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
847*98685dc8SJohn Baldwin 	close(cpipe[0]);
848*98685dc8SJohn Baldwin 
849*98685dc8SJohn Baldwin 	children[1] = handle_fork_events(children[0]);
850*98685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
851*98685dc8SJohn Baldwin 
852*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
853*98685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
854*98685dc8SJohn Baldwin 
855*98685dc8SJohn Baldwin 	/*
856*98685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
857*98685dc8SJohn Baldwin 	 * the child.
858*98685dc8SJohn Baldwin 	 */
859*98685dc8SJohn Baldwin 	wpid = wait(&status);
860*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
861*98685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
862*98685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
863*98685dc8SJohn Baldwin 
864*98685dc8SJohn Baldwin 	wpid = wait(&status);
865*98685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
866*98685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
867*98685dc8SJohn Baldwin }
868*98685dc8SJohn Baldwin 
869c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
870c209e3e2SJohn Baldwin {
871c209e3e2SJohn Baldwin 
872c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
873c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
87457c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
87557c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
876*98685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
877*98685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
878*98685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
879*98685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
880*98685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
881*98685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
882*98685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
883*98685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
884c209e3e2SJohn Baldwin 
885c209e3e2SJohn Baldwin 	return (atf_no_error());
886c209e3e2SJohn Baldwin }
887