xref: /freebsd/tests/sys/kern/ptrace_test.c (revision e72879e554a04c16f263f5dcb071783d519f9524)
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>
32189ac973SJohn Baldwin #include <sys/syscall.h>
3357c74f5bSJohn Baldwin #include <sys/sysctl.h>
3457c74f5bSJohn Baldwin #include <sys/user.h>
35c209e3e2SJohn Baldwin #include <sys/wait.h>
36c209e3e2SJohn Baldwin #include <errno.h>
37189ac973SJohn Baldwin #include <pthread.h>
38c209e3e2SJohn Baldwin #include <signal.h>
39dfa8ba12SJohn Baldwin #include <stdio.h>
40c209e3e2SJohn Baldwin #include <stdlib.h>
41c209e3e2SJohn Baldwin #include <unistd.h>
42c209e3e2SJohn Baldwin #include <atf-c.h>
43c209e3e2SJohn Baldwin 
44c209e3e2SJohn Baldwin /*
45dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
46dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
47dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
48dfa8ba12SJohn Baldwin  */
49dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {						\
50dfa8ba12SJohn Baldwin 		if (!(exp))						\
51dfa8ba12SJohn Baldwin 			child_fail_require(__FILE__, __LINE__,		\
52dfa8ba12SJohn Baldwin 			    #exp " not met");				\
53dfa8ba12SJohn Baldwin 	} while (0)
54dfa8ba12SJohn Baldwin 
5598685dc8SJohn Baldwin static __dead2 void
56dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str)
57dfa8ba12SJohn Baldwin {
58dfa8ba12SJohn Baldwin 	char buf[128];
59dfa8ba12SJohn Baldwin 
60dfa8ba12SJohn Baldwin 	snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str);
61dfa8ba12SJohn Baldwin 	write(2, buf, strlen(buf));
62dfa8ba12SJohn Baldwin 	_exit(32);
63dfa8ba12SJohn Baldwin }
64dfa8ba12SJohn Baldwin 
6598685dc8SJohn Baldwin static void
6698685dc8SJohn Baldwin trace_me(void)
6798685dc8SJohn Baldwin {
6898685dc8SJohn Baldwin 
6998685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
7098685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7198685dc8SJohn Baldwin 
7298685dc8SJohn Baldwin 	/* Trigger a stop. */
7398685dc8SJohn Baldwin 	raise(SIGSTOP);
7498685dc8SJohn Baldwin }
7598685dc8SJohn Baldwin 
7698685dc8SJohn Baldwin static void
7798685dc8SJohn Baldwin attach_child(pid_t pid)
7898685dc8SJohn Baldwin {
7998685dc8SJohn Baldwin 	pid_t wpid;
8098685dc8SJohn Baldwin 	int status;
8198685dc8SJohn Baldwin 
8298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
8398685dc8SJohn Baldwin 
8498685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
8598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == pid);
8698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
8798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
8898685dc8SJohn Baldwin }
8998685dc8SJohn Baldwin 
9098685dc8SJohn Baldwin static void
9198685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
9298685dc8SJohn Baldwin {
9398685dc8SJohn Baldwin 
9498685dc8SJohn Baldwin 	/*
9598685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
9698685dc8SJohn Baldwin 	 * there is not a better way.
9798685dc8SJohn Baldwin 	 */
9898685dc8SJohn Baldwin 	for (;;) {
9998685dc8SJohn Baldwin 		struct kinfo_proc kp;
10098685dc8SJohn Baldwin 		size_t len;
10198685dc8SJohn Baldwin 		int mib[4];
10298685dc8SJohn Baldwin 
10398685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
10498685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
10598685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
10698685dc8SJohn Baldwin 		mib[3] = pid;
10798685dc8SJohn Baldwin 		len = sizeof(kp);
10898685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
10998685dc8SJohn Baldwin 			/* The KERN_PROC_PID sysctl fails for zombies. */
11098685dc8SJohn Baldwin 			ATF_REQUIRE(errno == ESRCH);
11198685dc8SJohn Baldwin 			break;
11298685dc8SJohn Baldwin 		}
11398685dc8SJohn Baldwin 		usleep(5000);
11498685dc8SJohn Baldwin 	}
11598685dc8SJohn Baldwin }
11698685dc8SJohn Baldwin 
117dfa8ba12SJohn Baldwin /*
118c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
119c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
120c209e3e2SJohn Baldwin  */
121c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
122c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
123c209e3e2SJohn Baldwin {
124c209e3e2SJohn Baldwin 	pid_t child, wpid;
125c209e3e2SJohn Baldwin 	int status;
126c209e3e2SJohn Baldwin 
127c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
128c209e3e2SJohn Baldwin 	if (child == 0) {
129c209e3e2SJohn Baldwin 		/* Child process. */
13098685dc8SJohn Baldwin 		trace_me();
131c209e3e2SJohn Baldwin 
132b98cb919SJohn Baldwin 		_exit(1);
133c209e3e2SJohn Baldwin 	}
134c209e3e2SJohn Baldwin 
135c209e3e2SJohn Baldwin 	/* Parent process. */
136c209e3e2SJohn Baldwin 
137c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
138c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
139c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
140c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
141c209e3e2SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
142c209e3e2SJohn Baldwin 
143c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
144c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
145c209e3e2SJohn Baldwin 
146c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
147c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
148c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
149c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
150c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
151c209e3e2SJohn Baldwin 
152c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
153c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
154c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
155c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
156c209e3e2SJohn Baldwin }
157c209e3e2SJohn Baldwin 
158c209e3e2SJohn Baldwin /*
159c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
160c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
161c209e3e2SJohn Baldwin  */
162c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
163c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
164c209e3e2SJohn Baldwin {
165c209e3e2SJohn Baldwin 	pid_t child, wpid;
166c209e3e2SJohn Baldwin 	int cpipe[2], status;
167c209e3e2SJohn Baldwin 	char c;
168c209e3e2SJohn Baldwin 
169c209e3e2SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
170c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
171c209e3e2SJohn Baldwin 	if (child == 0) {
172c209e3e2SJohn Baldwin 		/* Child process. */
173c209e3e2SJohn Baldwin 		close(cpipe[0]);
174c209e3e2SJohn Baldwin 
175c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
176dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0);
177c209e3e2SJohn Baldwin 
178b98cb919SJohn Baldwin 		_exit(1);
179c209e3e2SJohn Baldwin 	}
180c209e3e2SJohn Baldwin 	close(cpipe[1]);
181c209e3e2SJohn Baldwin 
182c209e3e2SJohn Baldwin 	/* Parent process. */
183c209e3e2SJohn Baldwin 
184c209e3e2SJohn Baldwin 	/* Attach to the child process. */
18598685dc8SJohn Baldwin 	attach_child(child);
186c209e3e2SJohn Baldwin 
187c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
188c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
189c209e3e2SJohn Baldwin 
190c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
191c209e3e2SJohn Baldwin 	close(cpipe[0]);
192c209e3e2SJohn Baldwin 
193c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
194c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
195c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
196c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
197c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
198c209e3e2SJohn Baldwin 
199c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
200c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
201c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
202c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
203c209e3e2SJohn Baldwin }
204c209e3e2SJohn Baldwin 
20557c74f5bSJohn Baldwin /*
20657c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
20757c74f5bSJohn Baldwin  * after the debugger has seen it.
20857c74f5bSJohn Baldwin  */
20957c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
21057c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
21157c74f5bSJohn Baldwin {
21257c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
21357c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
21457c74f5bSJohn Baldwin 	char c;
21557c74f5bSJohn Baldwin 
21657c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
21757c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
21857c74f5bSJohn Baldwin 
21957c74f5bSJohn Baldwin 	if (child == 0) {
22057c74f5bSJohn Baldwin 		/* Child process. */
22157c74f5bSJohn Baldwin 		close(cpipe[0]);
22257c74f5bSJohn Baldwin 
22357c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
224dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
22557c74f5bSJohn Baldwin 
226b98cb919SJohn Baldwin 		_exit(1);
22757c74f5bSJohn Baldwin 	}
22857c74f5bSJohn Baldwin 	close(cpipe[1]);
22957c74f5bSJohn Baldwin 
23057c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
23157c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
23257c74f5bSJohn Baldwin 
23357c74f5bSJohn Baldwin 	if (debugger == 0) {
23457c74f5bSJohn Baldwin 		/* Debugger process. */
23557c74f5bSJohn Baldwin 		close(dpipe[0]);
23657c74f5bSJohn Baldwin 
237dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
23857c74f5bSJohn Baldwin 
23957c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
240dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
241dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
242dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
24357c74f5bSJohn Baldwin 
244dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
24557c74f5bSJohn Baldwin 
24657c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
247dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
24857c74f5bSJohn Baldwin 
24957c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
250dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0);
25157c74f5bSJohn Baldwin 
25257c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
253dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
254dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
255dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
25657c74f5bSJohn Baldwin 
257b98cb919SJohn Baldwin 		_exit(0);
25857c74f5bSJohn Baldwin 	}
25957c74f5bSJohn Baldwin 	close(dpipe[1]);
26057c74f5bSJohn Baldwin 
26157c74f5bSJohn Baldwin 	/* Parent process. */
26257c74f5bSJohn Baldwin 
26357c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
26457c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
26557c74f5bSJohn Baldwin 
26657c74f5bSJohn Baldwin 	/* Release the child. */
26757c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
26857c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
26957c74f5bSJohn Baldwin 	close(cpipe[0]);
27057c74f5bSJohn Baldwin 
27198685dc8SJohn Baldwin 	wait_for_zombie(child);
27257c74f5bSJohn Baldwin 
27357c74f5bSJohn Baldwin 	/*
2742f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
2752f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
2762f021998SJohn Baldwin 	 * until the debugger sees the exit.
27757c74f5bSJohn Baldwin 	 */
27857c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
27957c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
28057c74f5bSJohn Baldwin 
28157c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
28257c74f5bSJohn Baldwin 	close(dpipe[0]);
28357c74f5bSJohn Baldwin 
28457c74f5bSJohn Baldwin 	/* Wait for the debugger. */
28557c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
28657c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
28757c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
28857c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
28957c74f5bSJohn Baldwin 
29057c74f5bSJohn Baldwin 	/* The child process should now be ready. */
29157c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
29257c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
29357c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
29457c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
29557c74f5bSJohn Baldwin }
29657c74f5bSJohn Baldwin 
29757c74f5bSJohn Baldwin /*
29857c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
29957c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
30057c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
30157c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
30257c74f5bSJohn Baldwin  */
30357c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
30457c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
30557c74f5bSJohn Baldwin {
30657c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
30757c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
30857c74f5bSJohn Baldwin 	char c;
30957c74f5bSJohn Baldwin 
31057c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
31157c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
31257c74f5bSJohn Baldwin 
31357c74f5bSJohn Baldwin 	if (child == 0) {
31457c74f5bSJohn Baldwin 		/* Child process. */
31557c74f5bSJohn Baldwin 		close(cpipe[0]);
31657c74f5bSJohn Baldwin 
31757c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
318dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
31957c74f5bSJohn Baldwin 
320b98cb919SJohn Baldwin 		_exit(1);
32157c74f5bSJohn Baldwin 	}
32257c74f5bSJohn Baldwin 	close(cpipe[1]);
32357c74f5bSJohn Baldwin 
32457c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
32557c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
32657c74f5bSJohn Baldwin 
32757c74f5bSJohn Baldwin 	if (debugger == 0) {
32857c74f5bSJohn Baldwin 		/* Debugger parent. */
32957c74f5bSJohn Baldwin 
33057c74f5bSJohn Baldwin 		/*
33157c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
33257c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
33357c74f5bSJohn Baldwin 		 */
334dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
33557c74f5bSJohn Baldwin 		if (fpid != 0)
336b98cb919SJohn Baldwin 			_exit(2);
33757c74f5bSJohn Baldwin 
33857c74f5bSJohn Baldwin 		/* Debugger process. */
33957c74f5bSJohn Baldwin 		close(dpipe[0]);
34057c74f5bSJohn Baldwin 
341dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
34257c74f5bSJohn Baldwin 
34357c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
344dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
345dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
346dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
34757c74f5bSJohn Baldwin 
348dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
34957c74f5bSJohn Baldwin 
35057c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
351dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
35257c74f5bSJohn Baldwin 
35357c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
354dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c));
35557c74f5bSJohn Baldwin 
35657c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
357dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
358dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
359dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
36057c74f5bSJohn Baldwin 
361b98cb919SJohn Baldwin 		_exit(0);
36257c74f5bSJohn Baldwin 	}
363eddb85c6SJohn Baldwin 	close(dpipe[1]);
36457c74f5bSJohn Baldwin 
36557c74f5bSJohn Baldwin 	/* Parent process. */
36657c74f5bSJohn Baldwin 
36757c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
36857c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
36957c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
37057c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
37157c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
37257c74f5bSJohn Baldwin 
37357c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
37457c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
37557c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
37657c74f5bSJohn Baldwin 
37757c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
37857c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
37957c74f5bSJohn Baldwin 
38057c74f5bSJohn Baldwin 	/* Release the child. */
38157c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
38257c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
38357c74f5bSJohn Baldwin 	close(cpipe[0]);
38457c74f5bSJohn Baldwin 
38598685dc8SJohn Baldwin 	wait_for_zombie(child);
38657c74f5bSJohn Baldwin 
38757c74f5bSJohn Baldwin 	/*
3882f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3892f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3902f021998SJohn Baldwin 	 * until the debugger sees the exit.
39157c74f5bSJohn Baldwin 	 */
39257c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
39357c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
39457c74f5bSJohn Baldwin 
39557c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
396eddb85c6SJohn Baldwin 	ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c));
39757c74f5bSJohn Baldwin 
39857c74f5bSJohn Baldwin 	/* Wait for the debugger. */
399eddb85c6SJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0);
400eddb85c6SJohn Baldwin 	close(dpipe[0]);
40157c74f5bSJohn Baldwin 
40257c74f5bSJohn Baldwin 	/* The child process should now be ready. */
40357c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
40457c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
40557c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
40657c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
40757c74f5bSJohn Baldwin }
40857c74f5bSJohn Baldwin 
40998685dc8SJohn Baldwin /*
41098685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
41198685dc8SJohn Baldwin  * debugger is attached to it.
41298685dc8SJohn Baldwin  */
41398685dc8SJohn Baldwin static __dead2 void
414189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
41598685dc8SJohn Baldwin {
41698685dc8SJohn Baldwin 	pid_t fpid, wpid;
41798685dc8SJohn Baldwin 	int status;
41898685dc8SJohn Baldwin 
419189ac973SJohn Baldwin 	if (use_vfork)
420189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
421189ac973SJohn Baldwin 	else
42298685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
42398685dc8SJohn Baldwin 
42498685dc8SJohn Baldwin 	if (fpid == 0)
42598685dc8SJohn Baldwin 		/* Child */
426b98cb919SJohn Baldwin 		_exit(2);
42798685dc8SJohn Baldwin 
42898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
42998685dc8SJohn Baldwin 	CHILD_REQUIRE(wpid == fpid);
43098685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
43198685dc8SJohn Baldwin 	CHILD_REQUIRE(WEXITSTATUS(status) == 2);
43298685dc8SJohn Baldwin 
433b98cb919SJohn Baldwin 	_exit(1);
43498685dc8SJohn Baldwin }
43598685dc8SJohn Baldwin 
43698685dc8SJohn Baldwin /*
43798685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
43898685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
43998685dc8SJohn Baldwin  * child process.
44098685dc8SJohn Baldwin  */
44198685dc8SJohn Baldwin static pid_t
442189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
44398685dc8SJohn Baldwin {
44498685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
44598685dc8SJohn Baldwin 	bool fork_reported[2];
44698685dc8SJohn Baldwin 	pid_t child, wpid;
44798685dc8SJohn Baldwin 	int i, status;
44898685dc8SJohn Baldwin 
44998685dc8SJohn Baldwin 	fork_reported[0] = false;
45098685dc8SJohn Baldwin 	fork_reported[1] = false;
45198685dc8SJohn Baldwin 	child = -1;
45298685dc8SJohn Baldwin 
45398685dc8SJohn Baldwin 	/*
45498685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
45598685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
45698685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
45798685dc8SJohn Baldwin 	 */
45898685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
45998685dc8SJohn Baldwin 		wpid = wait(&status);
46098685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
46198685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
46298685dc8SJohn Baldwin 
46398685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
46498685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
46598685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
46698685dc8SJohn Baldwin 		    0);
46798685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
46898685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
46998685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
47098685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
47198685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
47298685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
47398685dc8SJohn Baldwin 			if (child == -1)
47498685dc8SJohn Baldwin 				child = wpid;
47598685dc8SJohn Baldwin 			else
47698685dc8SJohn Baldwin 				ATF_REQUIRE(child == wpid);
477189ac973SJohn Baldwin 			if (ppl != NULL)
478189ac973SJohn Baldwin 				ppl[1] = pl;
47998685dc8SJohn Baldwin 			fork_reported[1] = true;
48098685dc8SJohn Baldwin 		} else {
48198685dc8SJohn Baldwin 			ATF_REQUIRE(wpid == parent);
48298685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
48398685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
48498685dc8SJohn Baldwin 			if (child == -1)
48598685dc8SJohn Baldwin 				child = pl.pl_child_pid;
48698685dc8SJohn Baldwin 			else
48798685dc8SJohn Baldwin 				ATF_REQUIRE(child == pl.pl_child_pid);
488189ac973SJohn Baldwin 			if (ppl != NULL)
489189ac973SJohn Baldwin 				ppl[0] = pl;
49098685dc8SJohn Baldwin 			fork_reported[0] = true;
49198685dc8SJohn Baldwin 		}
49298685dc8SJohn Baldwin 	}
49398685dc8SJohn Baldwin 
49498685dc8SJohn Baldwin 	return (child);
49598685dc8SJohn Baldwin }
49698685dc8SJohn Baldwin 
49798685dc8SJohn Baldwin /*
49898685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
49998685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
50098685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
50198685dc8SJohn Baldwin  */
50298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
50398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
50498685dc8SJohn Baldwin {
505479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
50698685dc8SJohn Baldwin 	int status;
50798685dc8SJohn Baldwin 
50898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
50998685dc8SJohn Baldwin 	if (fpid == 0) {
51098685dc8SJohn Baldwin 		trace_me();
511189ac973SJohn Baldwin 		follow_fork_parent(false);
51298685dc8SJohn Baldwin 	}
51398685dc8SJohn Baldwin 
51498685dc8SJohn Baldwin 	/* Parent process. */
51598685dc8SJohn Baldwin 	children[0] = fpid;
51698685dc8SJohn Baldwin 
51798685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
51898685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
51998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
52098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
52198685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
52298685dc8SJohn Baldwin 
52398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
52498685dc8SJohn Baldwin 
52598685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
52698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
52798685dc8SJohn Baldwin 
528189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
52998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
53098685dc8SJohn Baldwin 
53198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
53298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
53398685dc8SJohn Baldwin 
53498685dc8SJohn Baldwin 	/*
53598685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
53698685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
53798685dc8SJohn Baldwin 	 */
53898685dc8SJohn Baldwin 	wpid = wait(&status);
53998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
54098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
54198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
54298685dc8SJohn Baldwin 
54398685dc8SJohn Baldwin 	wpid = wait(&status);
54498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
54598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
54698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
54798685dc8SJohn Baldwin 
54898685dc8SJohn Baldwin 	wpid = wait(&status);
54998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
55098685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
55198685dc8SJohn Baldwin }
55298685dc8SJohn Baldwin 
55398685dc8SJohn Baldwin /*
55498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
55598685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
55698685dc8SJohn Baldwin  * child process is detached after it reports its fork.
55798685dc8SJohn Baldwin  */
55898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
55998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
56098685dc8SJohn Baldwin {
561479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
56298685dc8SJohn Baldwin 	int status;
56398685dc8SJohn Baldwin 
56498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
56598685dc8SJohn Baldwin 	if (fpid == 0) {
56698685dc8SJohn Baldwin 		trace_me();
567189ac973SJohn Baldwin 		follow_fork_parent(false);
56898685dc8SJohn Baldwin 	}
56998685dc8SJohn Baldwin 
57098685dc8SJohn Baldwin 	/* Parent process. */
57198685dc8SJohn Baldwin 	children[0] = fpid;
57298685dc8SJohn Baldwin 
57398685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
57498685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
57598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
57698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
57798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
57898685dc8SJohn Baldwin 
57998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
58098685dc8SJohn Baldwin 
58198685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
58298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
58398685dc8SJohn Baldwin 
584189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
58598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
58698685dc8SJohn Baldwin 
58798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
58898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
58998685dc8SJohn Baldwin 
59098685dc8SJohn Baldwin 	/*
59198685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
59298685dc8SJohn Baldwin 	 * child.
59398685dc8SJohn Baldwin 	 */
59498685dc8SJohn Baldwin 	wpid = wait(&status);
59598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
59698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
59798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
59898685dc8SJohn Baldwin 
59998685dc8SJohn Baldwin 	wpid = wait(&status);
60098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
60198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
60298685dc8SJohn Baldwin }
60398685dc8SJohn Baldwin 
60498685dc8SJohn Baldwin /*
60598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
60698685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
60798685dc8SJohn Baldwin  * traced parent is detached after the fork.
60898685dc8SJohn Baldwin  */
60998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
61098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
61198685dc8SJohn Baldwin {
612479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
61398685dc8SJohn Baldwin 	int status;
61498685dc8SJohn Baldwin 
61598685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
61698685dc8SJohn Baldwin 	if (fpid == 0) {
61798685dc8SJohn Baldwin 		trace_me();
618189ac973SJohn Baldwin 		follow_fork_parent(false);
61998685dc8SJohn Baldwin 	}
62098685dc8SJohn Baldwin 
62198685dc8SJohn Baldwin 	/* Parent process. */
62298685dc8SJohn Baldwin 	children[0] = fpid;
62398685dc8SJohn Baldwin 
62498685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
62598685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
62698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
62798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
62898685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
62998685dc8SJohn Baldwin 
63098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
63198685dc8SJohn Baldwin 
63298685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
63398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
63498685dc8SJohn Baldwin 
635189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
63698685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
63798685dc8SJohn Baldwin 
63898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
63998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
64098685dc8SJohn Baldwin 
64198685dc8SJohn Baldwin 	/*
64298685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
64398685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
64498685dc8SJohn Baldwin 	 *
64598685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
64698685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
64798685dc8SJohn Baldwin 	 * after the grandchild.
64898685dc8SJohn Baldwin 	 */
64998685dc8SJohn Baldwin 	wpid = wait(&status);
65098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
65198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
65298685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
65398685dc8SJohn Baldwin 
65498685dc8SJohn Baldwin 	wpid = wait(&status);
65598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
65698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
65798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
65898685dc8SJohn Baldwin 
65998685dc8SJohn Baldwin 	wpid = wait(&status);
66098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
66198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
66298685dc8SJohn Baldwin }
66398685dc8SJohn Baldwin 
66498685dc8SJohn Baldwin static void
66598685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
66698685dc8SJohn Baldwin {
66798685dc8SJohn Baldwin 	pid_t fpid;
66898685dc8SJohn Baldwin 
66998685dc8SJohn Baldwin 	close(cpipe[0]);
67098685dc8SJohn Baldwin 
67198685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
67298685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
67398685dc8SJohn Baldwin 	if (fpid != 0)
674b98cb919SJohn Baldwin 		_exit(3);
67598685dc8SJohn Baldwin 
67698685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
67798685dc8SJohn Baldwin 	fpid = getpid();
67898685dc8SJohn Baldwin 	CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
67998685dc8SJohn Baldwin 
68098685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
68198685dc8SJohn Baldwin 	CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
68298685dc8SJohn Baldwin }
68398685dc8SJohn Baldwin 
68498685dc8SJohn Baldwin /*
68598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
68698685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
68798685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
68898685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
68998685dc8SJohn Baldwin  */
69098685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
69198685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
69298685dc8SJohn Baldwin {
693479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
69498685dc8SJohn Baldwin 	int cpipe[2], status;
69598685dc8SJohn Baldwin 
69698685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
69798685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
69898685dc8SJohn Baldwin 	if (fpid == 0) {
69998685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
700189ac973SJohn Baldwin 		follow_fork_parent(false);
70198685dc8SJohn Baldwin 	}
70298685dc8SJohn Baldwin 
70398685dc8SJohn Baldwin 	/* Parent process. */
70498685dc8SJohn Baldwin 	close(cpipe[1]);
70598685dc8SJohn Baldwin 
70698685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
70798685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
70898685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
70998685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
71098685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
71198685dc8SJohn Baldwin 
71298685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
71398685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
71498685dc8SJohn Baldwin 	    sizeof(children[0]));
71598685dc8SJohn Baldwin 
71698685dc8SJohn Baldwin 	/* Attach to the fork parent. */
71798685dc8SJohn Baldwin 	attach_child(children[0]);
71898685dc8SJohn Baldwin 
71998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
72098685dc8SJohn Baldwin 
72198685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
72298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
72398685dc8SJohn Baldwin 
72498685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
72598685dc8SJohn Baldwin 	close(cpipe[0]);
72698685dc8SJohn Baldwin 
727189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
72898685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
72998685dc8SJohn Baldwin 
73098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
73198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
73298685dc8SJohn Baldwin 
73398685dc8SJohn Baldwin 	/*
73498685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
73598685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
73698685dc8SJohn Baldwin 	 */
73798685dc8SJohn Baldwin 	wpid = wait(&status);
73898685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
73998685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
74098685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
74198685dc8SJohn Baldwin 
74298685dc8SJohn Baldwin 	wpid = wait(&status);
74398685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
74498685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
74598685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
74698685dc8SJohn Baldwin 
74798685dc8SJohn Baldwin 	wpid = wait(&status);
74898685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
74998685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
75098685dc8SJohn Baldwin }
75198685dc8SJohn Baldwin 
75298685dc8SJohn Baldwin /*
75398685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
75498685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
75598685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
75698685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
75798685dc8SJohn Baldwin  */
75898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
75998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
76098685dc8SJohn Baldwin {
761479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
76298685dc8SJohn Baldwin 	int cpipe[2], status;
76398685dc8SJohn Baldwin 
76498685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
76598685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
76698685dc8SJohn Baldwin 	if (fpid == 0) {
76798685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
768189ac973SJohn Baldwin 		follow_fork_parent(false);
76998685dc8SJohn Baldwin 	}
77098685dc8SJohn Baldwin 
77198685dc8SJohn Baldwin 	/* Parent process. */
77298685dc8SJohn Baldwin 	close(cpipe[1]);
77398685dc8SJohn Baldwin 
77498685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
77598685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
77698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
77798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
77898685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
77998685dc8SJohn Baldwin 
78098685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
78198685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
78298685dc8SJohn Baldwin 	    sizeof(children[0]));
78398685dc8SJohn Baldwin 
78498685dc8SJohn Baldwin 	/* Attach to the fork parent. */
78598685dc8SJohn Baldwin 	attach_child(children[0]);
78698685dc8SJohn Baldwin 
78798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
78898685dc8SJohn Baldwin 
78998685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
79098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
79198685dc8SJohn Baldwin 
79298685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
79398685dc8SJohn Baldwin 	close(cpipe[0]);
79498685dc8SJohn Baldwin 
795189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
79698685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
79798685dc8SJohn Baldwin 
79898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
79998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
80098685dc8SJohn Baldwin 
80198685dc8SJohn Baldwin 	/*
80298685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
80398685dc8SJohn Baldwin 	 * parent.
80498685dc8SJohn Baldwin 	 */
80598685dc8SJohn Baldwin 	wpid = wait(&status);
80698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
80798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
80898685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
80998685dc8SJohn Baldwin 
81098685dc8SJohn Baldwin 	wpid = wait(&status);
81198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
81298685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
81398685dc8SJohn Baldwin }
81498685dc8SJohn Baldwin 
81598685dc8SJohn Baldwin /*
81698685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
81798685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
81898685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
81998685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
82098685dc8SJohn Baldwin  */
82198685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
82298685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
82398685dc8SJohn Baldwin {
824479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
82598685dc8SJohn Baldwin 	int cpipe[2], status;
82698685dc8SJohn Baldwin 
82798685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
82898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
82998685dc8SJohn Baldwin 	if (fpid == 0) {
83098685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
831189ac973SJohn Baldwin 		follow_fork_parent(false);
83298685dc8SJohn Baldwin 	}
83398685dc8SJohn Baldwin 
83498685dc8SJohn Baldwin 	/* Parent process. */
83598685dc8SJohn Baldwin 	close(cpipe[1]);
83698685dc8SJohn Baldwin 
83798685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
83898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
83998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
84098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
84198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
84298685dc8SJohn Baldwin 
84398685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
84498685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
84598685dc8SJohn Baldwin 	    sizeof(children[0]));
84698685dc8SJohn Baldwin 
84798685dc8SJohn Baldwin 	/* Attach to the fork parent. */
84898685dc8SJohn Baldwin 	attach_child(children[0]);
84998685dc8SJohn Baldwin 
85098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
85198685dc8SJohn Baldwin 
85298685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
85398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
85498685dc8SJohn Baldwin 
85598685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
85698685dc8SJohn Baldwin 	close(cpipe[0]);
85798685dc8SJohn Baldwin 
858189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
85998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
86098685dc8SJohn Baldwin 
86198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
86298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
86398685dc8SJohn Baldwin 
86498685dc8SJohn Baldwin 	/*
86598685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
86698685dc8SJohn Baldwin 	 * the child.
86798685dc8SJohn Baldwin 	 */
86898685dc8SJohn Baldwin 	wpid = wait(&status);
86998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
87098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
87198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
87298685dc8SJohn Baldwin 
87398685dc8SJohn Baldwin 	wpid = wait(&status);
87498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
87598685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
87698685dc8SJohn Baldwin }
87798685dc8SJohn Baldwin 
878368b2b1cSJohn Baldwin /*
879368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
880368b2b1cSJohn Baldwin  * parent but sees its original parent process.
881368b2b1cSJohn Baldwin  */
882368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
883368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
884368b2b1cSJohn Baldwin {
885368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
886368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
887368b2b1cSJohn Baldwin 	char c;
888368b2b1cSJohn Baldwin 
889368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
890368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
891368b2b1cSJohn Baldwin 
892368b2b1cSJohn Baldwin 	if (child == 0) {
893368b2b1cSJohn Baldwin 		/* Child process. */
894368b2b1cSJohn Baldwin 		close(cpipe[0]);
895368b2b1cSJohn Baldwin 
896368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
897368b2b1cSJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
898368b2b1cSJohn Baldwin 
899368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
900368b2b1cSJohn Baldwin 		ppid = getppid();
901368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) ==
902368b2b1cSJohn Baldwin 		    sizeof(ppid));
903368b2b1cSJohn Baldwin 
904368b2b1cSJohn Baldwin 		_exit(1);
905368b2b1cSJohn Baldwin 	}
906368b2b1cSJohn Baldwin 	close(cpipe[1]);
907368b2b1cSJohn Baldwin 
908368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
909368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
910368b2b1cSJohn Baldwin 
911368b2b1cSJohn Baldwin 	if (debugger == 0) {
912368b2b1cSJohn Baldwin 		/* Debugger process. */
913368b2b1cSJohn Baldwin 		close(dpipe[0]);
914368b2b1cSJohn Baldwin 
915368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
916368b2b1cSJohn Baldwin 
917368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
918368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
919368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
920368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
921368b2b1cSJohn Baldwin 
922368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
923368b2b1cSJohn Baldwin 
924368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
925368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
926368b2b1cSJohn Baldwin 
927368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
928368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
929368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
930368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
931368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
932368b2b1cSJohn Baldwin 
933368b2b1cSJohn Baldwin 		_exit(0);
934368b2b1cSJohn Baldwin 	}
935368b2b1cSJohn Baldwin 	close(dpipe[1]);
936368b2b1cSJohn Baldwin 
937368b2b1cSJohn Baldwin 	/* Parent process. */
938368b2b1cSJohn Baldwin 
939368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
940368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
941368b2b1cSJohn Baldwin 
942368b2b1cSJohn Baldwin 	/* Release the child. */
943368b2b1cSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
944368b2b1cSJohn Baldwin 
945368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
946368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid));
947368b2b1cSJohn Baldwin 	close(cpipe[0]);
948368b2b1cSJohn Baldwin 
949368b2b1cSJohn Baldwin 	ATF_REQUIRE(ppid == getpid());
950368b2b1cSJohn Baldwin 
951368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
952368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
953368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
954368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
955368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
956368b2b1cSJohn Baldwin 
957368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
958368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
959368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == child);
960368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
961368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
962368b2b1cSJohn Baldwin }
963368b2b1cSJohn Baldwin 
964189ac973SJohn Baldwin /*
965189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
966189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
967189ac973SJohn Baldwin  */
968189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
969189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
970189ac973SJohn Baldwin {
971189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
972189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
973189ac973SJohn Baldwin 	int status;
974189ac973SJohn Baldwin 
975189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
976189ac973SJohn Baldwin 	if (fpid == 0) {
977189ac973SJohn Baldwin 		trace_me();
978189ac973SJohn Baldwin 		follow_fork_parent(false);
979189ac973SJohn Baldwin 	}
980189ac973SJohn Baldwin 
981189ac973SJohn Baldwin 	/* Parent process. */
982189ac973SJohn Baldwin 	children[0] = fpid;
983189ac973SJohn Baldwin 
984189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
985189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
986189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
987189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
988189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
989189ac973SJohn Baldwin 
990189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
991189ac973SJohn Baldwin 
992189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
993189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
994189ac973SJohn Baldwin 
995189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
996189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
997189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
998189ac973SJohn Baldwin 
999189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1000189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1001189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork);
1002189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1003189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1004189ac973SJohn Baldwin 
1005189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1006189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1007189ac973SJohn Baldwin 
1008189ac973SJohn Baldwin 	/*
1009189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1010189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1011189ac973SJohn Baldwin 	 */
1012189ac973SJohn Baldwin 	wpid = wait(&status);
1013189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1014189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1015189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1016189ac973SJohn Baldwin 
1017189ac973SJohn Baldwin 	wpid = wait(&status);
1018189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1019189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1020189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1021189ac973SJohn Baldwin 
1022189ac973SJohn Baldwin 	wpid = wait(&status);
1023189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1024189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1025189ac973SJohn Baldwin }
1026189ac973SJohn Baldwin 
1027189ac973SJohn Baldwin /*
1028189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1029189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1030189ac973SJohn Baldwin  */
1031189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1032189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1033189ac973SJohn Baldwin {
1034189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1035189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1036189ac973SJohn Baldwin 	int status;
1037189ac973SJohn Baldwin 
1038189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1039189ac973SJohn Baldwin 	if (fpid == 0) {
1040189ac973SJohn Baldwin 		trace_me();
1041189ac973SJohn Baldwin 		follow_fork_parent(true);
1042189ac973SJohn Baldwin 	}
1043189ac973SJohn Baldwin 
1044189ac973SJohn Baldwin 	/* Parent process. */
1045189ac973SJohn Baldwin 	children[0] = fpid;
1046189ac973SJohn Baldwin 
1047189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1048189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1049189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1050189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1051189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1052189ac973SJohn Baldwin 
1053189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1054189ac973SJohn Baldwin 
1055189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1056189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1057189ac973SJohn Baldwin 
1058189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1059189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1060189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1061189ac973SJohn Baldwin 
1062189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1063189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1064189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork);
1065189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1066189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1067189ac973SJohn Baldwin 
1068189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1069189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1070189ac973SJohn Baldwin 
1071189ac973SJohn Baldwin 	/*
1072189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1073189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1074189ac973SJohn Baldwin 	 */
1075189ac973SJohn Baldwin 	wpid = wait(&status);
1076189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1077189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1078189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1079189ac973SJohn Baldwin 
1080189ac973SJohn Baldwin 	wpid = wait(&status);
1081189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1082189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1083189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1084189ac973SJohn Baldwin 
1085189ac973SJohn Baldwin 	wpid = wait(&status);
1086189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1087189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1088189ac973SJohn Baldwin }
1089189ac973SJohn Baldwin 
1090189ac973SJohn Baldwin static void *
1091189ac973SJohn Baldwin simple_thread(void *arg __unused)
1092189ac973SJohn Baldwin {
1093189ac973SJohn Baldwin 
1094189ac973SJohn Baldwin 	pthread_exit(NULL);
1095189ac973SJohn Baldwin }
1096189ac973SJohn Baldwin 
1097189ac973SJohn Baldwin /*
1098189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1099189ac973SJohn Baldwin  * thread reports the correct value.
1100189ac973SJohn Baldwin  */
1101189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1102189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1103189ac973SJohn Baldwin {
1104189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1105189ac973SJohn Baldwin 	pid_t fpid, wpid;
1106*e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1107189ac973SJohn Baldwin 	int status;
1108189ac973SJohn Baldwin 
1109189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1110189ac973SJohn Baldwin 	if (fpid == 0) {
1111189ac973SJohn Baldwin 		pthread_t thread;
1112189ac973SJohn Baldwin 
1113189ac973SJohn Baldwin 		trace_me();
1114189ac973SJohn Baldwin 
1115189ac973SJohn Baldwin 		CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread,
1116189ac973SJohn Baldwin 			NULL) == 0);
1117189ac973SJohn Baldwin 		CHILD_REQUIRE(pthread_join(thread, NULL) == 0);
1118189ac973SJohn Baldwin 		exit(1);
1119189ac973SJohn Baldwin 	}
1120189ac973SJohn Baldwin 
1121189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1122189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1123189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1124189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1125189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1126189ac973SJohn Baldwin 
1127189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1128189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1129*e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1130189ac973SJohn Baldwin 
1131189ac973SJohn Baldwin 	/*
1132189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1133189ac973SJohn Baldwin 	 * system call exits.
1134189ac973SJohn Baldwin 	 */
1135189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1136189ac973SJohn Baldwin 
1137189ac973SJohn Baldwin 	/*
1138189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1139189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1140189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1141189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1142189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1143189ac973SJohn Baldwin 	 */
1144189ac973SJohn Baldwin 	for (;;) {
1145189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1146189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1147189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1148189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1149189ac973SJohn Baldwin 
1150189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1151189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1152189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1153189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1154*e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1155189ac973SJohn Baldwin 			/* New thread seen. */
1156189ac973SJohn Baldwin 			break;
1157189ac973SJohn Baldwin 
1158189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1159189ac973SJohn Baldwin 	}
1160189ac973SJohn Baldwin 
1161189ac973SJohn Baldwin 	/* Wait for the child to exit. */
1162189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1163189ac973SJohn Baldwin 	for (;;) {
1164189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1165189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1166189ac973SJohn Baldwin 		if (WIFEXITED(status))
1167189ac973SJohn Baldwin 			break;
1168189ac973SJohn Baldwin 
1169189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1170189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1171189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1172189ac973SJohn Baldwin 	}
1173189ac973SJohn Baldwin 
1174189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1175189ac973SJohn Baldwin 
1176189ac973SJohn Baldwin 	wpid = wait(&status);
1177189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1178189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1179189ac973SJohn Baldwin }
1180189ac973SJohn Baldwin 
1181c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
1182c209e3e2SJohn Baldwin {
1183c209e3e2SJohn Baldwin 
1184c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
1185c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
118657c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
118757c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
118898685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
118998685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
119098685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
119198685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
119298685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
119398685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
119498685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
119598685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
1196368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
1197189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
1198189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
1199189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
1200c209e3e2SJohn Baldwin 
1201c209e3e2SJohn Baldwin 	return (atf_no_error());
1202c209e3e2SJohn Baldwin }
1203