xref: /freebsd/tests/sys/kern/ptrace_test.c (revision 128c9bc05baf1fa69638707801ede25ae7466b0d)
1c209e3e2SJohn Baldwin /*-
2c209e3e2SJohn Baldwin  * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
3c209e3e2SJohn Baldwin  *
4c209e3e2SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
5c209e3e2SJohn Baldwin  * modification, are permitted provided that the following conditions
6c209e3e2SJohn Baldwin  * are met:
7c209e3e2SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
8c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
9c209e3e2SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
10c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
11c209e3e2SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
12c209e3e2SJohn Baldwin  *
13c209e3e2SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14c209e3e2SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15c209e3e2SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16c209e3e2SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17c209e3e2SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18c209e3e2SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19c209e3e2SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20c209e3e2SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21c209e3e2SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22c209e3e2SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23c209e3e2SJohn Baldwin  * SUCH DAMAGE.
24c209e3e2SJohn Baldwin  */
25c209e3e2SJohn Baldwin 
26c209e3e2SJohn Baldwin #include <sys/cdefs.h>
27c209e3e2SJohn Baldwin __FBSDID("$FreeBSD$");
28c209e3e2SJohn Baldwin 
29c209e3e2SJohn Baldwin #include <sys/types.h>
3082a4538fSEric Badger #include <sys/cpuset.h>
3182a4538fSEric Badger #include <sys/event.h>
32d74da94cSMark Johnston #include <sys/file.h>
3382a4538fSEric Badger #include <sys/time.h>
34b38bd91fSEric Badger #include <sys/procctl.h>
35c209e3e2SJohn Baldwin #include <sys/ptrace.h>
36bc2be1d3SEric Badger #include <sys/queue.h>
37bc2be1d3SEric Badger #include <sys/runq.h>
38189ac973SJohn Baldwin #include <sys/syscall.h>
3957c74f5bSJohn Baldwin #include <sys/sysctl.h>
4057c74f5bSJohn Baldwin #include <sys/user.h>
41c209e3e2SJohn Baldwin #include <sys/wait.h>
42c209e3e2SJohn Baldwin #include <errno.h>
439e0d1159SEric Badger #include <machine/cpufunc.h>
44189ac973SJohn Baldwin #include <pthread.h>
45bc2be1d3SEric Badger #include <sched.h>
4682a4538fSEric Badger #include <semaphore.h>
47c209e3e2SJohn Baldwin #include <signal.h>
48dfa8ba12SJohn Baldwin #include <stdio.h>
49c209e3e2SJohn Baldwin #include <stdlib.h>
50c209e3e2SJohn Baldwin #include <unistd.h>
51c209e3e2SJohn Baldwin #include <atf-c.h>
52c209e3e2SJohn Baldwin 
53c209e3e2SJohn Baldwin /*
54403e331dSJohn Baldwin  * Architectures with a user-visible breakpoint().
55403e331dSJohn Baldwin  */
56a9c91abdSJohn Baldwin #if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) ||	\
57a9c91abdSJohn Baldwin     defined(__i386__) || defined(__mips__) || defined(__riscv) ||	\
58a9c91abdSJohn Baldwin     defined(__sparc64__)
59403e331dSJohn Baldwin #define	HAVE_BREAKPOINT
60403e331dSJohn Baldwin #endif
61403e331dSJohn Baldwin 
62403e331dSJohn Baldwin /*
63403e331dSJohn Baldwin  * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap.
64403e331dSJohn Baldwin  */
65403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
66a9c91abdSJohn Baldwin #if defined(__aarch64__)
67a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->elr += 4)
68a9c91abdSJohn Baldwin #elif defined(__amd64__) || defined(__i386__)
69403e331dSJohn Baldwin #define	SKIP_BREAK(reg)
70a9c91abdSJohn Baldwin #elif defined(__arm__)
71a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_pc += 4)
72bd061c39SJohn Baldwin #elif defined(__mips__)
73bd061c39SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_regs[PC] += 4)
74ca75fa17SJohn Baldwin #elif defined(__riscv)
75ca75fa17SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->sepc += 4)
76403e331dSJohn Baldwin #elif defined(__sparc64__)
77403e331dSJohn Baldwin #define	SKIP_BREAK(reg)	do {						\
78403e331dSJohn Baldwin 	(reg)->r_tpc = (reg)->r_tnpc + 4;				\
79403e331dSJohn Baldwin 	(reg)->r_tnpc += 8;						\
80403e331dSJohn Baldwin } while (0)
81403e331dSJohn Baldwin #endif
82403e331dSJohn Baldwin #endif
83403e331dSJohn Baldwin 
84403e331dSJohn Baldwin /*
85dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
86dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
87dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
88dfa8ba12SJohn Baldwin  */
89dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {						\
90dfa8ba12SJohn Baldwin 		if (!(exp))						\
91dfa8ba12SJohn Baldwin 			child_fail_require(__FILE__, __LINE__,		\
92dfa8ba12SJohn Baldwin 			    #exp " not met");				\
93dfa8ba12SJohn Baldwin 	} while (0)
94dfa8ba12SJohn Baldwin 
9598685dc8SJohn Baldwin static __dead2 void
96dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str)
97dfa8ba12SJohn Baldwin {
98dfa8ba12SJohn Baldwin 	char buf[128];
99dfa8ba12SJohn Baldwin 
100dfa8ba12SJohn Baldwin 	snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str);
101dfa8ba12SJohn Baldwin 	write(2, buf, strlen(buf));
102dfa8ba12SJohn Baldwin 	_exit(32);
103dfa8ba12SJohn Baldwin }
104dfa8ba12SJohn Baldwin 
10598685dc8SJohn Baldwin static void
10698685dc8SJohn Baldwin trace_me(void)
10798685dc8SJohn Baldwin {
10898685dc8SJohn Baldwin 
10998685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
11098685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11198685dc8SJohn Baldwin 
11298685dc8SJohn Baldwin 	/* Trigger a stop. */
11398685dc8SJohn Baldwin 	raise(SIGSTOP);
11498685dc8SJohn Baldwin }
11598685dc8SJohn Baldwin 
11698685dc8SJohn Baldwin static void
11798685dc8SJohn Baldwin attach_child(pid_t pid)
11898685dc8SJohn Baldwin {
11998685dc8SJohn Baldwin 	pid_t wpid;
12098685dc8SJohn Baldwin 	int status;
12198685dc8SJohn Baldwin 
12298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
12398685dc8SJohn Baldwin 
12498685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
12598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == pid);
12698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
12898685dc8SJohn Baldwin }
12998685dc8SJohn Baldwin 
13098685dc8SJohn Baldwin static void
13198685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
13298685dc8SJohn Baldwin {
13398685dc8SJohn Baldwin 
13498685dc8SJohn Baldwin 	/*
13598685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
13698685dc8SJohn Baldwin 	 * there is not a better way.
1373a014c56SJohn Baldwin 	 *
1383a014c56SJohn Baldwin 	 * Prior to r325719, the kern.proc.pid.<pid> sysctl failed
1393a014c56SJohn Baldwin 	 * with ESRCH.  After that change, a valid struct kinfo_proc
1403a014c56SJohn Baldwin 	 * is returned for zombies with ki_stat set to SZOMB.
14198685dc8SJohn Baldwin 	 */
14298685dc8SJohn Baldwin 	for (;;) {
14398685dc8SJohn Baldwin 		struct kinfo_proc kp;
14498685dc8SJohn Baldwin 		size_t len;
14598685dc8SJohn Baldwin 		int mib[4];
14698685dc8SJohn Baldwin 
14798685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
14898685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
14998685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
15098685dc8SJohn Baldwin 		mib[3] = pid;
15198685dc8SJohn Baldwin 		len = sizeof(kp);
15298685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
15398685dc8SJohn Baldwin 			ATF_REQUIRE(errno == ESRCH);
15498685dc8SJohn Baldwin 			break;
15598685dc8SJohn Baldwin 		}
1563a014c56SJohn Baldwin 		if (kp.ki_stat == SZOMB)
1573a014c56SJohn Baldwin 			break;
15898685dc8SJohn Baldwin 		usleep(5000);
15998685dc8SJohn Baldwin 	}
16098685dc8SJohn Baldwin }
16198685dc8SJohn Baldwin 
162dfa8ba12SJohn Baldwin /*
163c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
164c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
165c209e3e2SJohn Baldwin  */
166c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
167c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
168c209e3e2SJohn Baldwin {
169c209e3e2SJohn Baldwin 	pid_t child, wpid;
170c209e3e2SJohn Baldwin 	int status;
171c209e3e2SJohn Baldwin 
172c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
173c209e3e2SJohn Baldwin 	if (child == 0) {
174c209e3e2SJohn Baldwin 		/* Child process. */
17598685dc8SJohn Baldwin 		trace_me();
176c209e3e2SJohn Baldwin 
177b98cb919SJohn Baldwin 		_exit(1);
178c209e3e2SJohn Baldwin 	}
179c209e3e2SJohn Baldwin 
180c209e3e2SJohn Baldwin 	/* Parent process. */
181c209e3e2SJohn Baldwin 
182c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
183c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
184c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
185c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
186c209e3e2SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
187c209e3e2SJohn Baldwin 
188c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
189c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
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 
203c209e3e2SJohn Baldwin /*
204c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
205c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
206c209e3e2SJohn Baldwin  */
207c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
208c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
209c209e3e2SJohn Baldwin {
210c209e3e2SJohn Baldwin 	pid_t child, wpid;
211c209e3e2SJohn Baldwin 	int cpipe[2], status;
212c209e3e2SJohn Baldwin 	char c;
213c209e3e2SJohn Baldwin 
214c209e3e2SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
215c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
216c209e3e2SJohn Baldwin 	if (child == 0) {
217c209e3e2SJohn Baldwin 		/* Child process. */
218c209e3e2SJohn Baldwin 		close(cpipe[0]);
219c209e3e2SJohn Baldwin 
220c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
221dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0);
222c209e3e2SJohn Baldwin 
223b98cb919SJohn Baldwin 		_exit(1);
224c209e3e2SJohn Baldwin 	}
225c209e3e2SJohn Baldwin 	close(cpipe[1]);
226c209e3e2SJohn Baldwin 
227c209e3e2SJohn Baldwin 	/* Parent process. */
228c209e3e2SJohn Baldwin 
229c209e3e2SJohn Baldwin 	/* Attach to the child process. */
23098685dc8SJohn Baldwin 	attach_child(child);
231c209e3e2SJohn Baldwin 
232c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
233c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
234c209e3e2SJohn Baldwin 
235c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
236c209e3e2SJohn Baldwin 	close(cpipe[0]);
237c209e3e2SJohn Baldwin 
238c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
239c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
240c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
241c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
242c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
243c209e3e2SJohn Baldwin 
244c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
245c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
246c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
247c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
248c209e3e2SJohn Baldwin }
249c209e3e2SJohn Baldwin 
25057c74f5bSJohn Baldwin /*
25157c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
25257c74f5bSJohn Baldwin  * after the debugger has seen it.
25357c74f5bSJohn Baldwin  */
25457c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
25557c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
25657c74f5bSJohn Baldwin {
25757c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
25857c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
25957c74f5bSJohn Baldwin 	char c;
26057c74f5bSJohn Baldwin 
26157c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
26257c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
26357c74f5bSJohn Baldwin 
26457c74f5bSJohn Baldwin 	if (child == 0) {
26557c74f5bSJohn Baldwin 		/* Child process. */
26657c74f5bSJohn Baldwin 		close(cpipe[0]);
26757c74f5bSJohn Baldwin 
26857c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
269dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
27057c74f5bSJohn Baldwin 
271b98cb919SJohn Baldwin 		_exit(1);
27257c74f5bSJohn Baldwin 	}
27357c74f5bSJohn Baldwin 	close(cpipe[1]);
27457c74f5bSJohn Baldwin 
27557c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
27657c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
27757c74f5bSJohn Baldwin 
27857c74f5bSJohn Baldwin 	if (debugger == 0) {
27957c74f5bSJohn Baldwin 		/* Debugger process. */
28057c74f5bSJohn Baldwin 		close(dpipe[0]);
28157c74f5bSJohn Baldwin 
282dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
28357c74f5bSJohn Baldwin 
28457c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
285dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
286dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
287dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
28857c74f5bSJohn Baldwin 
289dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
29057c74f5bSJohn Baldwin 
29157c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
292dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
29357c74f5bSJohn Baldwin 
29457c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
295dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0);
29657c74f5bSJohn Baldwin 
29757c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
298dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
299dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
300dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
30157c74f5bSJohn Baldwin 
302b98cb919SJohn Baldwin 		_exit(0);
30357c74f5bSJohn Baldwin 	}
30457c74f5bSJohn Baldwin 	close(dpipe[1]);
30557c74f5bSJohn Baldwin 
30657c74f5bSJohn Baldwin 	/* Parent process. */
30757c74f5bSJohn Baldwin 
30857c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
30957c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
31057c74f5bSJohn Baldwin 
31157c74f5bSJohn Baldwin 	/* Release the child. */
31257c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
31357c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
31457c74f5bSJohn Baldwin 	close(cpipe[0]);
31557c74f5bSJohn Baldwin 
31698685dc8SJohn Baldwin 	wait_for_zombie(child);
31757c74f5bSJohn Baldwin 
31857c74f5bSJohn Baldwin 	/*
3192f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3202f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3212f021998SJohn Baldwin 	 * until the debugger sees the exit.
32257c74f5bSJohn Baldwin 	 */
32357c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
32457c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
32557c74f5bSJohn Baldwin 
32657c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
32757c74f5bSJohn Baldwin 	close(dpipe[0]);
32857c74f5bSJohn Baldwin 
32957c74f5bSJohn Baldwin 	/* Wait for the debugger. */
33057c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
33157c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
33257c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
33357c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
33457c74f5bSJohn Baldwin 
33557c74f5bSJohn Baldwin 	/* The child process should now be ready. */
33657c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
33757c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
33857c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
33957c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
34057c74f5bSJohn Baldwin }
34157c74f5bSJohn Baldwin 
34257c74f5bSJohn Baldwin /*
34357c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
34457c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
34557c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
34657c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
34757c74f5bSJohn Baldwin  */
34857c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
34957c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
35057c74f5bSJohn Baldwin {
35157c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
35257c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
35357c74f5bSJohn Baldwin 	char c;
35457c74f5bSJohn Baldwin 
35557c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
35657c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
35757c74f5bSJohn Baldwin 
35857c74f5bSJohn Baldwin 	if (child == 0) {
35957c74f5bSJohn Baldwin 		/* Child process. */
36057c74f5bSJohn Baldwin 		close(cpipe[0]);
36157c74f5bSJohn Baldwin 
36257c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
363dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
36457c74f5bSJohn Baldwin 
365b98cb919SJohn Baldwin 		_exit(1);
36657c74f5bSJohn Baldwin 	}
36757c74f5bSJohn Baldwin 	close(cpipe[1]);
36857c74f5bSJohn Baldwin 
36957c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
37057c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
37157c74f5bSJohn Baldwin 
37257c74f5bSJohn Baldwin 	if (debugger == 0) {
37357c74f5bSJohn Baldwin 		/* Debugger parent. */
37457c74f5bSJohn Baldwin 
37557c74f5bSJohn Baldwin 		/*
37657c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
37757c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
37857c74f5bSJohn Baldwin 		 */
379dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
38057c74f5bSJohn Baldwin 		if (fpid != 0)
381b98cb919SJohn Baldwin 			_exit(2);
38257c74f5bSJohn Baldwin 
38357c74f5bSJohn Baldwin 		/* Debugger process. */
38457c74f5bSJohn Baldwin 		close(dpipe[0]);
38557c74f5bSJohn Baldwin 
386dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
38757c74f5bSJohn Baldwin 
38857c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
389dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
390dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
391dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
39257c74f5bSJohn Baldwin 
393dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
39457c74f5bSJohn Baldwin 
39557c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
396dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
39757c74f5bSJohn Baldwin 
39857c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
399dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c));
40057c74f5bSJohn Baldwin 
40157c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
402dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
403dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
404dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
40557c74f5bSJohn Baldwin 
406b98cb919SJohn Baldwin 		_exit(0);
40757c74f5bSJohn Baldwin 	}
408eddb85c6SJohn Baldwin 	close(dpipe[1]);
40957c74f5bSJohn Baldwin 
41057c74f5bSJohn Baldwin 	/* Parent process. */
41157c74f5bSJohn Baldwin 
41257c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
41357c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
41457c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
41557c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
41657c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
41757c74f5bSJohn Baldwin 
41857c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
41957c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
42057c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
42157c74f5bSJohn Baldwin 
42257c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
42357c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
42457c74f5bSJohn Baldwin 
42557c74f5bSJohn Baldwin 	/* Release the child. */
42657c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
42757c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
42857c74f5bSJohn Baldwin 	close(cpipe[0]);
42957c74f5bSJohn Baldwin 
43098685dc8SJohn Baldwin 	wait_for_zombie(child);
43157c74f5bSJohn Baldwin 
43257c74f5bSJohn Baldwin 	/*
4332f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
4342f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
4352f021998SJohn Baldwin 	 * until the debugger sees the exit.
43657c74f5bSJohn Baldwin 	 */
43757c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
43857c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
43957c74f5bSJohn Baldwin 
44057c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
441eddb85c6SJohn Baldwin 	ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c));
44257c74f5bSJohn Baldwin 
44357c74f5bSJohn Baldwin 	/* Wait for the debugger. */
444eddb85c6SJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0);
445eddb85c6SJohn Baldwin 	close(dpipe[0]);
44657c74f5bSJohn Baldwin 
44757c74f5bSJohn Baldwin 	/* The child process should now be ready. */
44857c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
44957c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
45057c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
45157c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
45257c74f5bSJohn Baldwin }
45357c74f5bSJohn Baldwin 
45498685dc8SJohn Baldwin /*
455*128c9bc0SMark Johnston  * Make sure that we can collect the exit status of an orphaned process.
456*128c9bc0SMark Johnston  */
457*128c9bc0SMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
458*128c9bc0SMark Johnston ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
459*128c9bc0SMark Johnston {
460*128c9bc0SMark Johnston 	ssize_t n;
461*128c9bc0SMark Johnston 	int cpipe1[2], cpipe2[2], gcpipe[2], status;
462*128c9bc0SMark Johnston 	pid_t child, gchild;
463*128c9bc0SMark Johnston 
464*128c9bc0SMark Johnston 	ATF_REQUIRE(pipe(cpipe1) == 0);
465*128c9bc0SMark Johnston 	ATF_REQUIRE(pipe(cpipe2) == 0);
466*128c9bc0SMark Johnston 	ATF_REQUIRE(pipe(gcpipe) == 0);
467*128c9bc0SMark Johnston 
468*128c9bc0SMark Johnston 	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
469*128c9bc0SMark Johnston 
470*128c9bc0SMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
471*128c9bc0SMark Johnston 	if (child == 0) {
472*128c9bc0SMark Johnston 		CHILD_REQUIRE((gchild = fork()) != -1);
473*128c9bc0SMark Johnston 		if (gchild == 0) {
474*128c9bc0SMark Johnston 			status = 1;
475*128c9bc0SMark Johnston 			do {
476*128c9bc0SMark Johnston 				n = read(gcpipe[0], &status, sizeof(status));
477*128c9bc0SMark Johnston 			} while (n == -1 && errno == EINTR);
478*128c9bc0SMark Johnston 			_exit(status);
479*128c9bc0SMark Johnston 		}
480*128c9bc0SMark Johnston 
481*128c9bc0SMark Johnston 		CHILD_REQUIRE(write(cpipe1[1], &gchild, sizeof(gchild)) ==
482*128c9bc0SMark Johnston 		    sizeof(gchild));
483*128c9bc0SMark Johnston 		CHILD_REQUIRE(read(cpipe2[0], &status, sizeof(status)) ==
484*128c9bc0SMark Johnston 		    sizeof(status));
485*128c9bc0SMark Johnston 		_exit(status);
486*128c9bc0SMark Johnston 	}
487*128c9bc0SMark Johnston 
488*128c9bc0SMark Johnston 	ATF_REQUIRE(read(cpipe1[0], &gchild, sizeof(gchild)) == sizeof(gchild));
489*128c9bc0SMark Johnston 
490*128c9bc0SMark Johnston 	ATF_REQUIRE(ptrace(PT_ATTACH, gchild, NULL, 0) == 0);
491*128c9bc0SMark Johnston 
492*128c9bc0SMark Johnston 	status = 0;
493*128c9bc0SMark Johnston 	ATF_REQUIRE(write(cpipe2[1], &status, sizeof(status)) ==
494*128c9bc0SMark Johnston 	    sizeof(status));
495*128c9bc0SMark Johnston 	ATF_REQUIRE(waitpid(child, &status, 0) == child);
496*128c9bc0SMark Johnston 	ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
497*128c9bc0SMark Johnston 
498*128c9bc0SMark Johnston 	status = 0;
499*128c9bc0SMark Johnston 	ATF_REQUIRE(write(gcpipe[1], &status, sizeof(status)) ==
500*128c9bc0SMark Johnston 	    sizeof(status));
501*128c9bc0SMark Johnston 	ATF_REQUIRE(waitpid(gchild, &status, 0) == gchild);
502*128c9bc0SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
503*128c9bc0SMark Johnston 	ATF_REQUIRE(ptrace(PT_DETACH, gchild, (caddr_t)1, 0) == 0);
504*128c9bc0SMark Johnston 	ATF_REQUIRE(waitpid(gchild, &status, 0) == gchild);
505*128c9bc0SMark Johnston 	ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
506*128c9bc0SMark Johnston 
507*128c9bc0SMark Johnston 	ATF_REQUIRE(close(cpipe1[0]) == 0);
508*128c9bc0SMark Johnston 	ATF_REQUIRE(close(cpipe1[1]) == 0);
509*128c9bc0SMark Johnston 	ATF_REQUIRE(close(cpipe2[0]) == 0);
510*128c9bc0SMark Johnston 	ATF_REQUIRE(close(cpipe2[1]) == 0);
511*128c9bc0SMark Johnston 	ATF_REQUIRE(close(gcpipe[0]) == 0);
512*128c9bc0SMark Johnston 	ATF_REQUIRE(close(gcpipe[1]) == 0);
513*128c9bc0SMark Johnston }
514*128c9bc0SMark Johnston 
515*128c9bc0SMark Johnston /*
51698685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
51798685dc8SJohn Baldwin  * debugger is attached to it.
51898685dc8SJohn Baldwin  */
51998685dc8SJohn Baldwin static __dead2 void
520189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
52198685dc8SJohn Baldwin {
52298685dc8SJohn Baldwin 	pid_t fpid, wpid;
52398685dc8SJohn Baldwin 	int status;
52498685dc8SJohn Baldwin 
525189ac973SJohn Baldwin 	if (use_vfork)
526189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
527189ac973SJohn Baldwin 	else
52898685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
52998685dc8SJohn Baldwin 
53098685dc8SJohn Baldwin 	if (fpid == 0)
53198685dc8SJohn Baldwin 		/* Child */
532b98cb919SJohn Baldwin 		_exit(2);
53398685dc8SJohn Baldwin 
53498685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
53598685dc8SJohn Baldwin 	CHILD_REQUIRE(wpid == fpid);
53698685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
53798685dc8SJohn Baldwin 	CHILD_REQUIRE(WEXITSTATUS(status) == 2);
53898685dc8SJohn Baldwin 
539b98cb919SJohn Baldwin 	_exit(1);
54098685dc8SJohn Baldwin }
54198685dc8SJohn Baldwin 
54298685dc8SJohn Baldwin /*
54398685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
54498685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
54598685dc8SJohn Baldwin  * child process.
54698685dc8SJohn Baldwin  */
54798685dc8SJohn Baldwin static pid_t
548189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
54998685dc8SJohn Baldwin {
55098685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
55198685dc8SJohn Baldwin 	bool fork_reported[2];
55298685dc8SJohn Baldwin 	pid_t child, wpid;
55398685dc8SJohn Baldwin 	int i, status;
55498685dc8SJohn Baldwin 
55598685dc8SJohn Baldwin 	fork_reported[0] = false;
55698685dc8SJohn Baldwin 	fork_reported[1] = false;
55798685dc8SJohn Baldwin 	child = -1;
55898685dc8SJohn Baldwin 
55998685dc8SJohn Baldwin 	/*
56098685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
56198685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
56298685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
56398685dc8SJohn Baldwin 	 */
56498685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
56598685dc8SJohn Baldwin 		wpid = wait(&status);
56698685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
56798685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
56898685dc8SJohn Baldwin 
56998685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
57098685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
57198685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
57298685dc8SJohn Baldwin 		    0);
57398685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
57498685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
57598685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
57698685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
57798685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
57898685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
57998685dc8SJohn Baldwin 			if (child == -1)
58098685dc8SJohn Baldwin 				child = wpid;
58198685dc8SJohn Baldwin 			else
58298685dc8SJohn Baldwin 				ATF_REQUIRE(child == wpid);
583189ac973SJohn Baldwin 			if (ppl != NULL)
584189ac973SJohn Baldwin 				ppl[1] = pl;
58598685dc8SJohn Baldwin 			fork_reported[1] = true;
58698685dc8SJohn Baldwin 		} else {
58798685dc8SJohn Baldwin 			ATF_REQUIRE(wpid == parent);
58898685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
58998685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
59098685dc8SJohn Baldwin 			if (child == -1)
59198685dc8SJohn Baldwin 				child = pl.pl_child_pid;
59298685dc8SJohn Baldwin 			else
59398685dc8SJohn Baldwin 				ATF_REQUIRE(child == pl.pl_child_pid);
594189ac973SJohn Baldwin 			if (ppl != NULL)
595189ac973SJohn Baldwin 				ppl[0] = pl;
59698685dc8SJohn Baldwin 			fork_reported[0] = true;
59798685dc8SJohn Baldwin 		}
59898685dc8SJohn Baldwin 	}
59998685dc8SJohn Baldwin 
60098685dc8SJohn Baldwin 	return (child);
60198685dc8SJohn Baldwin }
60298685dc8SJohn Baldwin 
60398685dc8SJohn Baldwin /*
60498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
60598685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
60698685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
60798685dc8SJohn Baldwin  */
60898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
60998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
61098685dc8SJohn Baldwin {
611479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
61298685dc8SJohn Baldwin 	int status;
61398685dc8SJohn Baldwin 
61498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
61598685dc8SJohn Baldwin 	if (fpid == 0) {
61698685dc8SJohn Baldwin 		trace_me();
617189ac973SJohn Baldwin 		follow_fork_parent(false);
61898685dc8SJohn Baldwin 	}
61998685dc8SJohn Baldwin 
62098685dc8SJohn Baldwin 	/* Parent process. */
62198685dc8SJohn Baldwin 	children[0] = fpid;
62298685dc8SJohn Baldwin 
62398685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
62498685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
62598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
62698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
62798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
62898685dc8SJohn Baldwin 
62998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
63098685dc8SJohn Baldwin 
63198685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
63298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
63398685dc8SJohn Baldwin 
634189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
63598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
63698685dc8SJohn Baldwin 
63798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
63898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
63998685dc8SJohn Baldwin 
64098685dc8SJohn Baldwin 	/*
64198685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
64298685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
64398685dc8SJohn Baldwin 	 */
64498685dc8SJohn Baldwin 	wpid = wait(&status);
64598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
64698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
64798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
64898685dc8SJohn Baldwin 
64998685dc8SJohn Baldwin 	wpid = wait(&status);
65098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
65198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
65298685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
65398685dc8SJohn Baldwin 
65498685dc8SJohn Baldwin 	wpid = wait(&status);
65598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
65698685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
65798685dc8SJohn Baldwin }
65898685dc8SJohn Baldwin 
65998685dc8SJohn Baldwin /*
66098685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
66198685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
66298685dc8SJohn Baldwin  * child process is detached after it reports its fork.
66398685dc8SJohn Baldwin  */
66498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
66598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
66698685dc8SJohn Baldwin {
667479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
66898685dc8SJohn Baldwin 	int status;
66998685dc8SJohn Baldwin 
67098685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
67198685dc8SJohn Baldwin 	if (fpid == 0) {
67298685dc8SJohn Baldwin 		trace_me();
673189ac973SJohn Baldwin 		follow_fork_parent(false);
67498685dc8SJohn Baldwin 	}
67598685dc8SJohn Baldwin 
67698685dc8SJohn Baldwin 	/* Parent process. */
67798685dc8SJohn Baldwin 	children[0] = fpid;
67898685dc8SJohn Baldwin 
67998685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
68098685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
68198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
68298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
68398685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
68498685dc8SJohn Baldwin 
68598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
68698685dc8SJohn Baldwin 
68798685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
68898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
68998685dc8SJohn Baldwin 
690189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
69198685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
69298685dc8SJohn Baldwin 
69398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
69498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
69598685dc8SJohn Baldwin 
69698685dc8SJohn Baldwin 	/*
69798685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
69898685dc8SJohn Baldwin 	 * child.
69998685dc8SJohn Baldwin 	 */
70098685dc8SJohn Baldwin 	wpid = wait(&status);
70198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
70298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
70398685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
70498685dc8SJohn Baldwin 
70598685dc8SJohn Baldwin 	wpid = wait(&status);
70698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
70798685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
70898685dc8SJohn Baldwin }
70998685dc8SJohn Baldwin 
71098685dc8SJohn Baldwin /*
71198685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
71298685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
71398685dc8SJohn Baldwin  * traced parent is detached after the fork.
71498685dc8SJohn Baldwin  */
71598685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
71698685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
71798685dc8SJohn Baldwin {
718479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
71998685dc8SJohn Baldwin 	int status;
72098685dc8SJohn Baldwin 
72198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
72298685dc8SJohn Baldwin 	if (fpid == 0) {
72398685dc8SJohn Baldwin 		trace_me();
724189ac973SJohn Baldwin 		follow_fork_parent(false);
72598685dc8SJohn Baldwin 	}
72698685dc8SJohn Baldwin 
72798685dc8SJohn Baldwin 	/* Parent process. */
72898685dc8SJohn Baldwin 	children[0] = fpid;
72998685dc8SJohn Baldwin 
73098685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
73198685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
73298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
73398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
73498685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
73598685dc8SJohn Baldwin 
73698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
73798685dc8SJohn Baldwin 
73898685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
73998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
74098685dc8SJohn Baldwin 
741189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
74298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
74398685dc8SJohn Baldwin 
74498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
74598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
74698685dc8SJohn Baldwin 
74798685dc8SJohn Baldwin 	/*
74898685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
74998685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
75098685dc8SJohn Baldwin 	 *
75198685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
75298685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
75398685dc8SJohn Baldwin 	 * after the grandchild.
75498685dc8SJohn Baldwin 	 */
75598685dc8SJohn Baldwin 	wpid = wait(&status);
75698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
75798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
75898685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
75998685dc8SJohn Baldwin 
76098685dc8SJohn Baldwin 	wpid = wait(&status);
76198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
76298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
76398685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
76498685dc8SJohn Baldwin 
76598685dc8SJohn Baldwin 	wpid = wait(&status);
76698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
76798685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
76898685dc8SJohn Baldwin }
76998685dc8SJohn Baldwin 
77098685dc8SJohn Baldwin static void
77198685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
77298685dc8SJohn Baldwin {
77398685dc8SJohn Baldwin 	pid_t fpid;
77498685dc8SJohn Baldwin 
77598685dc8SJohn Baldwin 	close(cpipe[0]);
77698685dc8SJohn Baldwin 
77798685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
77898685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
77998685dc8SJohn Baldwin 	if (fpid != 0)
780b98cb919SJohn Baldwin 		_exit(3);
78198685dc8SJohn Baldwin 
78298685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
78398685dc8SJohn Baldwin 	fpid = getpid();
78498685dc8SJohn Baldwin 	CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
78598685dc8SJohn Baldwin 
78698685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
78798685dc8SJohn Baldwin 	CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
78898685dc8SJohn Baldwin }
78998685dc8SJohn Baldwin 
79098685dc8SJohn Baldwin /*
79198685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
79298685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
79398685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
79498685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
79598685dc8SJohn Baldwin  */
79698685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
79798685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
79898685dc8SJohn Baldwin {
799479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
80098685dc8SJohn Baldwin 	int cpipe[2], status;
80198685dc8SJohn Baldwin 
80298685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
80398685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
80498685dc8SJohn Baldwin 	if (fpid == 0) {
80598685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
806189ac973SJohn Baldwin 		follow_fork_parent(false);
80798685dc8SJohn Baldwin 	}
80898685dc8SJohn Baldwin 
80998685dc8SJohn Baldwin 	/* Parent process. */
81098685dc8SJohn Baldwin 	close(cpipe[1]);
81198685dc8SJohn Baldwin 
81298685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
81398685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
81498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
81598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
81698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
81798685dc8SJohn Baldwin 
81898685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
81998685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
82098685dc8SJohn Baldwin 	    sizeof(children[0]));
82198685dc8SJohn Baldwin 
82298685dc8SJohn Baldwin 	/* Attach to the fork parent. */
82398685dc8SJohn Baldwin 	attach_child(children[0]);
82498685dc8SJohn Baldwin 
82598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
82698685dc8SJohn Baldwin 
82798685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
82898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
82998685dc8SJohn Baldwin 
83098685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
83198685dc8SJohn Baldwin 	close(cpipe[0]);
83298685dc8SJohn Baldwin 
833189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
83498685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
83598685dc8SJohn Baldwin 
83698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
83798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
83898685dc8SJohn Baldwin 
83998685dc8SJohn Baldwin 	/*
84098685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
84198685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
84298685dc8SJohn Baldwin 	 */
84398685dc8SJohn Baldwin 	wpid = wait(&status);
84498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
84598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
84698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
84798685dc8SJohn Baldwin 
84898685dc8SJohn Baldwin 	wpid = wait(&status);
84998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
85098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
85198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
85298685dc8SJohn Baldwin 
85398685dc8SJohn Baldwin 	wpid = wait(&status);
85498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
85598685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
85698685dc8SJohn Baldwin }
85798685dc8SJohn Baldwin 
85898685dc8SJohn Baldwin /*
85998685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
86098685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
86198685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
86298685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
86398685dc8SJohn Baldwin  */
86498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
86598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
86698685dc8SJohn Baldwin {
867479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
86898685dc8SJohn Baldwin 	int cpipe[2], status;
86998685dc8SJohn Baldwin 
87098685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
87198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
87298685dc8SJohn Baldwin 	if (fpid == 0) {
87398685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
874189ac973SJohn Baldwin 		follow_fork_parent(false);
87598685dc8SJohn Baldwin 	}
87698685dc8SJohn Baldwin 
87798685dc8SJohn Baldwin 	/* Parent process. */
87898685dc8SJohn Baldwin 	close(cpipe[1]);
87998685dc8SJohn Baldwin 
88098685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
88198685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
88298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
88398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
88498685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
88598685dc8SJohn Baldwin 
88698685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
88798685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
88898685dc8SJohn Baldwin 	    sizeof(children[0]));
88998685dc8SJohn Baldwin 
89098685dc8SJohn Baldwin 	/* Attach to the fork parent. */
89198685dc8SJohn Baldwin 	attach_child(children[0]);
89298685dc8SJohn Baldwin 
89398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
89498685dc8SJohn Baldwin 
89598685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
89698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
89798685dc8SJohn Baldwin 
89898685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
89998685dc8SJohn Baldwin 	close(cpipe[0]);
90098685dc8SJohn Baldwin 
901189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
90298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
90398685dc8SJohn Baldwin 
90498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
90598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
90698685dc8SJohn Baldwin 
90798685dc8SJohn Baldwin 	/*
90898685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
90998685dc8SJohn Baldwin 	 * parent.
91098685dc8SJohn Baldwin 	 */
91198685dc8SJohn Baldwin 	wpid = wait(&status);
91298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
91398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
91498685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
91598685dc8SJohn Baldwin 
91698685dc8SJohn Baldwin 	wpid = wait(&status);
91798685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
91898685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
91998685dc8SJohn Baldwin }
92098685dc8SJohn Baldwin 
92198685dc8SJohn Baldwin /*
92298685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
92398685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
92498685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
92598685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
92698685dc8SJohn Baldwin  */
92798685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
92898685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
92998685dc8SJohn Baldwin {
930479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
93198685dc8SJohn Baldwin 	int cpipe[2], status;
93298685dc8SJohn Baldwin 
93398685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
93498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
93598685dc8SJohn Baldwin 	if (fpid == 0) {
93698685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
937189ac973SJohn Baldwin 		follow_fork_parent(false);
93898685dc8SJohn Baldwin 	}
93998685dc8SJohn Baldwin 
94098685dc8SJohn Baldwin 	/* Parent process. */
94198685dc8SJohn Baldwin 	close(cpipe[1]);
94298685dc8SJohn Baldwin 
94398685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
94498685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
94598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
94698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
94798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
94898685dc8SJohn Baldwin 
94998685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
95098685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
95198685dc8SJohn Baldwin 	    sizeof(children[0]));
95298685dc8SJohn Baldwin 
95398685dc8SJohn Baldwin 	/* Attach to the fork parent. */
95498685dc8SJohn Baldwin 	attach_child(children[0]);
95598685dc8SJohn Baldwin 
95698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
95798685dc8SJohn Baldwin 
95898685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
95998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
96098685dc8SJohn Baldwin 
96198685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
96298685dc8SJohn Baldwin 	close(cpipe[0]);
96398685dc8SJohn Baldwin 
964189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
96598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
96698685dc8SJohn Baldwin 
96798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
96898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
96998685dc8SJohn Baldwin 
97098685dc8SJohn Baldwin 	/*
97198685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
97298685dc8SJohn Baldwin 	 * the child.
97398685dc8SJohn Baldwin 	 */
97498685dc8SJohn Baldwin 	wpid = wait(&status);
97598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
97698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
97798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
97898685dc8SJohn Baldwin 
97998685dc8SJohn Baldwin 	wpid = wait(&status);
98098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
98198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
98298685dc8SJohn Baldwin }
98398685dc8SJohn Baldwin 
984368b2b1cSJohn Baldwin /*
985368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
986368b2b1cSJohn Baldwin  * parent but sees its original parent process.
987368b2b1cSJohn Baldwin  */
988368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
989368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
990368b2b1cSJohn Baldwin {
991368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
992368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
993368b2b1cSJohn Baldwin 	char c;
994368b2b1cSJohn Baldwin 
995368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
996368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
997368b2b1cSJohn Baldwin 
998368b2b1cSJohn Baldwin 	if (child == 0) {
999368b2b1cSJohn Baldwin 		/* Child process. */
1000368b2b1cSJohn Baldwin 		close(cpipe[0]);
1001368b2b1cSJohn Baldwin 
1002368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
1003368b2b1cSJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
1004368b2b1cSJohn Baldwin 
1005368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
1006368b2b1cSJohn Baldwin 		ppid = getppid();
1007368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) ==
1008368b2b1cSJohn Baldwin 		    sizeof(ppid));
1009368b2b1cSJohn Baldwin 
1010368b2b1cSJohn Baldwin 		_exit(1);
1011368b2b1cSJohn Baldwin 	}
1012368b2b1cSJohn Baldwin 	close(cpipe[1]);
1013368b2b1cSJohn Baldwin 
1014368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
1015368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
1016368b2b1cSJohn Baldwin 
1017368b2b1cSJohn Baldwin 	if (debugger == 0) {
1018368b2b1cSJohn Baldwin 		/* Debugger process. */
1019368b2b1cSJohn Baldwin 		close(dpipe[0]);
1020368b2b1cSJohn Baldwin 
1021368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
1022368b2b1cSJohn Baldwin 
1023368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
1024368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
1025368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
1026368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1027368b2b1cSJohn Baldwin 
1028368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
1029368b2b1cSJohn Baldwin 
1030368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
1031368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
1032368b2b1cSJohn Baldwin 
1033368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
1034368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
1035368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
1036368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
1037368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
1038368b2b1cSJohn Baldwin 
1039368b2b1cSJohn Baldwin 		_exit(0);
1040368b2b1cSJohn Baldwin 	}
1041368b2b1cSJohn Baldwin 	close(dpipe[1]);
1042368b2b1cSJohn Baldwin 
1043368b2b1cSJohn Baldwin 	/* Parent process. */
1044368b2b1cSJohn Baldwin 
1045368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
1046368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
1047368b2b1cSJohn Baldwin 
1048368b2b1cSJohn Baldwin 	/* Release the child. */
1049368b2b1cSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
1050368b2b1cSJohn Baldwin 
1051368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
1052368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid));
1053368b2b1cSJohn Baldwin 	close(cpipe[0]);
1054368b2b1cSJohn Baldwin 
1055368b2b1cSJohn Baldwin 	ATF_REQUIRE(ppid == getpid());
1056368b2b1cSJohn Baldwin 
1057368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
1058368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
1059368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
1060368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1061368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
1062368b2b1cSJohn Baldwin 
1063368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
1064368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
1065368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == child);
1066368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1067368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1068368b2b1cSJohn Baldwin }
1069368b2b1cSJohn Baldwin 
1070189ac973SJohn Baldwin /*
1071189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1072189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
1073189ac973SJohn Baldwin  */
1074189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
1075189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
1076189ac973SJohn Baldwin {
1077189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1078189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1079189ac973SJohn Baldwin 	int status;
1080189ac973SJohn Baldwin 
1081189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1082189ac973SJohn Baldwin 	if (fpid == 0) {
1083189ac973SJohn Baldwin 		trace_me();
1084189ac973SJohn Baldwin 		follow_fork_parent(false);
1085189ac973SJohn Baldwin 	}
1086189ac973SJohn Baldwin 
1087189ac973SJohn Baldwin 	/* Parent process. */
1088189ac973SJohn Baldwin 	children[0] = fpid;
1089189ac973SJohn Baldwin 
1090189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1091189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1092189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1093189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1094189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1095189ac973SJohn Baldwin 
1096189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1097189ac973SJohn Baldwin 
1098189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1099189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1100189ac973SJohn Baldwin 
1101189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1102189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1103189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1104189ac973SJohn Baldwin 
1105189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1106189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1107189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork);
1108189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1109189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1110189ac973SJohn Baldwin 
1111189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1112189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1113189ac973SJohn Baldwin 
1114189ac973SJohn Baldwin 	/*
1115189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1116189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1117189ac973SJohn Baldwin 	 */
1118189ac973SJohn Baldwin 	wpid = wait(&status);
1119189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1120189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1121189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1122189ac973SJohn Baldwin 
1123189ac973SJohn Baldwin 	wpid = wait(&status);
1124189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1125189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1126189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1127189ac973SJohn Baldwin 
1128189ac973SJohn Baldwin 	wpid = wait(&status);
1129189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1130189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1131189ac973SJohn Baldwin }
1132189ac973SJohn Baldwin 
1133189ac973SJohn Baldwin /*
1134189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1135189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1136189ac973SJohn Baldwin  */
1137189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1138189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1139189ac973SJohn Baldwin {
1140189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1141189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1142189ac973SJohn Baldwin 	int status;
1143189ac973SJohn Baldwin 
1144189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1145189ac973SJohn Baldwin 	if (fpid == 0) {
1146189ac973SJohn Baldwin 		trace_me();
1147189ac973SJohn Baldwin 		follow_fork_parent(true);
1148189ac973SJohn Baldwin 	}
1149189ac973SJohn Baldwin 
1150189ac973SJohn Baldwin 	/* Parent process. */
1151189ac973SJohn Baldwin 	children[0] = fpid;
1152189ac973SJohn Baldwin 
1153189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1154189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1155189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1156189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1157189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1158189ac973SJohn Baldwin 
1159189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1160189ac973SJohn Baldwin 
1161189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1162189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1163189ac973SJohn Baldwin 
1164189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1165189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1166189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1167189ac973SJohn Baldwin 
1168189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1169189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1170189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork);
1171189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1172189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1173189ac973SJohn Baldwin 
1174189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1175189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1176189ac973SJohn Baldwin 
1177189ac973SJohn Baldwin 	/*
1178189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1179189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1180189ac973SJohn Baldwin 	 */
1181189ac973SJohn Baldwin 	wpid = wait(&status);
1182189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1183189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1184189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1185189ac973SJohn Baldwin 
1186189ac973SJohn Baldwin 	wpid = wait(&status);
1187189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1188189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1189189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1190189ac973SJohn Baldwin 
1191189ac973SJohn Baldwin 	wpid = wait(&status);
1192189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1193189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1194189ac973SJohn Baldwin }
1195189ac973SJohn Baldwin 
1196189ac973SJohn Baldwin static void *
1197189ac973SJohn Baldwin simple_thread(void *arg __unused)
1198189ac973SJohn Baldwin {
1199189ac973SJohn Baldwin 
1200189ac973SJohn Baldwin 	pthread_exit(NULL);
1201189ac973SJohn Baldwin }
1202189ac973SJohn Baldwin 
12035fcfab6eSJohn Baldwin static __dead2 void
12045fcfab6eSJohn Baldwin simple_thread_main(void)
12055fcfab6eSJohn Baldwin {
12065fcfab6eSJohn Baldwin 	pthread_t thread;
12075fcfab6eSJohn Baldwin 
12085fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, NULL) == 0);
12095fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_join(thread, NULL) == 0);
12105fcfab6eSJohn Baldwin 	exit(1);
12115fcfab6eSJohn Baldwin }
12125fcfab6eSJohn Baldwin 
1213189ac973SJohn Baldwin /*
1214189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1215189ac973SJohn Baldwin  * thread reports the correct value.
1216189ac973SJohn Baldwin  */
1217189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1218189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1219189ac973SJohn Baldwin {
1220189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1221189ac973SJohn Baldwin 	pid_t fpid, wpid;
1222e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1223189ac973SJohn Baldwin 	int status;
1224189ac973SJohn Baldwin 
1225189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1226189ac973SJohn Baldwin 	if (fpid == 0) {
1227189ac973SJohn Baldwin 		trace_me();
12285fcfab6eSJohn Baldwin 		simple_thread_main();
1229189ac973SJohn Baldwin 	}
1230189ac973SJohn Baldwin 
1231189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1232189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1233189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1234189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1235189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1236189ac973SJohn Baldwin 
1237189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1238189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1239e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1240189ac973SJohn Baldwin 
1241189ac973SJohn Baldwin 	/*
1242189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1243189ac973SJohn Baldwin 	 * system call exits.
1244189ac973SJohn Baldwin 	 */
1245189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1246189ac973SJohn Baldwin 
1247189ac973SJohn Baldwin 	/*
1248189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1249189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1250189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1251189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1252189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1253189ac973SJohn Baldwin 	 */
1254189ac973SJohn Baldwin 	for (;;) {
1255189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1256189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1257189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1258189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1259189ac973SJohn Baldwin 
1260189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1261189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1262189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1263189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1264e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1265189ac973SJohn Baldwin 			/* New thread seen. */
1266189ac973SJohn Baldwin 			break;
1267189ac973SJohn Baldwin 
1268189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1269189ac973SJohn Baldwin 	}
1270189ac973SJohn Baldwin 
1271189ac973SJohn Baldwin 	/* Wait for the child to exit. */
1272189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1273189ac973SJohn Baldwin 	for (;;) {
1274189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1275189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1276189ac973SJohn Baldwin 		if (WIFEXITED(status))
1277189ac973SJohn Baldwin 			break;
1278189ac973SJohn Baldwin 
1279189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1280189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1281189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1282189ac973SJohn Baldwin 	}
1283189ac973SJohn Baldwin 
1284189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1285189ac973SJohn Baldwin 
1286189ac973SJohn Baldwin 	wpid = wait(&status);
1287189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1288189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1289189ac973SJohn Baldwin }
1290189ac973SJohn Baldwin 
12915fcfab6eSJohn Baldwin /*
12925fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
12935fcfab6eSJohn Baldwin  */
12945fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
12955fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
12965fcfab6eSJohn Baldwin {
12975fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
12985fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
12995fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
13005fcfab6eSJohn Baldwin 	int status;
13015fcfab6eSJohn Baldwin 
13025fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13035fcfab6eSJohn Baldwin 	if (fpid == 0) {
13045fcfab6eSJohn Baldwin 		trace_me();
13055fcfab6eSJohn Baldwin 		simple_thread_main();
13065fcfab6eSJohn Baldwin 	}
13075fcfab6eSJohn Baldwin 
13085fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13095fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13105fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13115fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13125fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
13135fcfab6eSJohn Baldwin 
13145fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13155fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13165fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13175fcfab6eSJohn Baldwin 
13185fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
13195fcfab6eSJohn Baldwin 
13205fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
13215fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13225fcfab6eSJohn Baldwin 
13235fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13245fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13255fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13265fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13275fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13285fcfab6eSJohn Baldwin 
13295fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13305fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
13315fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13325fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13335fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13345fcfab6eSJohn Baldwin 
13355fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13365fcfab6eSJohn Baldwin 
13375fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
13385fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13395fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13405fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13415fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13425fcfab6eSJohn Baldwin 
13435fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13445fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
13455fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
13465fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
13475fcfab6eSJohn Baldwin 
13485fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13495fcfab6eSJohn Baldwin 
13505fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13515fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13525fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
13535fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
13545fcfab6eSJohn Baldwin 
13555fcfab6eSJohn Baldwin 	wpid = wait(&status);
13565fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
13575fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
13585fcfab6eSJohn Baldwin }
13595fcfab6eSJohn Baldwin 
13605fcfab6eSJohn Baldwin static void *
13615fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
13625fcfab6eSJohn Baldwin {
13635fcfab6eSJohn Baldwin 
13645fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
13655fcfab6eSJohn Baldwin 	exit(127);
13665fcfab6eSJohn Baldwin }
13675fcfab6eSJohn Baldwin 
13685fcfab6eSJohn Baldwin static __dead2 void
13695fcfab6eSJohn Baldwin exec_thread_main(void)
13705fcfab6eSJohn Baldwin {
13715fcfab6eSJohn Baldwin 	pthread_t thread;
13725fcfab6eSJohn Baldwin 
13735fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, exec_thread, NULL) == 0);
13745fcfab6eSJohn Baldwin 	for (;;)
13755fcfab6eSJohn Baldwin 		sleep(60);
13765fcfab6eSJohn Baldwin 	exit(1);
13775fcfab6eSJohn Baldwin }
13785fcfab6eSJohn Baldwin 
13795fcfab6eSJohn Baldwin /*
13805fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
13815fcfab6eSJohn Baldwin  * process that calls execve(2).
13825fcfab6eSJohn Baldwin  */
13835fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
13845fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
13855fcfab6eSJohn Baldwin {
13865fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
13875fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
13885fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
13895fcfab6eSJohn Baldwin 	int status;
13905fcfab6eSJohn Baldwin 
13915fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13925fcfab6eSJohn Baldwin 	if (fpid == 0) {
13935fcfab6eSJohn Baldwin 		trace_me();
13945fcfab6eSJohn Baldwin 		exec_thread_main();
13955fcfab6eSJohn Baldwin 	}
13965fcfab6eSJohn Baldwin 
13975fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13985fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13995fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14005fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14015fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14025fcfab6eSJohn Baldwin 
14035fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
14045fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
14055fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
14065fcfab6eSJohn Baldwin 
14075fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
14085fcfab6eSJohn Baldwin 
14095fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
14105fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14115fcfab6eSJohn Baldwin 
14125fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
14135fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14145fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14155fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14165fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
14175fcfab6eSJohn Baldwin 
14185fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14195fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
14205fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
14215fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
14225fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
14235fcfab6eSJohn Baldwin 
14245fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14255fcfab6eSJohn Baldwin 
14265fcfab6eSJohn Baldwin 	/*
14275fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
14285fcfab6eSJohn Baldwin 	 * single threading from execve().
14295fcfab6eSJohn Baldwin 	 */
14305fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14315fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14325fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14335fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
14345fcfab6eSJohn Baldwin 
14355fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14365fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
14375fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
14385fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[0]);
14395fcfab6eSJohn Baldwin 
14405fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14415fcfab6eSJohn Baldwin 
14425fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
14435fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14445fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14455fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
14465fcfab6eSJohn Baldwin 
14475fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14485fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
14495fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
14505fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
14515fcfab6eSJohn Baldwin 
14525fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14535fcfab6eSJohn Baldwin 
14545fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
14555fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14565fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
14575fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
14585fcfab6eSJohn Baldwin 
14595fcfab6eSJohn Baldwin 	wpid = wait(&status);
14605fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14615fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
14625fcfab6eSJohn Baldwin }
14635fcfab6eSJohn Baldwin 
14643340c45bSJohn Baldwin static void
14653340c45bSJohn Baldwin handler(int sig __unused)
14663340c45bSJohn Baldwin {
14673340c45bSJohn Baldwin }
14683340c45bSJohn Baldwin 
14693340c45bSJohn Baldwin static void
14703340c45bSJohn Baldwin signal_main(void)
14713340c45bSJohn Baldwin {
14723340c45bSJohn Baldwin 
14733340c45bSJohn Baldwin 	signal(SIGINFO, handler);
14743340c45bSJohn Baldwin 	raise(SIGINFO);
14753340c45bSJohn Baldwin 	exit(0);
14763340c45bSJohn Baldwin }
14773340c45bSJohn Baldwin 
14783340c45bSJohn Baldwin /*
14793340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
14803340c45bSJohn Baldwin  */
14813340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
14823340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
14833340c45bSJohn Baldwin {
14843340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
14853340c45bSJohn Baldwin 	pid_t fpid, wpid;
14863340c45bSJohn Baldwin 	int status;
14873340c45bSJohn Baldwin 
14883340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14893340c45bSJohn Baldwin 	if (fpid == 0) {
14903340c45bSJohn Baldwin 		trace_me();
14913340c45bSJohn Baldwin 		signal_main();
14923340c45bSJohn Baldwin 	}
14933340c45bSJohn Baldwin 
14943340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14953340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14963340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14973340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14983340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14993340c45bSJohn Baldwin 
15003340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15013340c45bSJohn Baldwin 
15023340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
15033340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15043340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15053340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGINFO);
15063340c45bSJohn Baldwin 
15073340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
15083340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_event == PL_EVENT_SIGNAL);
15093340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
15103340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == SI_LWP);
15113340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_pid == wpid);
15123340c45bSJohn Baldwin 
15133340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15143340c45bSJohn Baldwin 
15153340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
15163340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15173340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15183340c45bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15193340c45bSJohn Baldwin 
15203340c45bSJohn Baldwin 	wpid = wait(&status);
15213340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15223340c45bSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15233340c45bSJohn Baldwin }
15243340c45bSJohn Baldwin 
15258d570f64SJohn Baldwin /*
15268d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
15278d570f64SJohn Baldwin  */
15288d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
15298d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
15308d570f64SJohn Baldwin {
15318d570f64SJohn Baldwin 	pid_t fpid, wpid;
15328d570f64SJohn Baldwin 	int events, status;
15338d570f64SJohn Baldwin 
15348d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15358d570f64SJohn Baldwin 	if (fpid == 0) {
15368d570f64SJohn Baldwin 		trace_me();
15378d570f64SJohn Baldwin 		exec_thread(NULL);
15388d570f64SJohn Baldwin 	}
15398d570f64SJohn Baldwin 
15408d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15418d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15428d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15438d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15448d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15458d570f64SJohn Baldwin 
15468d570f64SJohn Baldwin 	events = 0;
15478d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15488d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15498d570f64SJohn Baldwin 
15508d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15518d570f64SJohn Baldwin 
15528d570f64SJohn Baldwin 	/* Should get one event at exit. */
15538d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15548d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15558d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15568d570f64SJohn Baldwin 
15578d570f64SJohn Baldwin 	wpid = wait(&status);
15588d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15598d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15608d570f64SJohn Baldwin }
15618d570f64SJohn Baldwin 
15628d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
15638d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
15648d570f64SJohn Baldwin {
15658d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
15668d570f64SJohn Baldwin 	pid_t fpid, wpid;
15678d570f64SJohn Baldwin 	int events, status;
15688d570f64SJohn Baldwin 
15698d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15708d570f64SJohn Baldwin 	if (fpid == 0) {
15718d570f64SJohn Baldwin 		trace_me();
15728d570f64SJohn Baldwin 		exec_thread(NULL);
15738d570f64SJohn Baldwin 	}
15748d570f64SJohn Baldwin 
15758d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15768d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15778d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15788d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15798d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15808d570f64SJohn Baldwin 
15818d570f64SJohn Baldwin 	events = PTRACE_EXEC;
15828d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15838d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15848d570f64SJohn Baldwin 
15858d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15868d570f64SJohn Baldwin 
15878d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
15888d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15898d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15908d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
15918d570f64SJohn Baldwin 
15928d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
15938d570f64SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
15948d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
15958d570f64SJohn Baldwin 
15968d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15978d570f64SJohn Baldwin 
15988d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
15998d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16008d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
16018d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
16028d570f64SJohn Baldwin 
16038d570f64SJohn Baldwin 	wpid = wait(&status);
16048d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
16058d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
16068d570f64SJohn Baldwin }
16078d570f64SJohn Baldwin 
16088d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
16098d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
16108d570f64SJohn Baldwin {
16118d570f64SJohn Baldwin 	pid_t fpid, wpid;
16128d570f64SJohn Baldwin 	int events, status;
16138d570f64SJohn Baldwin 
16148d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16158d570f64SJohn Baldwin 	if (fpid == 0) {
16168d570f64SJohn Baldwin 		trace_me();
16178d570f64SJohn Baldwin 		exit(0);
16188d570f64SJohn Baldwin 	}
16198d570f64SJohn Baldwin 
16208d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16218d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16228d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
16238d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
16248d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
16258d570f64SJohn Baldwin 
16268d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
16278d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
16288d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16298d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16308d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_FORK);
16318d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
16328d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16338d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16348d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_FORK));
16358d570f64SJohn Baldwin 
16368d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
16378d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
16388d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16398d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16408d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_LWP);
16418d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
16428d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16438d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16448d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_LWP));
16458d570f64SJohn Baldwin 
16468d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
16478d570f64SJohn Baldwin 
16488d570f64SJohn Baldwin 	/* Should get one event at exit. */
16498d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16508d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
16518d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
16528d570f64SJohn Baldwin 
16538d570f64SJohn Baldwin 	wpid = wait(&status);
16548d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
16558d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
16568d570f64SJohn Baldwin }
16578d570f64SJohn Baldwin 
1658fc4f075aSJohn Baldwin /*
1659fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1660fc4f075aSJohn Baldwin  */
1661fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
1662fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1663fc4f075aSJohn Baldwin {
1664fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1665fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1666fc4f075aSJohn Baldwin 	int events, status;
1667fc4f075aSJohn Baldwin 
1668fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1669fc4f075aSJohn Baldwin 	if (fpid == 0) {
1670fc4f075aSJohn Baldwin 		trace_me();
1671fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1672fc4f075aSJohn Baldwin 	}
1673fc4f075aSJohn Baldwin 
1674fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1675fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1676fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1677fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1678fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1679fc4f075aSJohn Baldwin 
1680fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1681fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1682fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1683fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1684fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1685fc4f075aSJohn Baldwin 
1686fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1687fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1688fc4f075aSJohn Baldwin 
1689fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1690fc4f075aSJohn Baldwin 	wpid = wait(&status);
1691fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1692fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1693fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1694fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1695fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1696fc4f075aSJohn Baldwin 
1697fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1698fc4f075aSJohn Baldwin 
1699fc4f075aSJohn Baldwin 	wpid = wait(&status);
1700fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1701fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1702fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1703fc4f075aSJohn Baldwin 
1704fc4f075aSJohn Baldwin 	wpid = wait(&status);
1705fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1706fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1707fc4f075aSJohn Baldwin }
1708fc4f075aSJohn Baldwin 
1709fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
1710fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1711fc4f075aSJohn Baldwin {
1712fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1713fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1714fc4f075aSJohn Baldwin 	int events, status;
1715fc4f075aSJohn Baldwin 
1716fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1717fc4f075aSJohn Baldwin 	if (fpid == 0) {
1718fc4f075aSJohn Baldwin 		trace_me();
1719fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1720fc4f075aSJohn Baldwin 	}
1721fc4f075aSJohn Baldwin 
1722fc4f075aSJohn Baldwin 	/* Parent process. */
1723fc4f075aSJohn Baldwin 	children[0] = fpid;
1724fc4f075aSJohn Baldwin 
1725fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1726fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1727fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1728fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1729fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1730fc4f075aSJohn Baldwin 
1731fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1732fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1733fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1734fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1735fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1736fc4f075aSJohn Baldwin 
1737fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1738fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1739fc4f075aSJohn Baldwin 
1740fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1741fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1742fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1743fc4f075aSJohn Baldwin 
1744fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1745fc4f075aSJohn Baldwin 
1746fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1747fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1748fc4f075aSJohn Baldwin 
1749fc4f075aSJohn Baldwin 	/*
1750fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1751fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1752fc4f075aSJohn Baldwin 	 */
1753fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
1754fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1755fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1756fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1757fc4f075aSJohn Baldwin 
1758fc4f075aSJohn Baldwin 	/*
1759fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1760fc4f075aSJohn Baldwin 	 * exits.
1761fc4f075aSJohn Baldwin 	 */
1762fc4f075aSJohn Baldwin 	wpid = wait(&status);
1763fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1764fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1765fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1766fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1767fc4f075aSJohn Baldwin 	    -1);
1768fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1769fc4f075aSJohn Baldwin 
1770fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1771fc4f075aSJohn Baldwin 
1772fc4f075aSJohn Baldwin 	wpid = wait(&status);
1773fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1774fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1775fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1776fc4f075aSJohn Baldwin 
1777fc4f075aSJohn Baldwin 	wpid = wait(&status);
1778fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1779fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1780fc4f075aSJohn Baldwin }
1781fc4f075aSJohn Baldwin 
1782403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
1783e2ebfbbfSEric Badger /*
178482a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
178582a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
178682a4538fSEric Badger  */
178782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
178882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
178982a4538fSEric Badger {
179082a4538fSEric Badger 	pid_t fpid, wpid;
179182a4538fSEric Badger 	int status;
179282a4538fSEric Badger 
179382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
179482a4538fSEric Badger 	if (fpid == 0) {
179582a4538fSEric Badger 		trace_me();
17969e0d1159SEric Badger 		breakpoint();
179782a4538fSEric Badger 		exit(1);
179882a4538fSEric Badger 	}
179982a4538fSEric Badger 
180082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
180182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
180282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
180382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
180482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
180582a4538fSEric Badger 
180682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
180782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
180882a4538fSEric Badger 
180982a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
181082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
181182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
181282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
181382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
181482a4538fSEric Badger 
181582a4538fSEric Badger 	/* Kill the child process. */
181682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
181782a4538fSEric Badger 
181882a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
181982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
182082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
182182a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
182282a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
182382a4538fSEric Badger 
182482a4538fSEric Badger 	wpid = wait(&status);
182582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
182682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
182782a4538fSEric Badger }
1828403e331dSJohn Baldwin #endif /* HAVE_BREAKPOINT */
182982a4538fSEric Badger 
183082a4538fSEric Badger /*
183182a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
183282a4538fSEric Badger  * process exit when stopped inside of a system call.
183382a4538fSEric Badger  */
183482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
183582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
183682a4538fSEric Badger {
183782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
183882a4538fSEric Badger 	pid_t fpid, wpid;
183982a4538fSEric Badger 	int status;
184082a4538fSEric Badger 
184182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
184282a4538fSEric Badger 	if (fpid == 0) {
184382a4538fSEric Badger 		trace_me();
184482a4538fSEric Badger 		getpid();
184582a4538fSEric Badger 		exit(1);
184682a4538fSEric Badger 	}
184782a4538fSEric Badger 
184882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
184982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
185082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
185182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
185282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
185382a4538fSEric Badger 
185482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
185582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
185682a4538fSEric Badger 
185782a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
185882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
185982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
186082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
186182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
186282a4538fSEric Badger 
186382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
186482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
186582a4538fSEric Badger 
186682a4538fSEric Badger 	/* Kill the child process. */
186782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
186882a4538fSEric Badger 
186982a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
187082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
187182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
187282a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
187382a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
187482a4538fSEric Badger 
187582a4538fSEric Badger 	wpid = wait(&status);
187682a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
187782a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
187882a4538fSEric Badger }
187982a4538fSEric Badger 
188082a4538fSEric Badger /*
188182a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
188282a4538fSEric Badger  * process exit when killing a multithreaded process.
188382a4538fSEric Badger  */
188482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
188582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
188682a4538fSEric Badger {
188782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
188882a4538fSEric Badger 	pid_t fpid, wpid;
188982a4538fSEric Badger 	lwpid_t main_lwp;
189082a4538fSEric Badger 	int status;
189182a4538fSEric Badger 
189282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
189382a4538fSEric Badger 	if (fpid == 0) {
189482a4538fSEric Badger 		trace_me();
189582a4538fSEric Badger 		simple_thread_main();
189682a4538fSEric Badger 	}
189782a4538fSEric Badger 
189882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
189982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
190082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
190182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
190282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
190382a4538fSEric Badger 
190482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
190582a4538fSEric Badger 	    sizeof(pl)) != -1);
190682a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
190782a4538fSEric Badger 
190882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
190982a4538fSEric Badger 
191082a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
191182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
191282a4538fSEric Badger 
191382a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
191482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
191582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
191682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
191782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
191882a4538fSEric Badger 
191982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
192082a4538fSEric Badger 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
192182a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
192282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
192382a4538fSEric Badger 
192482a4538fSEric Badger 	/* Kill the child process. */
192582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
192682a4538fSEric Badger 
192782a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
192882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
192982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
193082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
193182a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
193282a4538fSEric Badger 
193382a4538fSEric Badger 	wpid = wait(&status);
193482a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
193582a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
193682a4538fSEric Badger }
193782a4538fSEric Badger 
193882a4538fSEric Badger static void *
193982a4538fSEric Badger mask_usr1_thread(void *arg)
194082a4538fSEric Badger {
194182a4538fSEric Badger 	pthread_barrier_t *pbarrier;
194282a4538fSEric Badger 	sigset_t sigmask;
194382a4538fSEric Badger 
194482a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
194582a4538fSEric Badger 
194682a4538fSEric Badger 	sigemptyset(&sigmask);
194782a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
194882a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
194982a4538fSEric Badger 
195082a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
195182a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
195282a4538fSEric Badger 
195382a4538fSEric Badger 	for (;;)
195482a4538fSEric Badger 		sleep(60);
195582a4538fSEric Badger 
195682a4538fSEric Badger 	return (NULL);
195782a4538fSEric Badger }
195882a4538fSEric Badger 
195982a4538fSEric Badger /*
196082a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
196182a4538fSEric Badger  * and prevents spurious stops due to those other signals.
196282a4538fSEric Badger  */
19633cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal);
19643cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
19653cf56bb4SEnji Cooper {
19663cf56bb4SEnji Cooper 
19673cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
19683cf56bb4SEnji Cooper }
196982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
197082a4538fSEric Badger {
197182a4538fSEric Badger 	pid_t fpid, wpid;
197282a4538fSEric Badger 	int status;
197382a4538fSEric Badger 	cpuset_t setmask;
197482a4538fSEric Badger 	pthread_t t;
197582a4538fSEric Badger 	pthread_barrier_t barrier;
1976bc2be1d3SEric Badger 	struct sched_param sched_param;
197782a4538fSEric Badger 
197882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
197982a4538fSEric Badger 	if (fpid == 0) {
1980bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
198182a4538fSEric Badger 		CPU_ZERO(&setmask);
198282a4538fSEric Badger 		CPU_SET(0, &setmask);
198382a4538fSEric Badger 		cpusetid_t setid;
198482a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
198582a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
198682a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
198782a4538fSEric Badger 
198882a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
198982a4538fSEric Badger 
199082a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
199182a4538fSEric Badger 		    (void*)&barrier) == 0);
199282a4538fSEric Badger 
1993bc2be1d3SEric Badger 		/*
1994bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
1995bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
1996bc2be1d3SEric Badger 		 * thread runs first.
1997bc2be1d3SEric Badger 		 */
1998bc2be1d3SEric Badger 		sched_param.sched_priority =
1999bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2000bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2001bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2002bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2003bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2004bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2005bc2be1d3SEric Badger 		    &sched_param) == 0);
2006bc2be1d3SEric Badger 
200782a4538fSEric Badger 		sigset_t sigmask;
200882a4538fSEric Badger 		sigemptyset(&sigmask);
200982a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
201082a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
201182a4538fSEric Badger 
201282a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
201382a4538fSEric Badger 		pthread_barrier_wait(&barrier);
201482a4538fSEric Badger 
201582a4538fSEric Badger 		trace_me();
201682a4538fSEric Badger 
201782a4538fSEric Badger 		for (;;)
201882a4538fSEric Badger 			sleep(60);
201982a4538fSEric Badger 
202082a4538fSEric Badger 		exit(1);
202182a4538fSEric Badger 	}
202282a4538fSEric Badger 
202382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
202482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
202582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
202682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
202782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
202882a4538fSEric Badger 
202982a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
203082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
203182a4538fSEric Badger 
203282a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
203382a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
203482a4538fSEric Badger 
203582a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
203682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
203782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
203882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
203982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
204082a4538fSEric Badger 
204182a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
204282a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
204382a4538fSEric Badger 
204482a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
204582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
204682a4538fSEric Badger 
204782a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
204882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
204982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
205082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
205182a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
205282a4538fSEric Badger 
205382a4538fSEric Badger 	wpid = wait(&status);
205482a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
205582a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
205682a4538fSEric Badger }
205782a4538fSEric Badger 
205882a4538fSEric Badger /*
205982a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
206082a4538fSEric Badger  * and prevents spurious stops caused by those events.
206182a4538fSEric Badger  */
20623cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop);
20633cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc)
20643cf56bb4SEnji Cooper {
20653cf56bb4SEnji Cooper 
20663cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
20673cf56bb4SEnji Cooper }
206882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
206982a4538fSEric Badger {
207082a4538fSEric Badger 	pid_t fpid, wpid;
2071bc2be1d3SEric Badger 	int status;
207282a4538fSEric Badger 	cpuset_t setmask;
207382a4538fSEric Badger 	pthread_t t;
207482a4538fSEric Badger 	pthread_barrier_t barrier;
207582a4538fSEric Badger 	lwpid_t main_lwp;
207682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2077bc2be1d3SEric Badger 	struct sched_param sched_param;
207882a4538fSEric Badger 
207982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
208082a4538fSEric Badger 	if (fpid == 0) {
208182a4538fSEric Badger 		trace_me();
208282a4538fSEric Badger 
2083bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
208482a4538fSEric Badger 		CPU_ZERO(&setmask);
208582a4538fSEric Badger 		CPU_SET(0, &setmask);
208682a4538fSEric Badger 		cpusetid_t setid;
208782a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
208882a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
208982a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
209082a4538fSEric Badger 
209182a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
209282a4538fSEric Badger 
209382a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
209482a4538fSEric Badger 		    (void*)&barrier) == 0);
209582a4538fSEric Badger 
2096bc2be1d3SEric Badger 		/*
2097bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2098bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2099bc2be1d3SEric Badger 		 * thread runs first.
2100bc2be1d3SEric Badger 		 */
2101bc2be1d3SEric Badger 		sched_param.sched_priority =
2102bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2103bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2104bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2105bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2106bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2107bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2108bc2be1d3SEric Badger 		    &sched_param) == 0);
2109bc2be1d3SEric Badger 
211082a4538fSEric Badger 		sigset_t sigmask;
211182a4538fSEric Badger 		sigemptyset(&sigmask);
211282a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
211382a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
211482a4538fSEric Badger 
211582a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
211682a4538fSEric Badger 		pthread_barrier_wait(&barrier);
211782a4538fSEric Badger 
211882a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
211982a4538fSEric Badger 		raise(SIGSTOP);
212082a4538fSEric Badger 
212182a4538fSEric Badger 		getpid();
212282a4538fSEric Badger 		exit(1);
212382a4538fSEric Badger 	}
212482a4538fSEric Badger 
212582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
212682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
212782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
212882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
212982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
213082a4538fSEric Badger 
213182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
213282a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
213382a4538fSEric Badger 
213482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
213582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
213682a4538fSEric Badger 
213782a4538fSEric Badger 	/*
213882a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
213982a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
214082a4538fSEric Badger 	 */
214182a4538fSEric Badger 	for (;;) {
214282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
214382a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
214482a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
214582a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
214682a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
214782a4538fSEric Badger 			    sizeof(pl)) != -1);
214882a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
214982a4538fSEric Badger 		} else {
215082a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
215182a4538fSEric Badger 			break;
215282a4538fSEric Badger 		}
215382a4538fSEric Badger 		ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
215482a4538fSEric Badger 	}
215582a4538fSEric Badger 
2156bc2be1d3SEric Badger 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
215782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
215882a4538fSEric Badger 
215982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
216082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
216182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
216282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
216382a4538fSEric Badger 
216482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
216582a4538fSEric Badger 	    sizeof(pl)) != -1);
2166bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid == main_lwp);
216782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
2168bc2be1d3SEric Badger 	/* Prevent the main thread from hitting its syscall exit for now. */
216982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0);
217082a4538fSEric Badger 
2171bc2be1d3SEric Badger 	/*
2172bc2be1d3SEric Badger 	 * Proceed, allowing second thread to hit syscall exit for
2173bc2be1d3SEric Badger 	 * pthread_barrier_wait().
2174bc2be1d3SEric Badger 	 */
2175bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
2176bc2be1d3SEric Badger 
2177bc2be1d3SEric Badger 	wpid = waitpid(fpid, &status, 0);
2178bc2be1d3SEric Badger 	ATF_REQUIRE(wpid == fpid);
2179bc2be1d3SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2180bc2be1d3SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
2181bc2be1d3SEric Badger 
2182bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
2183bc2be1d3SEric Badger 	    sizeof(pl)) != -1);
2184bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
2185bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
218682a4538fSEric Badger 
218782a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
218882a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
218982a4538fSEric Badger 
219082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
219182a4538fSEric Badger 
2192bc2be1d3SEric Badger 	/* The next wait() should report the SIGUSR2. */
219382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
219482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
219582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
219682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
219782a4538fSEric Badger 
219882a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
219982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_RESUME, main_lwp, 0, 0) == 0);
220082a4538fSEric Badger 
220182a4538fSEric Badger 	/*
220282a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
2203bc2be1d3SEric Badger 	 * has been resumed. The second thread has taken a SIGUSR2 which will
2204bc2be1d3SEric Badger 	 * be replaced with a SIGKILL below. The main thread will get to run
2205bc2be1d3SEric Badger 	 * first. It should notice the kill request (even though the signal
2206bc2be1d3SEric Badger 	 * replacement occurred in the other thread) and exit accordingly.  It
2207bc2be1d3SEric Badger 	 * should not stop for the system call exit event.
220882a4538fSEric Badger 	 */
220982a4538fSEric Badger 
221082a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
221182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
221282a4538fSEric Badger 
221382a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
221482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
221582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
221682a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
221782a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
221882a4538fSEric Badger 
221982a4538fSEric Badger 	wpid = wait(&status);
222082a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
222182a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
222282a4538fSEric Badger }
222382a4538fSEric Badger 
222482a4538fSEric Badger static void
222582a4538fSEric Badger sigusr1_handler(int sig)
222682a4538fSEric Badger {
222782a4538fSEric Badger 
222882a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
222982a4538fSEric Badger 	_exit(2);
223082a4538fSEric Badger }
223182a4538fSEric Badger 
223282a4538fSEric Badger /*
223382a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
223482a4538fSEric Badger  * a PT_KILL will kill the process.
223582a4538fSEric Badger  */
223682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
223782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
223882a4538fSEric Badger {
223982a4538fSEric Badger 	pid_t fpid, wpid;
224082a4538fSEric Badger 	int status;
224182a4538fSEric Badger 	int max_pending_per_proc;
224282a4538fSEric Badger 	size_t len;
224382a4538fSEric Badger 	int i;
224482a4538fSEric Badger 
224582a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
224682a4538fSEric Badger 
224782a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
224882a4538fSEric Badger 	if (fpid == 0) {
224982a4538fSEric Badger 		trace_me();
225082a4538fSEric Badger 		exit(1);
225182a4538fSEric Badger 	}
225282a4538fSEric Badger 
225382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
225482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
225582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
225682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
225782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
225882a4538fSEric Badger 
225982a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
226082a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
226182a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
226282a4538fSEric Badger 
226382a4538fSEric Badger 	/* Fill the signal queue. */
226482a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
226582a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
226682a4538fSEric Badger 
226782a4538fSEric Badger 	/* Kill the child process. */
226882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
226982a4538fSEric Badger 
227082a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
227182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
227282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
227382a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
227482a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
227582a4538fSEric Badger 
227682a4538fSEric Badger 	wpid = wait(&status);
227782a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
227882a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
227982a4538fSEric Badger }
228082a4538fSEric Badger 
228182a4538fSEric Badger /*
228282a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
228382a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
228482a4538fSEric Badger  * call is complete.
228582a4538fSEric Badger  */
228682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
228782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
228882a4538fSEric Badger {
228982a4538fSEric Badger 	struct ptrace_lwpinfo pl;
229082a4538fSEric Badger 	pid_t fpid, wpid;
229182a4538fSEric Badger 	int status;
229282a4538fSEric Badger 
229382a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
229482a4538fSEric Badger 
229582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
229682a4538fSEric Badger 	if (fpid == 0) {
229782a4538fSEric Badger 		trace_me();
229882a4538fSEric Badger 		getpid();
229982a4538fSEric Badger 		exit(1);
230082a4538fSEric Badger 	}
230182a4538fSEric Badger 
230282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
230382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
230482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
230582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
230682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
230782a4538fSEric Badger 
230882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
230982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
231082a4538fSEric Badger 
231182a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
231282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
231382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
231482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
231582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
231682a4538fSEric Badger 
231782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
231882a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
231982a4538fSEric Badger 
232082a4538fSEric Badger 	/* Continue the child process with a signal. */
232182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
232282a4538fSEric Badger 
232382a4538fSEric Badger 	for (;;) {
232482a4538fSEric Badger 		/*
232582a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
232682a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
232782a4538fSEric Badger 		 * past any syscall stops.
232882a4538fSEric Badger 		 */
232982a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
233082a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
233182a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
233282a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
233382a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
233482a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
233582a4538fSEric Badger 		} else {
233682a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
233782a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
233882a4538fSEric Badger 			break;
233982a4538fSEric Badger 		}
234082a4538fSEric Badger 	}
234182a4538fSEric Badger 
234282a4538fSEric Badger 	wpid = wait(&status);
234382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
234482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
234582a4538fSEric Badger }
234682a4538fSEric Badger 
234782a4538fSEric Badger static void
234882a4538fSEric Badger sigusr1_counting_handler(int sig)
234982a4538fSEric Badger {
235082a4538fSEric Badger 	static int counter = 0;
235182a4538fSEric Badger 
235282a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
235382a4538fSEric Badger 	counter++;
235482a4538fSEric Badger 	if (counter == 2)
235582a4538fSEric Badger 		_exit(2);
235682a4538fSEric Badger }
235782a4538fSEric Badger 
235882a4538fSEric Badger /*
235982a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
236082a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
236182a4538fSEric Badger  * the system call is complete.
236282a4538fSEric Badger  */
236382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
236482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
236582a4538fSEric Badger {
236682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
236782a4538fSEric Badger 	pid_t fpid, wpid;
236882a4538fSEric Badger 	int status;
236982a4538fSEric Badger 
237082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
237182a4538fSEric Badger 
237282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
237382a4538fSEric Badger 	if (fpid == 0) {
237482a4538fSEric Badger 		trace_me();
237582a4538fSEric Badger 		getpid();
237682a4538fSEric Badger 		exit(1);
237782a4538fSEric Badger 	}
237882a4538fSEric Badger 
237982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
238082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
238182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
238282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
238382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
238482a4538fSEric Badger 
238582a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
238682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
238782a4538fSEric Badger 
238882a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
238982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
239082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
239182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
239282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
239382a4538fSEric Badger 
239482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
239582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
239682a4538fSEric Badger 
239782a4538fSEric Badger 	/* Continue the child process with a signal. */
239882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
239982a4538fSEric Badger 
240082a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
240182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
240282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
240382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
240482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
240582a4538fSEric Badger 
240682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
240782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
240882a4538fSEric Badger 
240982a4538fSEric Badger 	/* Continue the child process with a signal. */
241082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
241182a4538fSEric Badger 
241282a4538fSEric Badger 	for (;;) {
241382a4538fSEric Badger 		/*
241482a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
241582a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
241682a4538fSEric Badger 		 * past any syscall stops.
241782a4538fSEric Badger 		 */
241882a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
241982a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
242082a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
242182a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
242282a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
242382a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
242482a4538fSEric Badger 		} else {
242582a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
242682a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
242782a4538fSEric Badger 			break;
242882a4538fSEric Badger 		}
242982a4538fSEric Badger 	}
243082a4538fSEric Badger 
243182a4538fSEric Badger 	wpid = wait(&status);
243282a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
243382a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
243482a4538fSEric Badger }
243582a4538fSEric Badger 
243682a4538fSEric Badger /*
243782a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
243882a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
243982a4538fSEric Badger  */
244082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
244182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
244282a4538fSEric Badger {
244382a4538fSEric Badger 	pid_t fpid, wpid;
244482a4538fSEric Badger 	int status;
244582a4538fSEric Badger 	int max_pending_per_proc;
244682a4538fSEric Badger 	size_t len;
244782a4538fSEric Badger 	int i;
244882a4538fSEric Badger 
244982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
245082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
245182a4538fSEric Badger 
245282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
245382a4538fSEric Badger 	if (fpid == 0) {
245482a4538fSEric Badger 		trace_me();
245582a4538fSEric Badger 		exit(1);
245682a4538fSEric Badger 	}
245782a4538fSEric Badger 
245882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
245982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
246082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
246182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
246282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
246382a4538fSEric Badger 
246482a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
246582a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
246682a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
246782a4538fSEric Badger 
246882a4538fSEric Badger 	/* Fill the signal queue. */
246982a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
247082a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
247182a4538fSEric Badger 
247282a4538fSEric Badger 	/* Continue with signal. */
247382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
247482a4538fSEric Badger 
247582a4538fSEric Badger 	for (;;) {
247682a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
247782a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
247882a4538fSEric Badger 		if (WIFSTOPPED(status)) {
247982a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
248082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
248182a4538fSEric Badger 		} else {
248282a4538fSEric Badger 			/*
248382a4538fSEric Badger 			 * The last wait() should report normal _exit from the
248482a4538fSEric Badger 			 * SIGUSR1 handler.
248582a4538fSEric Badger 			 */
248682a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
248782a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
248882a4538fSEric Badger 			break;
248982a4538fSEric Badger 		}
249082a4538fSEric Badger 	}
249182a4538fSEric Badger 
249282a4538fSEric Badger 	wpid = wait(&status);
249382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
249482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
249582a4538fSEric Badger }
249682a4538fSEric Badger 
2497753e2922SBryan Drewery static sem_t sigusr1_sem;
2498753e2922SBryan Drewery static int got_usr1;
2499753e2922SBryan Drewery 
2500753e2922SBryan Drewery static void
2501753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused)
2502753e2922SBryan Drewery {
2503753e2922SBryan Drewery 
2504753e2922SBryan Drewery 	got_usr1++;
2505753e2922SBryan Drewery 	CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0);
2506753e2922SBryan Drewery }
2507753e2922SBryan Drewery 
2508753e2922SBryan Drewery /*
2509753e2922SBryan Drewery  * Verify that even if the signal queue is full for a child process,
2510753e2922SBryan Drewery  * and the signal is masked, a PT_CONTINUE with a signal will not
2511753e2922SBryan Drewery  * result in loss of that signal.
2512753e2922SBryan Drewery  */
2513753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
2514753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
2515753e2922SBryan Drewery {
2516753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2517753e2922SBryan Drewery 	pid_t fpid, wpid;
2518753e2922SBryan Drewery 	int status, err;
2519753e2922SBryan Drewery 	int max_pending_per_proc;
2520753e2922SBryan Drewery 	size_t len;
2521753e2922SBryan Drewery 	int i;
2522753e2922SBryan Drewery 	sigset_t sigmask;
2523753e2922SBryan Drewery 
2524753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
2525753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2526753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2527753e2922SBryan Drewery 
2528753e2922SBryan Drewery 	got_usr1 = 0;
2529753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2530753e2922SBryan Drewery 	if (fpid == 0) {
2531753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2532753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2533753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2534753e2922SBryan Drewery 
2535753e2922SBryan Drewery 		trace_me();
2536753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2537753e2922SBryan Drewery 
2538753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2539753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2540753e2922SBryan Drewery 		/* Wait to receive the SIGUSR1. */
2541753e2922SBryan Drewery 		do {
2542753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2543753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2544753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2545753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2546753e2922SBryan Drewery 		exit(1);
2547753e2922SBryan Drewery 	}
2548753e2922SBryan Drewery 
2549753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2550753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2551753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2552753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2553753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2554753e2922SBryan Drewery 
2555753e2922SBryan Drewery 	len = sizeof(max_pending_per_proc);
2556753e2922SBryan Drewery 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
2557753e2922SBryan Drewery 	    &max_pending_per_proc, &len, NULL, 0) == 0);
2558753e2922SBryan Drewery 
2559753e2922SBryan Drewery 	/* Fill the signal queue. */
2560753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i)
2561753e2922SBryan Drewery 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
2562753e2922SBryan Drewery 
2563753e2922SBryan Drewery 	/* Continue with signal. */
2564753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2565753e2922SBryan Drewery 
2566753e2922SBryan Drewery 	/* Collect and ignore all of the SIGUSR2. */
2567753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i) {
2568753e2922SBryan Drewery 		wpid = waitpid(fpid, &status, 0);
2569753e2922SBryan Drewery 		ATF_REQUIRE(wpid == fpid);
2570753e2922SBryan Drewery 		ATF_REQUIRE(WIFSTOPPED(status));
2571753e2922SBryan Drewery 		ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
2572753e2922SBryan Drewery 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2573753e2922SBryan Drewery 	}
2574753e2922SBryan Drewery 
2575753e2922SBryan Drewery 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
2576753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2577753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2578753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2579753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2580753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2581753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2582753e2922SBryan Drewery 
2583753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
2584753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2585753e2922SBryan Drewery 
2586753e2922SBryan Drewery 	/* The last wait() should report exit after receiving SIGUSR1. */
2587753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2588753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2589753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2590753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2591753e2922SBryan Drewery 
2592753e2922SBryan Drewery 	wpid = wait(&status);
2593753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2594753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2595753e2922SBryan Drewery }
2596753e2922SBryan Drewery 
259782a4538fSEric Badger /*
259882a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
259982a4538fSEric Badger  * replaced with another signal.
260082a4538fSEric Badger  */
260182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
260282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
260382a4538fSEric Badger {
260482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
260582a4538fSEric Badger 	pid_t fpid, wpid;
260682a4538fSEric Badger 	int status;
260782a4538fSEric Badger 
260882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
260982a4538fSEric Badger 	if (fpid == 0) {
261082a4538fSEric Badger 		trace_me();
261182a4538fSEric Badger 		sleep(20);
261282a4538fSEric Badger 		exit(1);
261382a4538fSEric Badger 	}
261482a4538fSEric Badger 
261582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
261682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
261782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
261882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
261982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
262082a4538fSEric Badger 
262182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
262282a4538fSEric Badger 
262382a4538fSEric Badger 	/* Send a signal without ptrace. */
262482a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGINT) == 0);
262582a4538fSEric Badger 
262682a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
262782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
262882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
262982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
263082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGINT);
263182a4538fSEric Badger 
263282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
263382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
263482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGINT);
263582a4538fSEric Badger 
263682a4538fSEric Badger 	/* Continue the child process with a different signal. */
263782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM) == 0);
263882a4538fSEric Badger 
263982a4538fSEric Badger 	/*
264082a4538fSEric Badger 	 * The last wait() should report having died due to the new
264182a4538fSEric Badger 	 * signal, SIGTERM.
264282a4538fSEric Badger 	 */
264382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
264482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
264582a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
264682a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGTERM);
264782a4538fSEric Badger 
264882a4538fSEric Badger 	wpid = wait(&status);
264982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
265082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
265182a4538fSEric Badger }
265282a4538fSEric Badger 
265382a4538fSEric Badger /*
265482a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
265582a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
265682a4538fSEric Badger  * invented for e.g, system call stops.
265782a4538fSEric Badger  */
265882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
265982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
266082a4538fSEric Badger {
266182a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2662fc1e29dcSBryan Drewery 	struct rlimit rl;
266382a4538fSEric Badger 	pid_t fpid, wpid;
266482a4538fSEric Badger 	int status;
266582a4538fSEric Badger 
266682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
266782a4538fSEric Badger 	if (fpid == 0) {
266882a4538fSEric Badger 		trace_me();
2669fc1e29dcSBryan Drewery 		/* SIGTRAP expected to cause exit on syscall entry. */
2670fc1e29dcSBryan Drewery 		rl.rlim_cur = rl.rlim_max = 0;
2671fc1e29dcSBryan Drewery 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0);
267282a4538fSEric Badger 		getpid();
267382a4538fSEric Badger 		exit(1);
267482a4538fSEric Badger 	}
267582a4538fSEric Badger 
267682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
267782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
267882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
267982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
268082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
268182a4538fSEric Badger 
268282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
268382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
268482a4538fSEric Badger 
268582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
268682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
268782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
268882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
268982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
269082a4538fSEric Badger 
269182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
269282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
269382a4538fSEric Badger 
269482a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
269582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP) == 0);
269682a4538fSEric Badger 
269782a4538fSEric Badger 	for (;;) {
269882a4538fSEric Badger 		/*
269982a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
270082a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
270182a4538fSEric Badger 		 */
270282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
270382a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
270482a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
270582a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
270682a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
270782a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
270882a4538fSEric Badger 		} else {
270982a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
271082a4538fSEric Badger 			ATF_REQUIRE(WTERMSIG(status) == SIGTRAP);
271182a4538fSEric Badger 			break;
271282a4538fSEric Badger 		}
271382a4538fSEric Badger 	}
271482a4538fSEric Badger 
271582a4538fSEric Badger 	wpid = wait(&status);
271682a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
271782a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
271882a4538fSEric Badger 
271982a4538fSEric Badger }
272082a4538fSEric Badger 
272182a4538fSEric Badger /*
272282a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
272382a4538fSEric Badger  */
272482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
272582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
272682a4538fSEric Badger {
272782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
272882a4538fSEric Badger 	pid_t fpid, wpid;
272982a4538fSEric Badger 	int status;
273082a4538fSEric Badger 
273182a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
273282a4538fSEric Badger 
273382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
273482a4538fSEric Badger 	if (fpid == 0) {
273582a4538fSEric Badger 		trace_me();
273682a4538fSEric Badger 		getpid();
273782a4538fSEric Badger 		exit(1);
273882a4538fSEric Badger 	}
273982a4538fSEric Badger 
274082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
274182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
274282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
274382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
274482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
274582a4538fSEric Badger 
274682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
274782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
274882a4538fSEric Badger 
274982a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
275082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
275182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
275282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
275382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
275482a4538fSEric Badger 
275582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
275682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
275782a4538fSEric Badger 
275882a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
275982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
276082a4538fSEric Badger 
276182a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
276282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
276382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
276482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
276582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
276682a4538fSEric Badger 
276782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
276882a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
276982a4538fSEric Badger 
277082a4538fSEric Badger 	/* Send an ABRT without ptrace. */
277182a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGABRT) == 0);
277282a4538fSEric Badger 
277382a4538fSEric Badger 	/* Continue normally. */
277482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
277582a4538fSEric Badger 
277682a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
277782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
277882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
277982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
278082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
278182a4538fSEric Badger 
278282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
278382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
278482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
278582a4538fSEric Badger 
278682a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
278782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
278882a4538fSEric Badger 
278982a4538fSEric Badger 	for (;;) {
279082a4538fSEric Badger 		/*
279182a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
279282a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
279382a4538fSEric Badger 		 * past any syscall stops.
279482a4538fSEric Badger 		 */
279582a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
279682a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
279782a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
279882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
279982a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
280082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
280182a4538fSEric Badger 		} else {
280282a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
280382a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
280482a4538fSEric Badger 			break;
280582a4538fSEric Badger 		}
280682a4538fSEric Badger 	}
280782a4538fSEric Badger 
280882a4538fSEric Badger 	wpid = wait(&status);
280982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
281082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
281182a4538fSEric Badger 
281282a4538fSEric Badger }
281382a4538fSEric Badger 
281482a4538fSEric Badger /*
281582a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
281682a4538fSEric Badger  */
281782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
281882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
281982a4538fSEric Badger {
282082a4538fSEric Badger 	pid_t fpid, wpid;
282182a4538fSEric Badger 	int status, kq, nevents;
282282a4538fSEric Badger 	struct kevent kev;
282382a4538fSEric Badger 
282482a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
282582a4538fSEric Badger 
282682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
282782a4538fSEric Badger 	if (fpid == 0) {
282882a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
282982a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
283082a4538fSEric Badger 		CHILD_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0);
283182a4538fSEric Badger 
283282a4538fSEric Badger 		trace_me();
283382a4538fSEric Badger 
283482a4538fSEric Badger 		for (;;) {
283582a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
283682a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
283782a4538fSEric Badger 				continue;
283882a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
283982a4538fSEric Badger 			CHILD_REQUIRE(kev.filter == EVFILT_SIGNAL);
284082a4538fSEric Badger 			CHILD_REQUIRE(kev.ident == SIGUSR1);
284182a4538fSEric Badger 			break;
284282a4538fSEric Badger 		}
284382a4538fSEric Badger 
284482a4538fSEric Badger 		exit(1);
284582a4538fSEric Badger 	}
284682a4538fSEric Badger 
284782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
284882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
284982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
285082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
285182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
285282a4538fSEric Badger 
285382a4538fSEric Badger 	/* Continue with the SIGUSR1. */
285482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
285582a4538fSEric Badger 
285682a4538fSEric Badger 	/*
285782a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
285882a4538fSEric Badger 	 */
285982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
286082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
286182a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
286282a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
286382a4538fSEric Badger 
286482a4538fSEric Badger 	wpid = wait(&status);
286582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
286682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
286782a4538fSEric Badger }
286882a4538fSEric Badger 
286982a4538fSEric Badger static void *
287082a4538fSEric Badger signal_thread(void *arg)
287182a4538fSEric Badger {
287282a4538fSEric Badger 	int err;
287382a4538fSEric Badger 	sigset_t sigmask;
287482a4538fSEric Badger 
287582a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
287682a4538fSEric Badger 
287782a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
287882a4538fSEric Badger 	do {
287982a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
288082a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
288182a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
288282a4538fSEric Badger 
288382a4538fSEric Badger 	/* Free our companion thread from the barrier. */
288482a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
288582a4538fSEric Badger 
288682a4538fSEric Badger 	/*
288782a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
288882a4538fSEric Badger 	 * other thread.
288982a4538fSEric Badger 	 */
289082a4538fSEric Badger 	CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
289182a4538fSEric Badger 	CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
289282a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
289382a4538fSEric Badger 
289482a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
289582a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
289682a4538fSEric Badger 
289782a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
289882a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
289982a4538fSEric Badger 
290082a4538fSEric Badger 	return (NULL);
290182a4538fSEric Badger }
290282a4538fSEric Badger 
290382a4538fSEric Badger /*
2904753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2905753e2922SBryan Drewery  * signal from kill() once unmasked.
2906753e2922SBryan Drewery  */
2907753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
2908753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
2909753e2922SBryan Drewery {
2910753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2911753e2922SBryan Drewery 	pid_t fpid, wpid;
2912753e2922SBryan Drewery 	int status, err;
2913753e2922SBryan Drewery 	sigset_t sigmask;
2914753e2922SBryan Drewery 
2915753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2916753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2917753e2922SBryan Drewery 	got_usr1 = 0;
2918753e2922SBryan Drewery 
2919753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2920753e2922SBryan Drewery 	if (fpid == 0) {
2921753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2922753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2923753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2924753e2922SBryan Drewery 
2925753e2922SBryan Drewery 		trace_me();
2926753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2927753e2922SBryan Drewery 
2928753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2929753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2930753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2931753e2922SBryan Drewery 		do {
2932753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2933753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2934753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2935753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2936753e2922SBryan Drewery 		exit(1);
2937753e2922SBryan Drewery 	}
2938753e2922SBryan Drewery 
2939753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2940753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2941753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2942753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2943753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2944753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2945753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
2946753e2922SBryan Drewery 
2947753e2922SBryan Drewery 	/* Send blocked SIGUSR1 which should cause a stop. */
2948753e2922SBryan Drewery 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
2949753e2922SBryan Drewery 
2950753e2922SBryan Drewery 	/* Continue the child ignoring the SIGSTOP. */
2951753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2952753e2922SBryan Drewery 
2953753e2922SBryan Drewery 	/* The next wait() should report the kill(SIGUSR1) was received. */
2954753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2955753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2956753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2957753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2958753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2959753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2960753e2922SBryan Drewery 
2961753e2922SBryan Drewery 	/* Continue the child, allowing in the SIGUSR1. */
2962753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2963753e2922SBryan Drewery 
2964753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
2965753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2966753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2967753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2968753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2969753e2922SBryan Drewery 
2970753e2922SBryan Drewery 	wpid = wait(&status);
2971753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2972753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2973753e2922SBryan Drewery }
2974753e2922SBryan Drewery 
2975753e2922SBryan Drewery /*
2976753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2977753e2922SBryan Drewery  * signal from PT_CONTINUE once unmasked.
2978753e2922SBryan Drewery  */
2979753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
2980753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
2981753e2922SBryan Drewery {
2982753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2983753e2922SBryan Drewery 	pid_t fpid, wpid;
2984753e2922SBryan Drewery 	int status, err;
2985753e2922SBryan Drewery 	sigset_t sigmask;
2986753e2922SBryan Drewery 
2987753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2988753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2989753e2922SBryan Drewery 	got_usr1 = 0;
2990753e2922SBryan Drewery 
2991753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2992753e2922SBryan Drewery 	if (fpid == 0) {
2993753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2994753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2995753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2996753e2922SBryan Drewery 
2997753e2922SBryan Drewery 		trace_me();
2998753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2999753e2922SBryan Drewery 
3000753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
3001753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
3002753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
3003753e2922SBryan Drewery 		do {
3004753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
3005753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
3006753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
3007753e2922SBryan Drewery 
3008753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
3009753e2922SBryan Drewery 		exit(1);
3010753e2922SBryan Drewery 	}
3011753e2922SBryan Drewery 
3012753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
3013753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3014753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
3015753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
3016753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3017753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
3018753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
3019753e2922SBryan Drewery 
3020753e2922SBryan Drewery 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
3021753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
3022753e2922SBryan Drewery 
3023753e2922SBryan Drewery 	/* The next wait() should report the SIGUSR1 was received. */
3024753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3025753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
3026753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
3027753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
3028753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
3029753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
3030753e2922SBryan Drewery 
3031753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
3032753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3033753e2922SBryan Drewery 
3034753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3035753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3036753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
3037753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
3038753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3039753e2922SBryan Drewery 
3040753e2922SBryan Drewery 	wpid = wait(&status);
3041753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
3042753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
3043753e2922SBryan Drewery }
3044753e2922SBryan Drewery 
3045753e2922SBryan Drewery /*
304682a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
304782a4538fSEric Badger  * a different signal that the new signal is routed to a thread
304899144520SEitan Adler  * that can accept it, and that the thread is awakened by the signal
304982a4538fSEric Badger  * in a timely manner.
305082a4538fSEric Badger  */
305182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
305282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
305382a4538fSEric Badger {
305482a4538fSEric Badger 	pid_t fpid, wpid;
305582a4538fSEric Badger 	int status, err;
305682a4538fSEric Badger 	pthread_t t;
305782a4538fSEric Badger 	sigset_t sigmask;
305882a4538fSEric Badger 	pthread_barrier_t barrier;
305982a4538fSEric Badger 
306082a4538fSEric Badger 	ATF_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
306182a4538fSEric Badger 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
306282a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
306382a4538fSEric Badger 
306482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
306582a4538fSEric Badger 	if (fpid == 0) {
306682a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, signal_thread, (void*)&barrier) == 0);
306782a4538fSEric Badger 
306882a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
306982a4538fSEric Badger 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
307082a4538fSEric Badger 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
307182a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
307282a4538fSEric Badger 
307382a4538fSEric Badger 		trace_me();
307482a4538fSEric Badger 
307582a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
307682a4538fSEric Badger 		pthread_barrier_wait(&barrier);
307782a4538fSEric Badger 
307882a4538fSEric Badger 		/*
307982a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
308082a4538fSEric Badger 		 * thread.
308182a4538fSEric Badger 		 */
308282a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
308382a4538fSEric Badger 
308482a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
308582a4538fSEric Badger 		pthread_barrier_wait(&barrier);
308682a4538fSEric Badger 
308782a4538fSEric Badger 		/*
308882a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
308982a4538fSEric Badger 		 * now.
309082a4538fSEric Badger 		 */
309182a4538fSEric Badger 		raise(SIGSTOP);
309282a4538fSEric Badger 
309382a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
309482a4538fSEric Badger 		do {
309582a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
309682a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
309782a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
309882a4538fSEric Badger 
309982a4538fSEric Badger 		/* Free the other thread from the barrier. */
310082a4538fSEric Badger 		pthread_barrier_wait(&barrier);
310182a4538fSEric Badger 
310282a4538fSEric Badger 		CHILD_REQUIRE(pthread_join(t, NULL) == 0);
310382a4538fSEric Badger 
310482a4538fSEric Badger 		exit(1);
310582a4538fSEric Badger 	}
310682a4538fSEric Badger 
310782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
310882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
310982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
311082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
311182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
311282a4538fSEric Badger 
311382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
311482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
311582a4538fSEric Badger 
311682a4538fSEric Badger 	/*
311782a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
311882a4538fSEric Badger 	 * in this case).
311982a4538fSEric Badger 	 */
312082a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
312182a4538fSEric Badger 
312282a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
312382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
312482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
312582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
312682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
312782a4538fSEric Badger 
312882a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
312982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
313082a4538fSEric Badger 
313182a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
313282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
313382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
313482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
313582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
313682a4538fSEric Badger 
313782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
313882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
313982a4538fSEric Badger 
314082a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
314182a4538fSEric Badger 
314282a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
314382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
314482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
314582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
314682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
314782a4538fSEric Badger 
314882a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
314982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
315082a4538fSEric Badger 
315182a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
315282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
315382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
315482a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
315582a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
315682a4538fSEric Badger 
315782a4538fSEric Badger 	wpid = wait(&status);
315882a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
315982a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
316082a4538fSEric Badger }
316182a4538fSEric Badger 
3162b38bd91fSEric Badger static void *
3163b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
3164b38bd91fSEric Badger {
3165b38bd91fSEric Badger 
3166b38bd91fSEric Badger 	raise(SIGSTOP);
3167b38bd91fSEric Badger 	return NULL;
3168b38bd91fSEric Badger }
3169b38bd91fSEric Badger 
3170b38bd91fSEric Badger static void *
3171b38bd91fSEric Badger sleep_thread(void *arg __unused)
3172b38bd91fSEric Badger {
3173b38bd91fSEric Badger 
3174b38bd91fSEric Badger 	sleep(60);
3175b38bd91fSEric Badger 	return NULL;
3176b38bd91fSEric Badger }
3177b38bd91fSEric Badger 
3178b38bd91fSEric Badger static void
3179b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
3180b38bd91fSEric Badger {
3181b38bd91fSEric Badger 	pid_t fpid, wpid;
3182b38bd91fSEric Badger 	int status, i;
3183b38bd91fSEric Badger 	cpuset_t setmask;
3184b38bd91fSEric Badger 	cpusetid_t setid;
3185b38bd91fSEric Badger 	pthread_t t;
3186b38bd91fSEric Badger 
3187b38bd91fSEric Badger 	/*
3188b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
3189b38bd91fSEric Badger 	 * that both child and grandchild have died.
3190b38bd91fSEric Badger 	 */
3191b38bd91fSEric Badger 	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
3192b38bd91fSEric Badger 
3193b38bd91fSEric Badger 	fpid = fork();
3194b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
3195b38bd91fSEric Badger 	if (fpid == 0) {
3196b38bd91fSEric Badger 		fpid = fork();
3197b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
3198b38bd91fSEric Badger 		if (fpid == 0) {
3199b38bd91fSEric Badger 			trace_me();
3200b38bd91fSEric Badger 
3201b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
3202b38bd91fSEric Badger 			CPU_ZERO(&setmask);
3203b38bd91fSEric Badger 			CPU_SET(0, &setmask);
3204b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset(&setid) == 0);
3205b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
3206b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
3207b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
3208b38bd91fSEric Badger 
3209b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
3210b38bd91fSEric Badger 				/*
3211b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
3212b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
3213b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
3214b38bd91fSEric Badger 				 * threads compete.
3215b38bd91fSEric Badger 				 */
3216b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3217b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
3218b38bd91fSEric Badger 				raise(SIGSTOP);
3219b38bd91fSEric Badger 			} else {
3220b38bd91fSEric Badger 				/*
3221b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
3222b38bd91fSEric Badger 				 * this thread. After creating the new thread,
3223b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
3224b38bd91fSEric Badger 				 * raise the SIGSTOP.
3225b38bd91fSEric Badger 				 */
3226b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3227b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
3228b38bd91fSEric Badger 				sleep(60);
3229b38bd91fSEric Badger 			}
3230b38bd91fSEric Badger 
3231b38bd91fSEric Badger 			exit(0);
3232b38bd91fSEric Badger 		}
3233b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
3234b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3235b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
3236b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3237b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3238b38bd91fSEric Badger 
3239b38bd91fSEric Badger 		CHILD_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3240b38bd91fSEric Badger 
3241b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
3242b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3243b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
3244b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3245b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3246b38bd91fSEric Badger 
3247b38bd91fSEric Badger 		/*
3248b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
3249b38bd91fSEric Badger 		 * should be killed.
3250b38bd91fSEric Badger 		 */
3251b38bd91fSEric Badger 		exit(0);
3252b38bd91fSEric Badger 	}
3253b38bd91fSEric Badger 
3254b38bd91fSEric Badger 	/*
3255b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
3256b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
3257b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
3258b38bd91fSEric Badger 	 * left dangling when its parent died.
3259b38bd91fSEric Badger 	 */
3260b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
3261b38bd91fSEric Badger 		wpid = wait(&status);
3262b38bd91fSEric Badger 		if (wpid == fpid)
3263b38bd91fSEric Badger 			ATF_REQUIRE(WIFEXITED(status) &&
3264b38bd91fSEric Badger 			    WEXITSTATUS(status) == 0);
3265b38bd91fSEric Badger 		else
3266b38bd91fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status) &&
3267b38bd91fSEric Badger 			    WTERMSIG(status) == SIGKILL);
3268b38bd91fSEric Badger 	}
3269b38bd91fSEric Badger }
3270b38bd91fSEric Badger 
3271b38bd91fSEric Badger /*
3272b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
3273b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
3274b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
3275b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
3276b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
3277b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
3278b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
3279b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
3280b38bd91fSEric Badger  * past, so make no assumption.
3281b38bd91fSEric Badger  */
32823cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
32833cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
32843cf56bb4SEnji Cooper {
32853cf56bb4SEnji Cooper 
32863cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
32873cf56bb4SEnji Cooper }
3288b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
3289b38bd91fSEric Badger {
3290b38bd91fSEric Badger 
3291b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
3292b38bd91fSEric Badger }
32933cf56bb4SEnji Cooper 
32943cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
32953cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
32963cf56bb4SEnji Cooper {
32973cf56bb4SEnji Cooper 
32983cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
32993cf56bb4SEnji Cooper }
3300b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
3301b38bd91fSEric Badger {
3302b38bd91fSEric Badger 
3303b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
3304b38bd91fSEric Badger }
3305b38bd91fSEric Badger 
3306b4d33259SEric Badger /*
3307b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
3308b4d33259SEric Badger  * is not modified.
3309b4d33259SEric Badger  */
3310b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
3311b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
3312b4d33259SEric Badger {
3313b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
3314b4d33259SEric Badger 	pid_t fpid, wpid;
3315b4d33259SEric Badger 	int status, event_mask, new_event_mask;
3316b4d33259SEric Badger 
3317b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
3318b4d33259SEric Badger 	if (fpid == 0) {
3319b4d33259SEric Badger 		trace_me();
3320b4d33259SEric Badger 		raise(SIGSTOP);
3321b4d33259SEric Badger 		exit(0);
3322b4d33259SEric Badger 	}
3323b4d33259SEric Badger 
3324b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
3325b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3326b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3327b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3328b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3329b4d33259SEric Badger 
3330b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
3331b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
3332b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
3333b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
3334b4d33259SEric Badger 
3335b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
3336b4d33259SEric Badger 	ATF_REQUIRE(kill(fpid, SIGKILL) == 0);
3337b4d33259SEric Badger 
3338b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
3339b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3340b4d33259SEric Badger 
3341b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
3342b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3343b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3344b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3345b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGKILL);
3346b4d33259SEric Badger 
3347b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3348b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3349b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGKILL);
3350b4d33259SEric Badger 
3351b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
3352b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3353b4d33259SEric Badger 
3354b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
3355b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3356b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3357b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3358b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3359b4d33259SEric Badger 
3360b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
3361b4d33259SEric Badger 	new_event_mask = 0;
3362b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
3363b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
3364b4d33259SEric Badger 	ATF_REQUIRE(event_mask == new_event_mask);
3365b4d33259SEric Badger 
3366b4d33259SEric Badger 	/* Continue the child to let it exit. */
3367b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3368b4d33259SEric Badger 
3369b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
3370b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3371b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
3372b4d33259SEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
3373b4d33259SEric Badger 
3374b4d33259SEric Badger 	wpid = wait(&status);
3375b4d33259SEric Badger 	ATF_REQUIRE(wpid == -1);
3376b4d33259SEric Badger 	ATF_REQUIRE(errno == ECHILD);
3377b4d33259SEric Badger }
3378b4d33259SEric Badger 
3379d74da94cSMark Johnston static void *
3380d74da94cSMark Johnston flock_thread(void *arg)
3381d74da94cSMark Johnston {
3382d74da94cSMark Johnston 	int fd;
3383d74da94cSMark Johnston 
3384d74da94cSMark Johnston 	fd = *(int *)arg;
3385d74da94cSMark Johnston 	(void)flock(fd, LOCK_EX);
3386d74da94cSMark Johnston 	(void)flock(fd, LOCK_UN);
3387d74da94cSMark Johnston 	return (NULL);
3388d74da94cSMark Johnston }
3389d74da94cSMark Johnston 
3390d74da94cSMark Johnston /*
3391d74da94cSMark Johnston  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
3392d74da94cSMark Johnston  * We rely on the fact that the lockf implementation sets SBDRY before blocking
3393d74da94cSMark Johnston  * on a lock. This is a regression test for r318191.
3394d74da94cSMark Johnston  */
3395d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
3396d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
3397d74da94cSMark Johnston {
3398d74da94cSMark Johnston 	pthread_barrier_t barrier;
3399d74da94cSMark Johnston 	pthread_barrierattr_t battr;
3400d74da94cSMark Johnston 	char tmpfile[64];
3401d74da94cSMark Johnston 	pid_t child, wpid;
3402d74da94cSMark Johnston 	int error, fd, i, status;
3403d74da94cSMark Johnston 
3404d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_init(&battr) == 0);
3405d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
3406d74da94cSMark Johnston 	    PTHREAD_PROCESS_SHARED) == 0);
3407d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrier_init(&barrier, &battr, 2) == 0);
3408d74da94cSMark Johnston 
3409d74da94cSMark Johnston 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
3410d74da94cSMark Johnston 	fd = mkstemp(tmpfile);
3411d74da94cSMark Johnston 	ATF_REQUIRE(fd >= 0);
3412d74da94cSMark Johnston 
3413d74da94cSMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
3414d74da94cSMark Johnston 	if (child == 0) {
3415d74da94cSMark Johnston 		pthread_t t[2];
341696437391SBryan Drewery 		int cfd;
3417d74da94cSMark Johnston 
3418d74da94cSMark Johnston 		error = pthread_barrier_wait(&barrier);
3419d74da94cSMark Johnston 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
3420d74da94cSMark Johnston 			_exit(1);
3421d74da94cSMark Johnston 
3422d74da94cSMark Johnston 		cfd = open(tmpfile, O_RDONLY);
3423d74da94cSMark Johnston 		if (cfd < 0)
3424d74da94cSMark Johnston 			_exit(1);
3425d74da94cSMark Johnston 
3426d74da94cSMark Johnston 		/*
3427d74da94cSMark Johnston 		 * We want at least two threads blocked on the file lock since
3428d74da94cSMark Johnston 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
3429d74da94cSMark Johnston 		 * sleep.
3430d74da94cSMark Johnston 		 */
3431d74da94cSMark Johnston 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
3432d74da94cSMark Johnston 			_exit(1);
3433d74da94cSMark Johnston 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
3434d74da94cSMark Johnston 			_exit(1);
3435d74da94cSMark Johnston 		if (pthread_join(t[0], NULL) != 0)
3436d74da94cSMark Johnston 			_exit(1);
3437d74da94cSMark Johnston 		if (pthread_join(t[1], NULL) != 0)
3438d74da94cSMark Johnston 			_exit(1);
3439d74da94cSMark Johnston 		_exit(0);
3440d74da94cSMark Johnston 	}
3441d74da94cSMark Johnston 
3442d74da94cSMark Johnston 	ATF_REQUIRE(flock(fd, LOCK_EX) == 0);
3443d74da94cSMark Johnston 
3444d74da94cSMark Johnston 	error = pthread_barrier_wait(&barrier);
3445d74da94cSMark Johnston 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
3446d74da94cSMark Johnston 
3447d74da94cSMark Johnston 	/*
3448d74da94cSMark Johnston 	 * Give the child some time to block. Is there a better way to do this?
3449d74da94cSMark Johnston 	 */
3450d74da94cSMark Johnston 	sleep(1);
3451d74da94cSMark Johnston 
3452d74da94cSMark Johnston 	/*
3453d74da94cSMark Johnston 	 * Attach and give the child 3 seconds to stop.
3454d74da94cSMark Johnston 	 */
3455d74da94cSMark Johnston 	ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0);
3456d74da94cSMark Johnston 	for (i = 0; i < 3; i++) {
3457d74da94cSMark Johnston 		wpid = waitpid(child, &status, WNOHANG);
3458d74da94cSMark Johnston 		if (wpid == child && WIFSTOPPED(status) &&
3459d74da94cSMark Johnston 		    WSTOPSIG(status) == SIGSTOP)
3460d74da94cSMark Johnston 			break;
3461d74da94cSMark Johnston 		sleep(1);
3462d74da94cSMark Johnston 	}
3463d74da94cSMark Johnston 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
3464d74da94cSMark Johnston 
3465d74da94cSMark Johnston 	ATF_REQUIRE(ptrace(PT_DETACH, child, NULL, 0) == 0);
3466d74da94cSMark Johnston 
3467d74da94cSMark Johnston 	ATF_REQUIRE(flock(fd, LOCK_UN) == 0);
3468d74da94cSMark Johnston 	ATF_REQUIRE(unlink(tmpfile) == 0);
3469d74da94cSMark Johnston 	ATF_REQUIRE(close(fd) == 0);
3470d74da94cSMark Johnston }
3471d74da94cSMark Johnston 
347254cfb29eSJohn Baldwin static void
347354cfb29eSJohn Baldwin sigusr1_step_handler(int sig)
347454cfb29eSJohn Baldwin {
347554cfb29eSJohn Baldwin 
347654cfb29eSJohn Baldwin 	CHILD_REQUIRE(sig == SIGUSR1);
347754cfb29eSJohn Baldwin 	raise(SIGABRT);
347854cfb29eSJohn Baldwin }
347954cfb29eSJohn Baldwin 
348054cfb29eSJohn Baldwin /*
348154cfb29eSJohn Baldwin  * Verify that PT_STEP with a signal invokes the signal before
348254cfb29eSJohn Baldwin  * stepping the next instruction (and that the next instruction is
348354cfb29eSJohn Baldwin  * stepped correctly).
348454cfb29eSJohn Baldwin  */
348554cfb29eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal);
348654cfb29eSJohn Baldwin ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
348754cfb29eSJohn Baldwin {
348854cfb29eSJohn Baldwin 	struct ptrace_lwpinfo pl;
348954cfb29eSJohn Baldwin 	pid_t fpid, wpid;
349054cfb29eSJohn Baldwin 	int status;
349154cfb29eSJohn Baldwin 
349254cfb29eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
349354cfb29eSJohn Baldwin 	if (fpid == 0) {
349454cfb29eSJohn Baldwin 		trace_me();
349554cfb29eSJohn Baldwin 		signal(SIGUSR1, sigusr1_step_handler);
349654cfb29eSJohn Baldwin 		raise(SIGABRT);
349754cfb29eSJohn Baldwin 		exit(1);
349854cfb29eSJohn Baldwin 	}
349954cfb29eSJohn Baldwin 
350054cfb29eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
350154cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
350254cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
350354cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
350454cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
350554cfb29eSJohn Baldwin 
350654cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
350754cfb29eSJohn Baldwin 
350854cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
350954cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
351054cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
351154cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
351254cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
351354cfb29eSJohn Baldwin 
351454cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
351554cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
351654cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
351754cfb29eSJohn Baldwin 
351854cfb29eSJohn Baldwin 	/* Step the child process inserting SIGUSR1. */
351954cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1) == 0);
352054cfb29eSJohn Baldwin 
352154cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the signal handler. */
352254cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
352354cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
352454cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
352554cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
352654cfb29eSJohn Baldwin 
352754cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
352854cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
352954cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
353054cfb29eSJohn Baldwin 
353154cfb29eSJohn Baldwin 	/* Continue the child process discarding the signal. */
353254cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
353354cfb29eSJohn Baldwin 
353454cfb29eSJohn Baldwin 	/* The next stop should report a trace trap from PT_STEP. */
353554cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
353654cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
353754cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
353854cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
353954cfb29eSJohn Baldwin 
354054cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
354154cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
354254cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
354354cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE);
354454cfb29eSJohn Baldwin 
354554cfb29eSJohn Baldwin 	/* Continue the child to let it exit. */
354654cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
354754cfb29eSJohn Baldwin 
354854cfb29eSJohn Baldwin 	/* The last event should be for the child process's exit. */
354954cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
355054cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
355154cfb29eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
355254cfb29eSJohn Baldwin 
355354cfb29eSJohn Baldwin 	wpid = wait(&status);
355454cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
355554cfb29eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
355654cfb29eSJohn Baldwin }
355754cfb29eSJohn Baldwin 
3558643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3559643ce7deSJohn Baldwin /*
3560643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported
3561643ce7deSJohn Baldwin  * for a breakpoint trap.
3562643ce7deSJohn Baldwin  */
3563643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo);
3564643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__breakpoint_siginfo, tc)
3565643ce7deSJohn Baldwin {
3566643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3567643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3568643ce7deSJohn Baldwin 	int status;
3569643ce7deSJohn Baldwin 
3570643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3571643ce7deSJohn Baldwin 	if (fpid == 0) {
3572643ce7deSJohn Baldwin 		trace_me();
3573643ce7deSJohn Baldwin 		breakpoint();
3574643ce7deSJohn Baldwin 		exit(1);
3575643ce7deSJohn Baldwin 	}
3576643ce7deSJohn Baldwin 
3577643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3578643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3579643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3580643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3581643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3582643ce7deSJohn Baldwin 
3583643ce7deSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
3584643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3585643ce7deSJohn Baldwin 
3586643ce7deSJohn Baldwin 	/* The second wait() should report hitting the breakpoint. */
3587643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3588643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3589643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3590643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3591643ce7deSJohn Baldwin 
3592643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3593643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3594643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
3595643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_BRKPT);
3596643ce7deSJohn Baldwin 
3597643ce7deSJohn Baldwin 	/* Kill the child process. */
3598643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
3599643ce7deSJohn Baldwin 
3600643ce7deSJohn Baldwin 	/* The last wait() should report the SIGKILL. */
3601643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3602643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3603643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSIGNALED(status));
3604643ce7deSJohn Baldwin 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
3605643ce7deSJohn Baldwin 
3606643ce7deSJohn Baldwin 	wpid = wait(&status);
3607643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3608643ce7deSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3609643ce7deSJohn Baldwin }
3610643ce7deSJohn Baldwin #endif /* HAVE_BREAKPOINT */
3611643ce7deSJohn Baldwin 
3612643ce7deSJohn Baldwin /*
3613643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_TRACE code is reported
3614643ce7deSJohn Baldwin  * for a single-step trap from PT_STEP.
3615643ce7deSJohn Baldwin  */
3616643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo);
3617643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__step_siginfo, tc)
3618643ce7deSJohn Baldwin {
3619643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3620643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3621643ce7deSJohn Baldwin 	int status;
3622643ce7deSJohn Baldwin 
3623643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3624643ce7deSJohn Baldwin 	if (fpid == 0) {
3625643ce7deSJohn Baldwin 		trace_me();
3626643ce7deSJohn Baldwin 		exit(1);
3627643ce7deSJohn Baldwin 	}
3628643ce7deSJohn Baldwin 
3629643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3630643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3631643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3632643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3633643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3634643ce7deSJohn Baldwin 
3635643ce7deSJohn Baldwin 	/* Step the child ignoring the SIGSTOP. */
3636643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, 0) == 0);
3637643ce7deSJohn Baldwin 
3638643ce7deSJohn Baldwin 	/* The second wait() should report a single-step trap. */
3639643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3640643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3641643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3642643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3643643ce7deSJohn Baldwin 
3644643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3645643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3646643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
3647643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE);
3648643ce7deSJohn Baldwin 
3649643ce7deSJohn Baldwin 	/* Continue the child process. */
3650643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3651643ce7deSJohn Baldwin 
3652643ce7deSJohn Baldwin 	/* The last event should be for the child process's exit. */
3653643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3654643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3655643ce7deSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3656643ce7deSJohn Baldwin 
3657643ce7deSJohn Baldwin 	wpid = wait(&status);
3658643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3659643ce7deSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3660643ce7deSJohn Baldwin }
3661643ce7deSJohn Baldwin 
3662403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3663e012fe34SJohn Baldwin static void *
3664e0a40f30SJohn Baldwin continue_thread(void *arg __unused)
3665e012fe34SJohn Baldwin {
3666e012fe34SJohn Baldwin 	breakpoint();
3667e012fe34SJohn Baldwin 	return (NULL);
3668e012fe34SJohn Baldwin }
3669e012fe34SJohn Baldwin 
3670e012fe34SJohn Baldwin static __dead2 void
3671e012fe34SJohn Baldwin continue_thread_main(void)
3672e012fe34SJohn Baldwin {
3673e012fe34SJohn Baldwin 	pthread_t threads[2];
3674e012fe34SJohn Baldwin 
3675e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
3676e012fe34SJohn Baldwin 	    NULL) == 0);
3677e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
3678e012fe34SJohn Baldwin 	    NULL) == 0);
3679e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_join(threads[0], NULL) == 0);
3680e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_join(threads[1], NULL) == 0);
3681e012fe34SJohn Baldwin 	exit(1);
3682e012fe34SJohn Baldwin }
3683e012fe34SJohn Baldwin 
3684e012fe34SJohn Baldwin /*
3685e012fe34SJohn Baldwin  * Ensure that PT_CONTINUE clears the status of the thread that
3686e012fe34SJohn Baldwin  * triggered the stop even if a different thread's LWP was passed to
3687e012fe34SJohn Baldwin  * PT_CONTINUE.
3688e012fe34SJohn Baldwin  */
3689e012fe34SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
3690e012fe34SJohn Baldwin ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
3691e012fe34SJohn Baldwin {
3692e012fe34SJohn Baldwin 	struct ptrace_lwpinfo pl;
3693e012fe34SJohn Baldwin 	pid_t fpid, wpid;
3694e012fe34SJohn Baldwin 	lwpid_t lwps[2];
3695e012fe34SJohn Baldwin 	bool hit_break[2];
3696403e331dSJohn Baldwin 	struct reg reg;
3697e012fe34SJohn Baldwin 	int i, j, status;
3698e012fe34SJohn Baldwin 
3699e012fe34SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3700e012fe34SJohn Baldwin 	if (fpid == 0) {
3701e012fe34SJohn Baldwin 		trace_me();
3702e012fe34SJohn Baldwin 		continue_thread_main();
3703e012fe34SJohn Baldwin 	}
3704e012fe34SJohn Baldwin 
3705e012fe34SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3706e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3707e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3708e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3709e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3710e012fe34SJohn Baldwin 
3711e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3712e012fe34SJohn Baldwin 	    sizeof(pl)) != -1);
3713e012fe34SJohn Baldwin 
3714e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
3715e012fe34SJohn Baldwin 
3716e012fe34SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
3717e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3718e012fe34SJohn Baldwin 
3719e012fe34SJohn Baldwin 	/* One of the new threads should report it's birth. */
3720e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3721e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3722e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3723e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3724e012fe34SJohn Baldwin 
3725e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3726e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
3727e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3728e012fe34SJohn Baldwin 	lwps[0] = pl.pl_lwpid;
3729e012fe34SJohn Baldwin 
3730e012fe34SJohn Baldwin 	/*
3731e012fe34SJohn Baldwin 	 * Suspend this thread to ensure both threads are alive before
3732e012fe34SJohn Baldwin 	 * hitting the breakpoint.
3733e012fe34SJohn Baldwin 	 */
3734e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
3735e012fe34SJohn Baldwin 
3736e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3737e012fe34SJohn Baldwin 
3738e012fe34SJohn Baldwin 	/* Second thread should report it's birth. */
3739e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3740e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3741e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3742e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3743e012fe34SJohn Baldwin 
3744e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3745e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
3746e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3747e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
3748e012fe34SJohn Baldwin 	lwps[1] = pl.pl_lwpid;
3749e012fe34SJohn Baldwin 
3750e012fe34SJohn Baldwin 	/* Resume both threads waiting for breakpoint events. */
3751e012fe34SJohn Baldwin 	hit_break[0] = hit_break[1] = false;
3752e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
3753e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3754e012fe34SJohn Baldwin 
3755e012fe34SJohn Baldwin 	/* One thread should report a breakpoint. */
3756e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3757e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3758e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3759e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3760e012fe34SJohn Baldwin 
3761e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3762e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3763e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
3764e012fe34SJohn Baldwin 	    pl.pl_siginfo.si_code == TRAP_BRKPT);
3765e012fe34SJohn Baldwin 	if (pl.pl_lwpid == lwps[0])
3766e012fe34SJohn Baldwin 		i = 0;
3767e012fe34SJohn Baldwin 	else
3768e012fe34SJohn Baldwin 		i = 1;
3769e012fe34SJohn Baldwin 	hit_break[i] = true;
3770403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3771403e331dSJohn Baldwin 	SKIP_BREAK(&reg);
3772403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3773e012fe34SJohn Baldwin 
3774e012fe34SJohn Baldwin 	/*
3775e012fe34SJohn Baldwin 	 * Resume both threads but pass the other thread's LWPID to
3776e012fe34SJohn Baldwin 	 * PT_CONTINUE.
3777e012fe34SJohn Baldwin 	 */
3778e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0) == 0);
3779e012fe34SJohn Baldwin 
3780e012fe34SJohn Baldwin 	/*
3781e012fe34SJohn Baldwin 	 * Will now get two thread exit events and one more breakpoint
3782e012fe34SJohn Baldwin 	 * event.
3783e012fe34SJohn Baldwin 	 */
3784e012fe34SJohn Baldwin 	for (j = 0; j < 3; j++) {
3785e012fe34SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
3786e012fe34SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
3787e012fe34SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
3788e012fe34SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3789e012fe34SJohn Baldwin 
3790e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3791e012fe34SJohn Baldwin 		    sizeof(pl)) != -1);
3792e012fe34SJohn Baldwin 
3793e012fe34SJohn Baldwin 		if (pl.pl_lwpid == lwps[0])
3794e012fe34SJohn Baldwin 			i = 0;
3795e012fe34SJohn Baldwin 		else
3796e012fe34SJohn Baldwin 			i = 1;
3797e012fe34SJohn Baldwin 
3798e012fe34SJohn Baldwin 		ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
3799e012fe34SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_EXITED) {
3800e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(hit_break[i],
3801e012fe34SJohn Baldwin 			    "exited thread did not report breakpoint");
3802e012fe34SJohn Baldwin 			lwps[i] = 0;
3803e012fe34SJohn Baldwin 		} else {
3804e012fe34SJohn Baldwin 			ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3805e012fe34SJohn Baldwin 			ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
3806e012fe34SJohn Baldwin 			    pl.pl_siginfo.si_code == TRAP_BRKPT);
3807e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(!hit_break[i],
3808e012fe34SJohn Baldwin 			    "double breakpoint event");
3809e012fe34SJohn Baldwin 			hit_break[i] = true;
3810403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
3811403e331dSJohn Baldwin 			    0) != -1);
3812403e331dSJohn Baldwin 			SKIP_BREAK(&reg);
3813403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
3814403e331dSJohn Baldwin 			    0) != -1);
3815e012fe34SJohn Baldwin 		}
3816e012fe34SJohn Baldwin 
3817e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3818e012fe34SJohn Baldwin 	}
3819e012fe34SJohn Baldwin 
3820e012fe34SJohn Baldwin 	/* Both threads should have exited. */
3821e012fe34SJohn Baldwin 	ATF_REQUIRE(lwps[0] == 0);
3822e012fe34SJohn Baldwin 	ATF_REQUIRE(lwps[1] == 0);
3823e012fe34SJohn Baldwin 
3824e012fe34SJohn Baldwin 	/* The last event should be for the child process's exit. */
3825e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3826e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3827e012fe34SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3828e012fe34SJohn Baldwin 
3829e012fe34SJohn Baldwin 	wpid = wait(&status);
3830e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3831e012fe34SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3832e012fe34SJohn Baldwin }
3833e012fe34SJohn Baldwin #endif
3834e012fe34SJohn Baldwin 
3835c5786670SJohn Baldwin /*
3836c5786670SJohn Baldwin  * Verify that PT_LWPINFO doesn't return stale siginfo.
3837c5786670SJohn Baldwin  */
3838c5786670SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_LWPINFO_stale_siginfo);
3839c5786670SJohn Baldwin ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo, tc)
3840c5786670SJohn Baldwin {
3841c5786670SJohn Baldwin 	struct ptrace_lwpinfo pl;
3842c5786670SJohn Baldwin 	pid_t fpid, wpid;
3843c5786670SJohn Baldwin 	int events, status;
3844c5786670SJohn Baldwin 
3845c5786670SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3846c5786670SJohn Baldwin 	if (fpid == 0) {
3847c5786670SJohn Baldwin 		trace_me();
3848c5786670SJohn Baldwin 		raise(SIGABRT);
3849c5786670SJohn Baldwin 		exit(1);
3850c5786670SJohn Baldwin 	}
3851c5786670SJohn Baldwin 
3852c5786670SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3853c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3854c5786670SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3855c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3856c5786670SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3857c5786670SJohn Baldwin 
3858c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3859c5786670SJohn Baldwin 
3860c5786670SJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
3861c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3862c5786670SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3863c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3864c5786670SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
3865c5786670SJohn Baldwin 
3866c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3867c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3868c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
3869c5786670SJohn Baldwin 
3870c5786670SJohn Baldwin 	/*
3871c5786670SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
3872c5786670SJohn Baldwin 	 * syscall traps.
3873c5786670SJohn Baldwin 	 */
3874c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
3875c5786670SJohn Baldwin 
3876c5786670SJohn Baldwin 	/*
3877c5786670SJohn Baldwin 	 * The next stop should report a system call entry from
3878c5786670SJohn Baldwin 	 * exit().  PL_FLAGS_SI should not be set.
3879c5786670SJohn Baldwin 	 */
3880c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3881c5786670SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3882c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3883c5786670SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3884c5786670SJohn Baldwin 
3885c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3886c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
3887c5786670SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) == 0);
3888c5786670SJohn Baldwin 
3889c5786670SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
3890c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
3891c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3892c5786670SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
3893c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
3894c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3895c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3896c5786670SJohn Baldwin 
3897c5786670SJohn Baldwin 	/* The last event should be for the child process's exit. */
3898c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3899c5786670SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3900c5786670SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3901c5786670SJohn Baldwin 
3902c5786670SJohn Baldwin 	wpid = wait(&status);
3903c5786670SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3904c5786670SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3905c5786670SJohn Baldwin }
3906c5786670SJohn Baldwin 
3907c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
3908c209e3e2SJohn Baldwin {
3909c209e3e2SJohn Baldwin 
3910c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
3911c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
391257c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
391357c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
3914*128c9bc0SMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
391598685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
391698685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
391798685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
391898685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
391998685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
392098685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
392198685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
392298685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
3923368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
3924189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
3925189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
3926189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
39275fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
39285fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
39293340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
39308d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
39318d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
39328d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
3933fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
3934fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
3935403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
393682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
3937e2ebfbbfSEric Badger #endif
393882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
393982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
394082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
394182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
394282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
394382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
394482a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
394582a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
394682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
3947753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
394882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
394982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
395082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
395182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
3952753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
3953753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
395482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
3955b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
3956b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
3957b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
3958d74da94cSMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
395954cfb29eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
3960643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3961643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo);
3962643ce7deSJohn Baldwin #endif
3963643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__step_siginfo);
3964403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3965e012fe34SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
3966e012fe34SJohn Baldwin #endif
3967c5786670SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
3968c209e3e2SJohn Baldwin 
3969c209e3e2SJohn Baldwin 	return (atf_no_error());
3970c209e3e2SJohn Baldwin }
3971