xref: /freebsd/tests/sys/kern/ptrace_test.c (revision 96a9e50e63bfcbca7309c012c2c7a477c8826824)
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>
35fd631bcdSMariusz Zaborski #include <sys/procdesc.h>
36e21f96a8SKyle Evans #define	_WANT_MIPS_REGNUM
37c209e3e2SJohn Baldwin #include <sys/ptrace.h>
38bc2be1d3SEric Badger #include <sys/queue.h>
39bc2be1d3SEric Badger #include <sys/runq.h>
40189ac973SJohn Baldwin #include <sys/syscall.h>
4157c74f5bSJohn Baldwin #include <sys/sysctl.h>
4257c74f5bSJohn Baldwin #include <sys/user.h>
43c209e3e2SJohn Baldwin #include <sys/wait.h>
44c209e3e2SJohn Baldwin #include <errno.h>
459e0d1159SEric Badger #include <machine/cpufunc.h>
46189ac973SJohn Baldwin #include <pthread.h>
47bc2be1d3SEric Badger #include <sched.h>
4882a4538fSEric Badger #include <semaphore.h>
49c209e3e2SJohn Baldwin #include <signal.h>
50*96a9e50eSAlex Richardson #include <stdarg.h>
51dfa8ba12SJohn Baldwin #include <stdio.h>
52c209e3e2SJohn Baldwin #include <stdlib.h>
53c209e3e2SJohn Baldwin #include <unistd.h>
54c209e3e2SJohn Baldwin #include <atf-c.h>
55c209e3e2SJohn Baldwin 
56c209e3e2SJohn Baldwin /*
57403e331dSJohn Baldwin  * Architectures with a user-visible breakpoint().
58403e331dSJohn Baldwin  */
59a9c91abdSJohn Baldwin #if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) ||	\
60a9c91abdSJohn Baldwin     defined(__i386__) || defined(__mips__) || defined(__riscv) ||	\
61a9c91abdSJohn Baldwin     defined(__sparc64__)
62403e331dSJohn Baldwin #define	HAVE_BREAKPOINT
63403e331dSJohn Baldwin #endif
64403e331dSJohn Baldwin 
65403e331dSJohn Baldwin /*
66403e331dSJohn Baldwin  * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap.
67403e331dSJohn Baldwin  */
68403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
69a9c91abdSJohn Baldwin #if defined(__aarch64__)
70a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->elr += 4)
71a9c91abdSJohn Baldwin #elif defined(__amd64__) || defined(__i386__)
72403e331dSJohn Baldwin #define	SKIP_BREAK(reg)
73a9c91abdSJohn Baldwin #elif defined(__arm__)
74a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_pc += 4)
75bd061c39SJohn Baldwin #elif defined(__mips__)
76bd061c39SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_regs[PC] += 4)
77ca75fa17SJohn Baldwin #elif defined(__riscv)
78ca75fa17SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->sepc += 4)
79403e331dSJohn Baldwin #elif defined(__sparc64__)
80403e331dSJohn Baldwin #define	SKIP_BREAK(reg)	do {						\
81403e331dSJohn Baldwin 	(reg)->r_tpc = (reg)->r_tnpc + 4;				\
82403e331dSJohn Baldwin 	(reg)->r_tnpc += 8;						\
83403e331dSJohn Baldwin } while (0)
84403e331dSJohn Baldwin #endif
85403e331dSJohn Baldwin #endif
86403e331dSJohn Baldwin 
87403e331dSJohn Baldwin /*
88dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
89dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
90dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
91dfa8ba12SJohn Baldwin  */
92dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {				\
93dfa8ba12SJohn Baldwin 	if (!(exp))					\
94dfa8ba12SJohn Baldwin 		child_fail_require(__FILE__, __LINE__,	\
95*96a9e50eSAlex Richardson 		    #exp " not met\n");			\
96*96a9e50eSAlex Richardson } while (0)
97*96a9e50eSAlex Richardson 
98*96a9e50eSAlex Richardson #define	CHILD_REQUIRE_EQ(actual, expected) do {			\
99*96a9e50eSAlex Richardson 	__typeof__(expected) _e = expected;			\
100*96a9e50eSAlex Richardson 	__typeof__(actual) _a = actual;				\
101*96a9e50eSAlex Richardson 	if (_e != _a)						\
102*96a9e50eSAlex Richardson 		child_fail_require(__FILE__, __LINE__, #actual	\
103*96a9e50eSAlex Richardson 		    " (%jd) == " #expected " (%jd) not met\n",	\
104*96a9e50eSAlex Richardson 		    (intmax_t)_a, (intmax_t)_e);		\
105dfa8ba12SJohn Baldwin } while (0)
106dfa8ba12SJohn Baldwin 
10798685dc8SJohn Baldwin static __dead2 void
108*96a9e50eSAlex Richardson child_fail_require(const char *file, int line, const char *fmt, ...)
109dfa8ba12SJohn Baldwin {
110*96a9e50eSAlex Richardson 	va_list ap;
111*96a9e50eSAlex Richardson 	char buf[1024];
112dfa8ba12SJohn Baldwin 
113*96a9e50eSAlex Richardson 	/* Use write() not fprintf() to avoid possible duplicate output. */
114*96a9e50eSAlex Richardson 	snprintf(buf, sizeof(buf), "%s:%d: ", file, line);
115*96a9e50eSAlex Richardson 	write(STDERR_FILENO, buf, strlen(buf));
116*96a9e50eSAlex Richardson 	va_start(ap, fmt);
117*96a9e50eSAlex Richardson 	vsnprintf(buf, sizeof(buf), fmt, ap);
118*96a9e50eSAlex Richardson 	write(STDERR_FILENO, buf, strlen(buf));
119*96a9e50eSAlex Richardson 	va_end(ap);
120*96a9e50eSAlex Richardson 
121dfa8ba12SJohn Baldwin 	_exit(32);
122dfa8ba12SJohn Baldwin }
123dfa8ba12SJohn Baldwin 
124*96a9e50eSAlex Richardson #define	REQUIRE_EQ(actual, expected) do {				\
125*96a9e50eSAlex Richardson 	__typeof__(expected) _e = expected;				\
126*96a9e50eSAlex Richardson 	__typeof__(actual) _a = actual;					\
127*96a9e50eSAlex Richardson 	ATF_REQUIRE_MSG(_e == _a, #actual " (%jd) == "			\
128*96a9e50eSAlex Richardson 	    #expected " (%jd) not met", (intmax_t)_a, (intmax_t)_e);	\
129*96a9e50eSAlex Richardson } while (0)
130*96a9e50eSAlex Richardson 
13198685dc8SJohn Baldwin static void
13298685dc8SJohn Baldwin trace_me(void)
13398685dc8SJohn Baldwin {
13498685dc8SJohn Baldwin 
13598685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
13698685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13798685dc8SJohn Baldwin 
13898685dc8SJohn Baldwin 	/* Trigger a stop. */
13998685dc8SJohn Baldwin 	raise(SIGSTOP);
14098685dc8SJohn Baldwin }
14198685dc8SJohn Baldwin 
14298685dc8SJohn Baldwin static void
14398685dc8SJohn Baldwin attach_child(pid_t pid)
14498685dc8SJohn Baldwin {
14598685dc8SJohn Baldwin 	pid_t wpid;
14698685dc8SJohn Baldwin 	int status;
14798685dc8SJohn Baldwin 
148*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, pid, NULL, 0), 0);
14998685dc8SJohn Baldwin 
15098685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
151*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, pid);
15298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
153*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15498685dc8SJohn Baldwin }
15598685dc8SJohn Baldwin 
15698685dc8SJohn Baldwin static void
15798685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
15898685dc8SJohn Baldwin {
15998685dc8SJohn Baldwin 
16098685dc8SJohn Baldwin 	/*
16198685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
16298685dc8SJohn Baldwin 	 * there is not a better way.
1633a014c56SJohn Baldwin 	 *
1643a014c56SJohn Baldwin 	 * Prior to r325719, the kern.proc.pid.<pid> sysctl failed
1653a014c56SJohn Baldwin 	 * with ESRCH.  After that change, a valid struct kinfo_proc
1663a014c56SJohn Baldwin 	 * is returned for zombies with ki_stat set to SZOMB.
16798685dc8SJohn Baldwin 	 */
16898685dc8SJohn Baldwin 	for (;;) {
16998685dc8SJohn Baldwin 		struct kinfo_proc kp;
17098685dc8SJohn Baldwin 		size_t len;
17198685dc8SJohn Baldwin 		int mib[4];
17298685dc8SJohn Baldwin 
17398685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
17498685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
17598685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
17698685dc8SJohn Baldwin 		mib[3] = pid;
17798685dc8SJohn Baldwin 		len = sizeof(kp);
17898685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
179*96a9e50eSAlex Richardson 			REQUIRE_EQ(errno, ESRCH);
18098685dc8SJohn Baldwin 			break;
18198685dc8SJohn Baldwin 		}
1823a014c56SJohn Baldwin 		if (kp.ki_stat == SZOMB)
1833a014c56SJohn Baldwin 			break;
18498685dc8SJohn Baldwin 		usleep(5000);
18598685dc8SJohn Baldwin 	}
18698685dc8SJohn Baldwin }
18798685dc8SJohn Baldwin 
188dfa8ba12SJohn Baldwin /*
189c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
190c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
191c209e3e2SJohn Baldwin  */
192c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
193c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
194c209e3e2SJohn Baldwin {
195c209e3e2SJohn Baldwin 	pid_t child, wpid;
196c209e3e2SJohn Baldwin 	int status;
197c209e3e2SJohn Baldwin 
198c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
199c209e3e2SJohn Baldwin 	if (child == 0) {
200c209e3e2SJohn Baldwin 		/* Child process. */
20198685dc8SJohn Baldwin 		trace_me();
202c209e3e2SJohn Baldwin 
203b98cb919SJohn Baldwin 		_exit(1);
204c209e3e2SJohn Baldwin 	}
205c209e3e2SJohn Baldwin 
206c209e3e2SJohn Baldwin 	/* Parent process. */
207c209e3e2SJohn Baldwin 
208c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
209c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
210*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
211c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
212*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
213c209e3e2SJohn Baldwin 
214c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
215c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
216c209e3e2SJohn Baldwin 
217c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
218c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
219*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
220c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
221*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
222c209e3e2SJohn Baldwin 
223c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
224c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
225*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
226*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
227c209e3e2SJohn Baldwin }
228c209e3e2SJohn Baldwin 
229c209e3e2SJohn Baldwin /*
230c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
231c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
232c209e3e2SJohn Baldwin  */
233c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
234c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
235c209e3e2SJohn Baldwin {
236c209e3e2SJohn Baldwin 	pid_t child, wpid;
237c209e3e2SJohn Baldwin 	int cpipe[2], status;
238c209e3e2SJohn Baldwin 	char c;
239c209e3e2SJohn Baldwin 
240f192f648SLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
241f192f648SLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/244055");
242f192f648SLi-Wen Hsu 
243*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
244c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
245c209e3e2SJohn Baldwin 	if (child == 0) {
246c209e3e2SJohn Baldwin 		/* Child process. */
247c209e3e2SJohn Baldwin 		close(cpipe[0]);
248c209e3e2SJohn Baldwin 
249c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
250*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(0, read(cpipe[1], &c, sizeof(c)));
251c209e3e2SJohn Baldwin 
252b98cb919SJohn Baldwin 		_exit(1);
253c209e3e2SJohn Baldwin 	}
254c209e3e2SJohn Baldwin 	close(cpipe[1]);
255c209e3e2SJohn Baldwin 
256c209e3e2SJohn Baldwin 	/* Parent process. */
257c209e3e2SJohn Baldwin 
258c209e3e2SJohn Baldwin 	/* Attach to the child process. */
25998685dc8SJohn Baldwin 	attach_child(child);
260c209e3e2SJohn Baldwin 
261c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
262c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
263c209e3e2SJohn Baldwin 
264c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
265c209e3e2SJohn Baldwin 	close(cpipe[0]);
266c209e3e2SJohn Baldwin 
267c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
268c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
269*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
270c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
271*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
272c209e3e2SJohn Baldwin 
273c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
274c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
275*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
276*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
277c209e3e2SJohn Baldwin }
278c209e3e2SJohn Baldwin 
27957c74f5bSJohn Baldwin /*
28057c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
28157c74f5bSJohn Baldwin  * after the debugger has seen it.
28257c74f5bSJohn Baldwin  */
28357c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
28457c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
28557c74f5bSJohn Baldwin {
28657c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
28757c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
28857c74f5bSJohn Baldwin 	char c;
28957c74f5bSJohn Baldwin 
29084922a5dSLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
291c2dc497aSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/239399");
292c2dc497aSLi-Wen Hsu 
293*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
29457c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
29557c74f5bSJohn Baldwin 
29657c74f5bSJohn Baldwin 	if (child == 0) {
29757c74f5bSJohn Baldwin 		/* Child process. */
29857c74f5bSJohn Baldwin 		close(cpipe[0]);
29957c74f5bSJohn Baldwin 
30057c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
301*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)), sizeof(c));
30257c74f5bSJohn Baldwin 
303b98cb919SJohn Baldwin 		_exit(1);
30457c74f5bSJohn Baldwin 	}
30557c74f5bSJohn Baldwin 	close(cpipe[1]);
30657c74f5bSJohn Baldwin 
307*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
30857c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
30957c74f5bSJohn Baldwin 
31057c74f5bSJohn Baldwin 	if (debugger == 0) {
31157c74f5bSJohn Baldwin 		/* Debugger process. */
31257c74f5bSJohn Baldwin 		close(dpipe[0]);
31357c74f5bSJohn Baldwin 
314dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
31557c74f5bSJohn Baldwin 
31657c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
317*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
318dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
319*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
32057c74f5bSJohn Baldwin 
321dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
32257c74f5bSJohn Baldwin 
32357c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
324*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)), sizeof(c));
32557c74f5bSJohn Baldwin 
32657c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
327*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(read(dpipe[1], &c, sizeof(c)), 0);
32857c74f5bSJohn Baldwin 
32957c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
330*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
331dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
332*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
33357c74f5bSJohn Baldwin 
334b98cb919SJohn Baldwin 		_exit(0);
33557c74f5bSJohn Baldwin 	}
33657c74f5bSJohn Baldwin 	close(dpipe[1]);
33757c74f5bSJohn Baldwin 
33857c74f5bSJohn Baldwin 	/* Parent process. */
33957c74f5bSJohn Baldwin 
34057c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
341*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), sizeof(c));
34257c74f5bSJohn Baldwin 
34357c74f5bSJohn Baldwin 	/* Release the child. */
344*96a9e50eSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), sizeof(c));
345*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &c, sizeof(c)), 0);
34657c74f5bSJohn Baldwin 	close(cpipe[0]);
34757c74f5bSJohn Baldwin 
34898685dc8SJohn Baldwin 	wait_for_zombie(child);
34957c74f5bSJohn Baldwin 
35057c74f5bSJohn Baldwin 	/*
3512f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3522f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3532f021998SJohn Baldwin 	 * until the debugger sees the exit.
35457c74f5bSJohn Baldwin 	 */
35557c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
356*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
35757c74f5bSJohn Baldwin 
35857c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
35957c74f5bSJohn Baldwin 	close(dpipe[0]);
36057c74f5bSJohn Baldwin 
36157c74f5bSJohn Baldwin 	/* Wait for the debugger. */
36257c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
363*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
36457c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
365*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
36657c74f5bSJohn Baldwin 
36757c74f5bSJohn Baldwin 	/* The child process should now be ready. */
36857c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
369*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
37057c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
371*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
37257c74f5bSJohn Baldwin }
37357c74f5bSJohn Baldwin 
37457c74f5bSJohn Baldwin /*
37557c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
37657c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
37757c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
37857c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
37957c74f5bSJohn Baldwin  */
38057c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
38157c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
38257c74f5bSJohn Baldwin {
38357c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
38457c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
38557c74f5bSJohn Baldwin 	char c;
38657c74f5bSJohn Baldwin 
387*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
38857c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
38957c74f5bSJohn Baldwin 
39057c74f5bSJohn Baldwin 	if (child == 0) {
39157c74f5bSJohn Baldwin 		/* Child process. */
39257c74f5bSJohn Baldwin 		close(cpipe[0]);
39357c74f5bSJohn Baldwin 
39457c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
395*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)), sizeof(c));
39657c74f5bSJohn Baldwin 
397b98cb919SJohn Baldwin 		_exit(1);
39857c74f5bSJohn Baldwin 	}
39957c74f5bSJohn Baldwin 	close(cpipe[1]);
40057c74f5bSJohn Baldwin 
401*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
40257c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
40357c74f5bSJohn Baldwin 
40457c74f5bSJohn Baldwin 	if (debugger == 0) {
40557c74f5bSJohn Baldwin 		/* Debugger parent. */
40657c74f5bSJohn Baldwin 
40757c74f5bSJohn Baldwin 		/*
40857c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
40957c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
41057c74f5bSJohn Baldwin 		 */
411dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
41257c74f5bSJohn Baldwin 		if (fpid != 0)
413b98cb919SJohn Baldwin 			_exit(2);
41457c74f5bSJohn Baldwin 
41557c74f5bSJohn Baldwin 		/* Debugger process. */
41657c74f5bSJohn Baldwin 		close(dpipe[0]);
41757c74f5bSJohn Baldwin 
418dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
41957c74f5bSJohn Baldwin 
42057c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
421*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
422dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
423*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42457c74f5bSJohn Baldwin 
425dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
42657c74f5bSJohn Baldwin 
42757c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
428*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)), sizeof(c));
42957c74f5bSJohn Baldwin 
43057c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
431*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(read(dpipe[1], &c, sizeof(c)), sizeof(c));
43257c74f5bSJohn Baldwin 
43357c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
434*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
435dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
436*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
43757c74f5bSJohn Baldwin 
438b98cb919SJohn Baldwin 		_exit(0);
43957c74f5bSJohn Baldwin 	}
440eddb85c6SJohn Baldwin 	close(dpipe[1]);
44157c74f5bSJohn Baldwin 
44257c74f5bSJohn Baldwin 	/* Parent process. */
44357c74f5bSJohn Baldwin 
44457c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
44557c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
446*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
44757c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
448*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
44957c74f5bSJohn Baldwin 
45057c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
45157c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
452*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
45357c74f5bSJohn Baldwin 
45457c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
455*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), sizeof(c));
45657c74f5bSJohn Baldwin 
45757c74f5bSJohn Baldwin 	/* Release the child. */
458*96a9e50eSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), sizeof(c));
459*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &c, sizeof(c)), 0);
46057c74f5bSJohn Baldwin 	close(cpipe[0]);
46157c74f5bSJohn Baldwin 
46298685dc8SJohn Baldwin 	wait_for_zombie(child);
46357c74f5bSJohn Baldwin 
46457c74f5bSJohn Baldwin 	/*
4652f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
4662f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
4672f021998SJohn Baldwin 	 * until the debugger sees the exit.
46857c74f5bSJohn Baldwin 	 */
46957c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
470*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
47157c74f5bSJohn Baldwin 
47257c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
473*96a9e50eSAlex Richardson 	REQUIRE_EQ(write(dpipe[0], &c, sizeof(c)), sizeof(c));
47457c74f5bSJohn Baldwin 
47557c74f5bSJohn Baldwin 	/* Wait for the debugger. */
476*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), 0);
477eddb85c6SJohn Baldwin 	close(dpipe[0]);
47857c74f5bSJohn Baldwin 
47957c74f5bSJohn Baldwin 	/* The child process should now be ready. */
48057c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
481*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
48257c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
483*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
48457c74f5bSJohn Baldwin }
48557c74f5bSJohn Baldwin 
48698685dc8SJohn Baldwin /*
487128c9bc0SMark Johnston  * Make sure that we can collect the exit status of an orphaned process.
488128c9bc0SMark Johnston  */
489128c9bc0SMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
490128c9bc0SMark Johnston ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
491128c9bc0SMark Johnston {
492128c9bc0SMark Johnston 	ssize_t n;
493128c9bc0SMark Johnston 	int cpipe1[2], cpipe2[2], gcpipe[2], status;
494128c9bc0SMark Johnston 	pid_t child, gchild;
495128c9bc0SMark Johnston 
496519aaa15SLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
497519aaa15SLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/244056");
498519aaa15SLi-Wen Hsu 
499*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe1), 0);
500*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe2), 0);
501*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(gcpipe), 0);
502128c9bc0SMark Johnston 
503*96a9e50eSAlex Richardson 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
504128c9bc0SMark Johnston 
505128c9bc0SMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
506128c9bc0SMark Johnston 	if (child == 0) {
507128c9bc0SMark Johnston 		CHILD_REQUIRE((gchild = fork()) != -1);
508128c9bc0SMark Johnston 		if (gchild == 0) {
509128c9bc0SMark Johnston 			status = 1;
510128c9bc0SMark Johnston 			do {
511128c9bc0SMark Johnston 				n = read(gcpipe[0], &status, sizeof(status));
512128c9bc0SMark Johnston 			} while (n == -1 && errno == EINTR);
513128c9bc0SMark Johnston 			_exit(status);
514128c9bc0SMark Johnston 		}
515128c9bc0SMark Johnston 
516128c9bc0SMark Johnston 		CHILD_REQUIRE(write(cpipe1[1], &gchild, sizeof(gchild)) ==
517128c9bc0SMark Johnston 		    sizeof(gchild));
518128c9bc0SMark Johnston 		CHILD_REQUIRE(read(cpipe2[0], &status, sizeof(status)) ==
519128c9bc0SMark Johnston 		    sizeof(status));
520128c9bc0SMark Johnston 		_exit(status);
521128c9bc0SMark Johnston 	}
522128c9bc0SMark Johnston 
523*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe1[0], &gchild, sizeof(gchild)), sizeof(gchild));
524128c9bc0SMark Johnston 
525*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, gchild, NULL, 0), 0);
526128c9bc0SMark Johnston 
527128c9bc0SMark Johnston 	status = 0;
528*96a9e50eSAlex Richardson 	REQUIRE_EQ(write(cpipe2[1], &status, sizeof(status)), sizeof(status));
529*96a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(child, &status, 0), child);
530*96a9e50eSAlex Richardson 	ATF_REQUIRE(WIFEXITED(status));
531*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
532128c9bc0SMark Johnston 
533128c9bc0SMark Johnston 	status = 0;
534*96a9e50eSAlex Richardson 	REQUIRE_EQ(write(gcpipe[1], &status, sizeof(status)), sizeof(status));
535*96a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(gchild, &status, 0), gchild);
536128c9bc0SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
537*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_DETACH, gchild, (caddr_t)1, 0), 0);
538*96a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(gchild, &status, 0), gchild);
539*96a9e50eSAlex Richardson 	ATF_REQUIRE(WIFEXITED(status));
540*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
541128c9bc0SMark Johnston 
542*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe1[0]), 0);
543*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe1[1]), 0);
544*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe2[0]), 0);
545*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe2[1]), 0);
546*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(gcpipe[0]), 0);
547*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(gcpipe[1]), 0);
548128c9bc0SMark Johnston }
549128c9bc0SMark Johnston 
550128c9bc0SMark Johnston /*
55198685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
55298685dc8SJohn Baldwin  * debugger is attached to it.
55398685dc8SJohn Baldwin  */
55498685dc8SJohn Baldwin static __dead2 void
555189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
55698685dc8SJohn Baldwin {
55798685dc8SJohn Baldwin 	pid_t fpid, wpid;
55898685dc8SJohn Baldwin 	int status;
55998685dc8SJohn Baldwin 
560189ac973SJohn Baldwin 	if (use_vfork)
561189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
562189ac973SJohn Baldwin 	else
56398685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
56498685dc8SJohn Baldwin 
56598685dc8SJohn Baldwin 	if (fpid == 0)
56698685dc8SJohn Baldwin 		/* Child */
567b98cb919SJohn Baldwin 		_exit(2);
56898685dc8SJohn Baldwin 
56998685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
570*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(wpid, fpid);
57198685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
572*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(WEXITSTATUS(status), 2);
57398685dc8SJohn Baldwin 
574b98cb919SJohn Baldwin 	_exit(1);
57598685dc8SJohn Baldwin }
57698685dc8SJohn Baldwin 
57798685dc8SJohn Baldwin /*
57898685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
57998685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
58098685dc8SJohn Baldwin  * child process.
58198685dc8SJohn Baldwin  */
58298685dc8SJohn Baldwin static pid_t
583189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
58498685dc8SJohn Baldwin {
58598685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
58698685dc8SJohn Baldwin 	bool fork_reported[2];
58798685dc8SJohn Baldwin 	pid_t child, wpid;
58898685dc8SJohn Baldwin 	int i, status;
58998685dc8SJohn Baldwin 
59098685dc8SJohn Baldwin 	fork_reported[0] = false;
59198685dc8SJohn Baldwin 	fork_reported[1] = false;
59298685dc8SJohn Baldwin 	child = -1;
59398685dc8SJohn Baldwin 
59498685dc8SJohn Baldwin 	/*
59598685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
59698685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
59798685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
59898685dc8SJohn Baldwin 	 */
59998685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
60098685dc8SJohn Baldwin 		wpid = wait(&status);
60198685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
60298685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
60398685dc8SJohn Baldwin 
60498685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
60598685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
60698685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
60798685dc8SJohn Baldwin 		    0);
60898685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
60998685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
61098685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
61198685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
612*96a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
61398685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
61498685dc8SJohn Baldwin 			if (child == -1)
61598685dc8SJohn Baldwin 				child = wpid;
61698685dc8SJohn Baldwin 			else
617*96a9e50eSAlex Richardson 				REQUIRE_EQ(child, wpid);
618189ac973SJohn Baldwin 			if (ppl != NULL)
619189ac973SJohn Baldwin 				ppl[1] = pl;
62098685dc8SJohn Baldwin 			fork_reported[1] = true;
62198685dc8SJohn Baldwin 		} else {
622*96a9e50eSAlex Richardson 			REQUIRE_EQ(wpid, parent);
623*96a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
62498685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
62598685dc8SJohn Baldwin 			if (child == -1)
62698685dc8SJohn Baldwin 				child = pl.pl_child_pid;
62798685dc8SJohn Baldwin 			else
628*96a9e50eSAlex Richardson 				REQUIRE_EQ(child, pl.pl_child_pid);
629189ac973SJohn Baldwin 			if (ppl != NULL)
630189ac973SJohn Baldwin 				ppl[0] = pl;
63198685dc8SJohn Baldwin 			fork_reported[0] = true;
63298685dc8SJohn Baldwin 		}
63398685dc8SJohn Baldwin 	}
63498685dc8SJohn Baldwin 
63598685dc8SJohn Baldwin 	return (child);
63698685dc8SJohn Baldwin }
63798685dc8SJohn Baldwin 
63898685dc8SJohn Baldwin /*
63998685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
64098685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
64198685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
64298685dc8SJohn Baldwin  */
64398685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
64498685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
64598685dc8SJohn Baldwin {
646479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
64798685dc8SJohn Baldwin 	int status;
64898685dc8SJohn Baldwin 
64998685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
65098685dc8SJohn Baldwin 	if (fpid == 0) {
65198685dc8SJohn Baldwin 		trace_me();
652189ac973SJohn Baldwin 		follow_fork_parent(false);
65398685dc8SJohn Baldwin 	}
65498685dc8SJohn Baldwin 
65598685dc8SJohn Baldwin 	/* Parent process. */
65698685dc8SJohn Baldwin 	children[0] = fpid;
65798685dc8SJohn Baldwin 
65898685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
65998685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
660*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
66198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
662*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
66398685dc8SJohn Baldwin 
66498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
66598685dc8SJohn Baldwin 
66698685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
66798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
66898685dc8SJohn Baldwin 
669189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
67098685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
67198685dc8SJohn Baldwin 
67298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
67398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
67498685dc8SJohn Baldwin 
67598685dc8SJohn Baldwin 	/*
67698685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
67798685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
67898685dc8SJohn Baldwin 	 */
67998685dc8SJohn Baldwin 	wpid = wait(&status);
680*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
68198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
682*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
68398685dc8SJohn Baldwin 
68498685dc8SJohn Baldwin 	wpid = wait(&status);
685*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
68698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
687*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
68898685dc8SJohn Baldwin 
68998685dc8SJohn Baldwin 	wpid = wait(&status);
690*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
691*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
69298685dc8SJohn Baldwin }
69398685dc8SJohn Baldwin 
69498685dc8SJohn Baldwin /*
69598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
69698685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
69798685dc8SJohn Baldwin  * child process is detached after it reports its fork.
69898685dc8SJohn Baldwin  */
69998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
70098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
70198685dc8SJohn Baldwin {
702479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
70398685dc8SJohn Baldwin 	int status;
70498685dc8SJohn Baldwin 
70598685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
70698685dc8SJohn Baldwin 	if (fpid == 0) {
70798685dc8SJohn Baldwin 		trace_me();
708189ac973SJohn Baldwin 		follow_fork_parent(false);
70998685dc8SJohn Baldwin 	}
71098685dc8SJohn Baldwin 
71198685dc8SJohn Baldwin 	/* Parent process. */
71298685dc8SJohn Baldwin 	children[0] = fpid;
71398685dc8SJohn Baldwin 
71498685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
71598685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
716*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
71798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
718*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
71998685dc8SJohn Baldwin 
72098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
72198685dc8SJohn Baldwin 
72298685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
72398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
72498685dc8SJohn Baldwin 
725189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
72698685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
72798685dc8SJohn Baldwin 
72898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
72998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
73098685dc8SJohn Baldwin 
73198685dc8SJohn Baldwin 	/*
73298685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
73398685dc8SJohn Baldwin 	 * child.
73498685dc8SJohn Baldwin 	 */
73598685dc8SJohn Baldwin 	wpid = wait(&status);
736*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
73798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
738*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
73998685dc8SJohn Baldwin 
74098685dc8SJohn Baldwin 	wpid = wait(&status);
741*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
742*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
74398685dc8SJohn Baldwin }
74498685dc8SJohn Baldwin 
74598685dc8SJohn Baldwin /*
74698685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
74798685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
74898685dc8SJohn Baldwin  * traced parent is detached after the fork.
74998685dc8SJohn Baldwin  */
75098685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
75198685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
75298685dc8SJohn Baldwin {
753479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
75498685dc8SJohn Baldwin 	int status;
75598685dc8SJohn Baldwin 
75698685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
75798685dc8SJohn Baldwin 	if (fpid == 0) {
75898685dc8SJohn Baldwin 		trace_me();
759189ac973SJohn Baldwin 		follow_fork_parent(false);
76098685dc8SJohn Baldwin 	}
76198685dc8SJohn Baldwin 
76298685dc8SJohn Baldwin 	/* Parent process. */
76398685dc8SJohn Baldwin 	children[0] = fpid;
76498685dc8SJohn Baldwin 
76598685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
76698685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
767*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
76898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
769*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
77098685dc8SJohn Baldwin 
77198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
77298685dc8SJohn Baldwin 
77398685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
77498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
77598685dc8SJohn Baldwin 
776189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
77798685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
77898685dc8SJohn Baldwin 
77998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
78098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
78198685dc8SJohn Baldwin 
78298685dc8SJohn Baldwin 	/*
78398685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
78498685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
78598685dc8SJohn Baldwin 	 *
78698685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
78798685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
78898685dc8SJohn Baldwin 	 * after the grandchild.
78998685dc8SJohn Baldwin 	 */
79098685dc8SJohn Baldwin 	wpid = wait(&status);
791*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
79298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
793*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
79498685dc8SJohn Baldwin 
79598685dc8SJohn Baldwin 	wpid = wait(&status);
796*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
79798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
798*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
79998685dc8SJohn Baldwin 
80098685dc8SJohn Baldwin 	wpid = wait(&status);
801*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
802*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
80398685dc8SJohn Baldwin }
80498685dc8SJohn Baldwin 
80598685dc8SJohn Baldwin static void
80698685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
80798685dc8SJohn Baldwin {
80898685dc8SJohn Baldwin 	pid_t fpid;
80998685dc8SJohn Baldwin 
81098685dc8SJohn Baldwin 	close(cpipe[0]);
81198685dc8SJohn Baldwin 
81298685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
81398685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
81498685dc8SJohn Baldwin 	if (fpid != 0)
815b98cb919SJohn Baldwin 		_exit(3);
81698685dc8SJohn Baldwin 
81798685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
81898685dc8SJohn Baldwin 	fpid = getpid();
819*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(write(cpipe[1], &fpid, sizeof(fpid)), sizeof(fpid));
82098685dc8SJohn Baldwin 
82198685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
822*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(read(cpipe[1], &fpid, sizeof(fpid)), 0);
82398685dc8SJohn Baldwin }
82498685dc8SJohn Baldwin 
82598685dc8SJohn Baldwin /*
82698685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
82798685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
82898685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
82998685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
83098685dc8SJohn Baldwin  */
83198685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
83298685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
83398685dc8SJohn Baldwin {
834479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
83598685dc8SJohn Baldwin 	int cpipe[2], status;
83698685dc8SJohn Baldwin 
83784922a5dSLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
838ea24861dSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/239397");
839ea24861dSLi-Wen Hsu 
840*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
84198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
84298685dc8SJohn Baldwin 	if (fpid == 0) {
84398685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
844189ac973SJohn Baldwin 		follow_fork_parent(false);
84598685dc8SJohn Baldwin 	}
84698685dc8SJohn Baldwin 
84798685dc8SJohn Baldwin 	/* Parent process. */
84898685dc8SJohn Baldwin 	close(cpipe[1]);
84998685dc8SJohn Baldwin 
85098685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
85198685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
852*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
85398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
854*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
85598685dc8SJohn Baldwin 
85698685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
857*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
85898685dc8SJohn Baldwin 	    sizeof(children[0]));
85998685dc8SJohn Baldwin 
86098685dc8SJohn Baldwin 	/* Attach to the fork parent. */
86198685dc8SJohn Baldwin 	attach_child(children[0]);
86298685dc8SJohn Baldwin 
86398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
86498685dc8SJohn Baldwin 
86598685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
86698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
86798685dc8SJohn Baldwin 
86898685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
86998685dc8SJohn Baldwin 	close(cpipe[0]);
87098685dc8SJohn Baldwin 
871189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
87298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
87398685dc8SJohn Baldwin 
87498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
87598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
87698685dc8SJohn Baldwin 
87798685dc8SJohn Baldwin 	/*
87898685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
87998685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
88098685dc8SJohn Baldwin 	 */
88198685dc8SJohn Baldwin 	wpid = wait(&status);
882*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
88398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
884*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
88598685dc8SJohn Baldwin 
88698685dc8SJohn Baldwin 	wpid = wait(&status);
887*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
88898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
889*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
89098685dc8SJohn Baldwin 
89198685dc8SJohn Baldwin 	wpid = wait(&status);
892*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
893*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
89498685dc8SJohn Baldwin }
89598685dc8SJohn Baldwin 
89698685dc8SJohn Baldwin /*
89798685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
89898685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
89998685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
90098685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
90198685dc8SJohn Baldwin  */
90298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
90398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
90498685dc8SJohn Baldwin {
905479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
90698685dc8SJohn Baldwin 	int cpipe[2], status;
90798685dc8SJohn Baldwin 
90884922a5dSLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
90963b0609cSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/239292");
91037ba9b34SLi-Wen Hsu 
911*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
91298685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
91398685dc8SJohn Baldwin 	if (fpid == 0) {
91498685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
915189ac973SJohn Baldwin 		follow_fork_parent(false);
91698685dc8SJohn Baldwin 	}
91798685dc8SJohn Baldwin 
91898685dc8SJohn Baldwin 	/* Parent process. */
91998685dc8SJohn Baldwin 	close(cpipe[1]);
92098685dc8SJohn Baldwin 
92198685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
92298685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
923*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
92498685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
925*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
92698685dc8SJohn Baldwin 
92798685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
928*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
92998685dc8SJohn Baldwin 	    sizeof(children[0]));
93098685dc8SJohn Baldwin 
93198685dc8SJohn Baldwin 	/* Attach to the fork parent. */
93298685dc8SJohn Baldwin 	attach_child(children[0]);
93398685dc8SJohn Baldwin 
93498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
93598685dc8SJohn Baldwin 
93698685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
93798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
93898685dc8SJohn Baldwin 
93998685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
94098685dc8SJohn Baldwin 	close(cpipe[0]);
94198685dc8SJohn Baldwin 
942189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
94398685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
94498685dc8SJohn Baldwin 
94598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
94698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
94798685dc8SJohn Baldwin 
94898685dc8SJohn Baldwin 	/*
94998685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
95098685dc8SJohn Baldwin 	 * parent.
95198685dc8SJohn Baldwin 	 */
95298685dc8SJohn Baldwin 	wpid = wait(&status);
953*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
95498685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
955*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
95698685dc8SJohn Baldwin 
95798685dc8SJohn Baldwin 	wpid = wait(&status);
958*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
959*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
96098685dc8SJohn Baldwin }
96198685dc8SJohn Baldwin 
96298685dc8SJohn Baldwin /*
96398685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
96498685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
96598685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
96698685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
96798685dc8SJohn Baldwin  */
96898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
96998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
97098685dc8SJohn Baldwin {
971479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
97298685dc8SJohn Baldwin 	int cpipe[2], status;
97398685dc8SJohn Baldwin 
97484922a5dSLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
9751ab93d1fSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/239425");
9761ab93d1fSLi-Wen Hsu 
977*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
97898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
97998685dc8SJohn Baldwin 	if (fpid == 0) {
98098685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
981189ac973SJohn Baldwin 		follow_fork_parent(false);
98298685dc8SJohn Baldwin 	}
98398685dc8SJohn Baldwin 
98498685dc8SJohn Baldwin 	/* Parent process. */
98598685dc8SJohn Baldwin 	close(cpipe[1]);
98698685dc8SJohn Baldwin 
98798685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
98898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
989*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
99098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
991*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
99298685dc8SJohn Baldwin 
99398685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
994*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
99598685dc8SJohn Baldwin 	    sizeof(children[0]));
99698685dc8SJohn Baldwin 
99798685dc8SJohn Baldwin 	/* Attach to the fork parent. */
99898685dc8SJohn Baldwin 	attach_child(children[0]);
99998685dc8SJohn Baldwin 
100098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
100198685dc8SJohn Baldwin 
100298685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
100398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
100498685dc8SJohn Baldwin 
100598685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
100698685dc8SJohn Baldwin 	close(cpipe[0]);
100798685dc8SJohn Baldwin 
1008189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
100998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
101098685dc8SJohn Baldwin 
101198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
101298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
101398685dc8SJohn Baldwin 
101498685dc8SJohn Baldwin 	/*
101598685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
101698685dc8SJohn Baldwin 	 * the child.
101798685dc8SJohn Baldwin 	 */
101898685dc8SJohn Baldwin 	wpid = wait(&status);
1019*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
102098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1021*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
102298685dc8SJohn Baldwin 
102398685dc8SJohn Baldwin 	wpid = wait(&status);
1024*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1025*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
102698685dc8SJohn Baldwin }
102798685dc8SJohn Baldwin 
1028368b2b1cSJohn Baldwin /*
1029368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
1030368b2b1cSJohn Baldwin  * parent but sees its original parent process.
1031368b2b1cSJohn Baldwin  */
1032368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
1033368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
1034368b2b1cSJohn Baldwin {
1035368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
1036368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
1037368b2b1cSJohn Baldwin 	char c;
1038368b2b1cSJohn Baldwin 
103931e3dc2dSLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
104031e3dc2dSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/240510");
104131e3dc2dSLi-Wen Hsu 
1042*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
1043368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
1044368b2b1cSJohn Baldwin 
1045368b2b1cSJohn Baldwin 	if (child == 0) {
1046368b2b1cSJohn Baldwin 		/* Child process. */
1047368b2b1cSJohn Baldwin 		close(cpipe[0]);
1048368b2b1cSJohn Baldwin 
1049368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
1050*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)), sizeof(c));
1051368b2b1cSJohn Baldwin 
1052368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
1053368b2b1cSJohn Baldwin 		ppid = getppid();
1054368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) ==
1055368b2b1cSJohn Baldwin 		    sizeof(ppid));
1056368b2b1cSJohn Baldwin 
1057368b2b1cSJohn Baldwin 		_exit(1);
1058368b2b1cSJohn Baldwin 	}
1059368b2b1cSJohn Baldwin 	close(cpipe[1]);
1060368b2b1cSJohn Baldwin 
1061*96a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
1062368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
1063368b2b1cSJohn Baldwin 
1064368b2b1cSJohn Baldwin 	if (debugger == 0) {
1065368b2b1cSJohn Baldwin 		/* Debugger process. */
1066368b2b1cSJohn Baldwin 		close(dpipe[0]);
1067368b2b1cSJohn Baldwin 
1068368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
1069368b2b1cSJohn Baldwin 
1070368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
1071*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
1072368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
1073*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1074368b2b1cSJohn Baldwin 
1075368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
1076368b2b1cSJohn Baldwin 
1077368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
1078*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)), sizeof(c));
1079368b2b1cSJohn Baldwin 
1080368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
1081368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
1082*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
1083368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
1084*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
1085368b2b1cSJohn Baldwin 
1086368b2b1cSJohn Baldwin 		_exit(0);
1087368b2b1cSJohn Baldwin 	}
1088368b2b1cSJohn Baldwin 	close(dpipe[1]);
1089368b2b1cSJohn Baldwin 
1090368b2b1cSJohn Baldwin 	/* Parent process. */
1091368b2b1cSJohn Baldwin 
1092368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
1093*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), sizeof(c));
1094368b2b1cSJohn Baldwin 
1095368b2b1cSJohn Baldwin 	/* Release the child. */
1096*96a9e50eSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), sizeof(c));
1097368b2b1cSJohn Baldwin 
1098368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
1099*96a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &ppid, sizeof(ppid)), sizeof(ppid));
1100368b2b1cSJohn Baldwin 	close(cpipe[0]);
1101368b2b1cSJohn Baldwin 
1102*96a9e50eSAlex Richardson 	REQUIRE_EQ(ppid, getpid());
1103368b2b1cSJohn Baldwin 
1104368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
1105368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
1106*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
1107368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1108*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
1109368b2b1cSJohn Baldwin 
1110368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
1111368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
1112*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
1113368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1114*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1115368b2b1cSJohn Baldwin }
1116368b2b1cSJohn Baldwin 
1117189ac973SJohn Baldwin /*
1118189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1119189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
1120189ac973SJohn Baldwin  */
1121189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
1122189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
1123189ac973SJohn Baldwin {
1124189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1125189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1126189ac973SJohn Baldwin 	int status;
1127189ac973SJohn Baldwin 
1128189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1129189ac973SJohn Baldwin 	if (fpid == 0) {
1130189ac973SJohn Baldwin 		trace_me();
1131189ac973SJohn Baldwin 		follow_fork_parent(false);
1132189ac973SJohn Baldwin 	}
1133189ac973SJohn Baldwin 
1134189ac973SJohn Baldwin 	/* Parent process. */
1135189ac973SJohn Baldwin 	children[0] = fpid;
1136189ac973SJohn Baldwin 
1137189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1138189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1139*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1140189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1141*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1142189ac973SJohn Baldwin 
1143189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1144189ac973SJohn Baldwin 
1145189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1146189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1147189ac973SJohn Baldwin 
1148189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1149189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1150189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1151189ac973SJohn Baldwin 
1152189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1153189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1154*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, SYS_fork);
1155*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, pl[1].pl_syscall_code);
1156*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_narg, pl[1].pl_syscall_narg);
1157189ac973SJohn Baldwin 
1158189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1159189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1160189ac973SJohn Baldwin 
1161189ac973SJohn Baldwin 	/*
1162189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1163189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1164189ac973SJohn Baldwin 	 */
1165189ac973SJohn Baldwin 	wpid = wait(&status);
1166*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1167189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1168*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1169189ac973SJohn Baldwin 
1170189ac973SJohn Baldwin 	wpid = wait(&status);
1171*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1172189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1173*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1174189ac973SJohn Baldwin 
1175189ac973SJohn Baldwin 	wpid = wait(&status);
1176*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1177*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1178189ac973SJohn Baldwin }
1179189ac973SJohn Baldwin 
1180189ac973SJohn Baldwin /*
1181189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1182189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1183189ac973SJohn Baldwin  */
1184189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1185189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1186189ac973SJohn Baldwin {
1187189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1188189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1189189ac973SJohn Baldwin 	int status;
1190189ac973SJohn Baldwin 
1191189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1192189ac973SJohn Baldwin 	if (fpid == 0) {
1193189ac973SJohn Baldwin 		trace_me();
1194189ac973SJohn Baldwin 		follow_fork_parent(true);
1195189ac973SJohn Baldwin 	}
1196189ac973SJohn Baldwin 
1197189ac973SJohn Baldwin 	/* Parent process. */
1198189ac973SJohn Baldwin 	children[0] = fpid;
1199189ac973SJohn Baldwin 
1200189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1201189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1202*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1203189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1204*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1205189ac973SJohn Baldwin 
1206189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1207189ac973SJohn Baldwin 
1208189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1209189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1210189ac973SJohn Baldwin 
1211189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1212189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1213189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1214189ac973SJohn Baldwin 
1215189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1216189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1217*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, SYS_vfork);
1218*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, pl[1].pl_syscall_code);
1219*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_narg, pl[1].pl_syscall_narg);
1220189ac973SJohn Baldwin 
1221189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1222189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1223189ac973SJohn Baldwin 
1224189ac973SJohn Baldwin 	/*
1225189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1226189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1227189ac973SJohn Baldwin 	 */
1228189ac973SJohn Baldwin 	wpid = wait(&status);
1229*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1230189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1231*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1232189ac973SJohn Baldwin 
1233189ac973SJohn Baldwin 	wpid = wait(&status);
1234*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1235189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1236*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1237189ac973SJohn Baldwin 
1238189ac973SJohn Baldwin 	wpid = wait(&status);
1239*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1240*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1241189ac973SJohn Baldwin }
1242189ac973SJohn Baldwin 
1243189ac973SJohn Baldwin static void *
1244189ac973SJohn Baldwin simple_thread(void *arg __unused)
1245189ac973SJohn Baldwin {
1246189ac973SJohn Baldwin 
1247189ac973SJohn Baldwin 	pthread_exit(NULL);
1248189ac973SJohn Baldwin }
1249189ac973SJohn Baldwin 
12505fcfab6eSJohn Baldwin static __dead2 void
12515fcfab6eSJohn Baldwin simple_thread_main(void)
12525fcfab6eSJohn Baldwin {
12535fcfab6eSJohn Baldwin 	pthread_t thread;
12545fcfab6eSJohn Baldwin 
1255*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_create(&thread, NULL, simple_thread, NULL), 0);
1256*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(thread, NULL), 0);
12575fcfab6eSJohn Baldwin 	exit(1);
12585fcfab6eSJohn Baldwin }
12595fcfab6eSJohn Baldwin 
1260189ac973SJohn Baldwin /*
1261189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1262189ac973SJohn Baldwin  * thread reports the correct value.
1263189ac973SJohn Baldwin  */
1264189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1265189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1266189ac973SJohn Baldwin {
1267189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1268189ac973SJohn Baldwin 	pid_t fpid, wpid;
1269e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1270189ac973SJohn Baldwin 	int status;
1271189ac973SJohn Baldwin 
1272189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1273189ac973SJohn Baldwin 	if (fpid == 0) {
1274189ac973SJohn Baldwin 		trace_me();
12755fcfab6eSJohn Baldwin 		simple_thread_main();
1276189ac973SJohn Baldwin 	}
1277189ac973SJohn Baldwin 
1278189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1279189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1280*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1281189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1282*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1283189ac973SJohn Baldwin 
1284189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1285189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1286e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1287189ac973SJohn Baldwin 
1288189ac973SJohn Baldwin 	/*
1289189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1290189ac973SJohn Baldwin 	 * system call exits.
1291189ac973SJohn Baldwin 	 */
1292189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1293189ac973SJohn Baldwin 
1294189ac973SJohn Baldwin 	/*
1295189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1296189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1297189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1298189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1299189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1300189ac973SJohn Baldwin 	 */
1301189ac973SJohn Baldwin 	for (;;) {
1302189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1303*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
1304189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1305*96a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1306189ac973SJohn Baldwin 
1307189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1308189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1309189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1310189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1311e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1312189ac973SJohn Baldwin 			/* New thread seen. */
1313189ac973SJohn Baldwin 			break;
1314189ac973SJohn Baldwin 
1315*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1316189ac973SJohn Baldwin 	}
1317189ac973SJohn Baldwin 
1318189ac973SJohn Baldwin 	/* Wait for the child to exit. */
1319*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1320189ac973SJohn Baldwin 	for (;;) {
1321189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1322*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
1323189ac973SJohn Baldwin 		if (WIFEXITED(status))
1324189ac973SJohn Baldwin 			break;
1325189ac973SJohn Baldwin 
1326189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1327*96a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1328*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1329189ac973SJohn Baldwin 	}
1330189ac973SJohn Baldwin 
1331*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1332189ac973SJohn Baldwin 
1333189ac973SJohn Baldwin 	wpid = wait(&status);
1334*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1335*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1336189ac973SJohn Baldwin }
1337189ac973SJohn Baldwin 
13385fcfab6eSJohn Baldwin /*
13395fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
13405fcfab6eSJohn Baldwin  */
13415fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
13425fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
13435fcfab6eSJohn Baldwin {
13445fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
13455fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
13465fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
13475fcfab6eSJohn Baldwin 	int status;
13485fcfab6eSJohn Baldwin 
13495fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13505fcfab6eSJohn Baldwin 	if (fpid == 0) {
13515fcfab6eSJohn Baldwin 		trace_me();
13525fcfab6eSJohn Baldwin 		simple_thread_main();
13535fcfab6eSJohn Baldwin 	}
13545fcfab6eSJohn Baldwin 
13555fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13565fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1357*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13585fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1359*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
13605fcfab6eSJohn Baldwin 
13615fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13625fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13635fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13645fcfab6eSJohn Baldwin 
1365*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
13665fcfab6eSJohn Baldwin 
13675fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1368*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13695fcfab6eSJohn Baldwin 
13705fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13715fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1372*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13735fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1374*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
13755fcfab6eSJohn Baldwin 
13765fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1377*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
13785fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13795fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13805fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13815fcfab6eSJohn Baldwin 
1382*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13835fcfab6eSJohn Baldwin 
13845fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
13855fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1386*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13875fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1388*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
13895fcfab6eSJohn Baldwin 
13905fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1391*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)),
13925fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
1393*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[1]);
13945fcfab6eSJohn Baldwin 
1395*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13965fcfab6eSJohn Baldwin 
13975fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13985fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13995fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1400*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
14015fcfab6eSJohn Baldwin 
14025fcfab6eSJohn Baldwin 	wpid = wait(&status);
1403*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1404*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
14055fcfab6eSJohn Baldwin }
14065fcfab6eSJohn Baldwin 
14075fcfab6eSJohn Baldwin static void *
14085fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
14095fcfab6eSJohn Baldwin {
14105fcfab6eSJohn Baldwin 
14115fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
14125fcfab6eSJohn Baldwin 	exit(127);
14135fcfab6eSJohn Baldwin }
14145fcfab6eSJohn Baldwin 
14155fcfab6eSJohn Baldwin static __dead2 void
14165fcfab6eSJohn Baldwin exec_thread_main(void)
14175fcfab6eSJohn Baldwin {
14185fcfab6eSJohn Baldwin 	pthread_t thread;
14195fcfab6eSJohn Baldwin 
1420*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_create(&thread, NULL, exec_thread, NULL), 0);
14215fcfab6eSJohn Baldwin 	for (;;)
14225fcfab6eSJohn Baldwin 		sleep(60);
14235fcfab6eSJohn Baldwin 	exit(1);
14245fcfab6eSJohn Baldwin }
14255fcfab6eSJohn Baldwin 
14265fcfab6eSJohn Baldwin /*
14275fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
14285fcfab6eSJohn Baldwin  * process that calls execve(2).
14295fcfab6eSJohn Baldwin  */
14305fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
14315fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
14325fcfab6eSJohn Baldwin {
14335fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
14345fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
14355fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
14365fcfab6eSJohn Baldwin 	int status;
14375fcfab6eSJohn Baldwin 
14385fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14395fcfab6eSJohn Baldwin 	if (fpid == 0) {
14405fcfab6eSJohn Baldwin 		trace_me();
14415fcfab6eSJohn Baldwin 		exec_thread_main();
14425fcfab6eSJohn Baldwin 	}
14435fcfab6eSJohn Baldwin 
14445fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14455fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1446*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14475fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1448*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
14495fcfab6eSJohn Baldwin 
14505fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
14515fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
14525fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
14535fcfab6eSJohn Baldwin 
1454*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
14555fcfab6eSJohn Baldwin 
14565fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1457*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14585fcfab6eSJohn Baldwin 
14595fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
14605fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1461*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14625fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1463*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14645fcfab6eSJohn Baldwin 
14655fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1466*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
14675fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
14685fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
14695fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
14705fcfab6eSJohn Baldwin 
1471*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14725fcfab6eSJohn Baldwin 
14735fcfab6eSJohn Baldwin 	/*
14745fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
14755fcfab6eSJohn Baldwin 	 * single threading from execve().
14765fcfab6eSJohn Baldwin 	 */
14775fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1478*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14795fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1480*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14815fcfab6eSJohn Baldwin 
14825fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1483*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)),
14845fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
1485*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[0]);
14865fcfab6eSJohn Baldwin 
1487*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14885fcfab6eSJohn Baldwin 
14895fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
14905fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14915fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1492*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14935fcfab6eSJohn Baldwin 
14945fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1495*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)),
14965fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
1497*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[1]);
14985fcfab6eSJohn Baldwin 
1499*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15005fcfab6eSJohn Baldwin 
15015fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
15025fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15035fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1504*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
15055fcfab6eSJohn Baldwin 
15065fcfab6eSJohn Baldwin 	wpid = wait(&status);
1507*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1508*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15095fcfab6eSJohn Baldwin }
15105fcfab6eSJohn Baldwin 
15113340c45bSJohn Baldwin static void
15123340c45bSJohn Baldwin handler(int sig __unused)
15133340c45bSJohn Baldwin {
15143340c45bSJohn Baldwin }
15153340c45bSJohn Baldwin 
15163340c45bSJohn Baldwin static void
15173340c45bSJohn Baldwin signal_main(void)
15183340c45bSJohn Baldwin {
15193340c45bSJohn Baldwin 
15203340c45bSJohn Baldwin 	signal(SIGINFO, handler);
15213340c45bSJohn Baldwin 	raise(SIGINFO);
15223340c45bSJohn Baldwin 	exit(0);
15233340c45bSJohn Baldwin }
15243340c45bSJohn Baldwin 
15253340c45bSJohn Baldwin /*
15263340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
15273340c45bSJohn Baldwin  */
15283340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
15293340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
15303340c45bSJohn Baldwin {
15313340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
15323340c45bSJohn Baldwin 	pid_t fpid, wpid;
15333340c45bSJohn Baldwin 	int status;
15343340c45bSJohn Baldwin 
15353340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15363340c45bSJohn Baldwin 	if (fpid == 0) {
15373340c45bSJohn Baldwin 		trace_me();
15383340c45bSJohn Baldwin 		signal_main();
15393340c45bSJohn Baldwin 	}
15403340c45bSJohn Baldwin 
15413340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15423340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1543*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
15443340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1545*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15463340c45bSJohn Baldwin 
1547*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15483340c45bSJohn Baldwin 
15493340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
15503340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15513340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1552*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGINFO);
15533340c45bSJohn Baldwin 
15543340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1555*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
15563340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
1557*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, SI_LWP);
1558*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_pid, wpid);
15593340c45bSJohn Baldwin 
1560*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15613340c45bSJohn Baldwin 
15623340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
15633340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15643340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1565*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
15663340c45bSJohn Baldwin 
15673340c45bSJohn Baldwin 	wpid = wait(&status);
1568*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1569*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15703340c45bSJohn Baldwin }
15713340c45bSJohn Baldwin 
15728d570f64SJohn Baldwin /*
15738d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
15748d570f64SJohn Baldwin  */
15758d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
15768d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
15778d570f64SJohn Baldwin {
15788d570f64SJohn Baldwin 	pid_t fpid, wpid;
15798d570f64SJohn Baldwin 	int events, status;
15808d570f64SJohn Baldwin 
15818d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15828d570f64SJohn Baldwin 	if (fpid == 0) {
15838d570f64SJohn Baldwin 		trace_me();
15848d570f64SJohn Baldwin 		exec_thread(NULL);
15858d570f64SJohn Baldwin 	}
15868d570f64SJohn Baldwin 
15878d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15888d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1589*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
15908d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1591*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15928d570f64SJohn Baldwin 
15938d570f64SJohn Baldwin 	events = 0;
15948d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15958d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15968d570f64SJohn Baldwin 
1597*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15988d570f64SJohn Baldwin 
15998d570f64SJohn Baldwin 	/* Should get one event at exit. */
16008d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16018d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1602*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16038d570f64SJohn Baldwin 
16048d570f64SJohn Baldwin 	wpid = wait(&status);
1605*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1606*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
16078d570f64SJohn Baldwin }
16088d570f64SJohn Baldwin 
16098d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
16108d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
16118d570f64SJohn Baldwin {
16128d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
16138d570f64SJohn Baldwin 	pid_t fpid, wpid;
16148d570f64SJohn Baldwin 	int events, status;
16158d570f64SJohn Baldwin 
16168d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16178d570f64SJohn Baldwin 	if (fpid == 0) {
16188d570f64SJohn Baldwin 		trace_me();
16198d570f64SJohn Baldwin 		exec_thread(NULL);
16208d570f64SJohn Baldwin 	}
16218d570f64SJohn Baldwin 
16228d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16238d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1624*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
16258d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1626*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
16278d570f64SJohn Baldwin 
16288d570f64SJohn Baldwin 	events = PTRACE_EXEC;
16298d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
16308d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16318d570f64SJohn Baldwin 
1632*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16338d570f64SJohn Baldwin 
16348d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
16358d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16368d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1637*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
16388d570f64SJohn Baldwin 
16398d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1640*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)),
16418d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
16428d570f64SJohn Baldwin 
1643*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16448d570f64SJohn Baldwin 
16458d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
16468d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16478d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1648*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16498d570f64SJohn Baldwin 
16508d570f64SJohn Baldwin 	wpid = wait(&status);
1651*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1652*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
16538d570f64SJohn Baldwin }
16548d570f64SJohn Baldwin 
16558d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
16568d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
16578d570f64SJohn Baldwin {
16588d570f64SJohn Baldwin 	pid_t fpid, wpid;
16598d570f64SJohn Baldwin 	int events, status;
16608d570f64SJohn Baldwin 
16618d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16628d570f64SJohn Baldwin 	if (fpid == 0) {
16638d570f64SJohn Baldwin 		trace_me();
16648d570f64SJohn Baldwin 		exit(0);
16658d570f64SJohn Baldwin 	}
16668d570f64SJohn Baldwin 
16678d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16688d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1669*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
16708d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1671*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
16728d570f64SJohn Baldwin 
16738d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
16748d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
16758d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16768d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16778d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_FORK);
16788d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
16798d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16808d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16818d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_FORK));
16828d570f64SJohn Baldwin 
16838d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
16848d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
16858d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16868d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16878d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_LWP);
16888d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
16898d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16908d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16918d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_LWP));
16928d570f64SJohn Baldwin 
1693*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16948d570f64SJohn Baldwin 
16958d570f64SJohn Baldwin 	/* Should get one event at exit. */
16968d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16978d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1698*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16998d570f64SJohn Baldwin 
17008d570f64SJohn Baldwin 	wpid = wait(&status);
1701*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1702*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
17038d570f64SJohn Baldwin }
17048d570f64SJohn Baldwin 
1705fc4f075aSJohn Baldwin /*
1706fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1707fc4f075aSJohn Baldwin  */
1708fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
1709fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1710fc4f075aSJohn Baldwin {
1711fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1712fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1713fc4f075aSJohn Baldwin 	int events, status;
1714fc4f075aSJohn Baldwin 
1715fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1716fc4f075aSJohn Baldwin 	if (fpid == 0) {
1717fc4f075aSJohn Baldwin 		trace_me();
1718fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1719fc4f075aSJohn Baldwin 	}
1720fc4f075aSJohn Baldwin 
1721fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1722fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1723*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1724fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1725*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1726fc4f075aSJohn Baldwin 
1727fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1728fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1729fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1730fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1731fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1732fc4f075aSJohn Baldwin 
1733fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1734fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1735fc4f075aSJohn Baldwin 
1736fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1737fc4f075aSJohn Baldwin 	wpid = wait(&status);
1738*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1739fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1740*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1741fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1742fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1743fc4f075aSJohn Baldwin 
1744fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1745fc4f075aSJohn Baldwin 
1746fc4f075aSJohn Baldwin 	wpid = wait(&status);
1747*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1748fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1749*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1750fc4f075aSJohn Baldwin 
1751fc4f075aSJohn Baldwin 	wpid = wait(&status);
1752*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1753*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1754fc4f075aSJohn Baldwin }
1755fc4f075aSJohn Baldwin 
1756fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
1757fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1758fc4f075aSJohn Baldwin {
1759fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1760fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1761fc4f075aSJohn Baldwin 	int events, status;
1762fc4f075aSJohn Baldwin 
1763fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1764fc4f075aSJohn Baldwin 	if (fpid == 0) {
1765fc4f075aSJohn Baldwin 		trace_me();
1766fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1767fc4f075aSJohn Baldwin 	}
1768fc4f075aSJohn Baldwin 
1769fc4f075aSJohn Baldwin 	/* Parent process. */
1770fc4f075aSJohn Baldwin 	children[0] = fpid;
1771fc4f075aSJohn Baldwin 
1772fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1773fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1774*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1775fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1776*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1777fc4f075aSJohn Baldwin 
1778fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1779fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1780fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1781fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1782fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1783fc4f075aSJohn Baldwin 
1784fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1785fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1786fc4f075aSJohn Baldwin 
1787fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1788fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1789fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1790fc4f075aSJohn Baldwin 
1791fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1792fc4f075aSJohn Baldwin 
1793fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1794fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1795fc4f075aSJohn Baldwin 
1796fc4f075aSJohn Baldwin 	/*
1797fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1798fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1799fc4f075aSJohn Baldwin 	 */
1800fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
1801*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1802fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1803*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1804fc4f075aSJohn Baldwin 
1805fc4f075aSJohn Baldwin 	/*
1806fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1807fc4f075aSJohn Baldwin 	 * exits.
1808fc4f075aSJohn Baldwin 	 */
1809fc4f075aSJohn Baldwin 	wpid = wait(&status);
1810*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1811fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1812*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1813fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1814fc4f075aSJohn Baldwin 	    -1);
1815fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1816fc4f075aSJohn Baldwin 
1817fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1818fc4f075aSJohn Baldwin 
1819fc4f075aSJohn Baldwin 	wpid = wait(&status);
1820*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1821fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1822*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1823fc4f075aSJohn Baldwin 
1824fc4f075aSJohn Baldwin 	wpid = wait(&status);
1825*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1826*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1827fc4f075aSJohn Baldwin }
1828fc4f075aSJohn Baldwin 
1829403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
1830e2ebfbbfSEric Badger /*
183182a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
183282a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
183382a4538fSEric Badger  */
183482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
183582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
183682a4538fSEric Badger {
183782a4538fSEric Badger 	pid_t fpid, wpid;
183882a4538fSEric Badger 	int status;
183982a4538fSEric Badger 
184082a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
184182a4538fSEric Badger 	if (fpid == 0) {
184282a4538fSEric Badger 		trace_me();
18439e0d1159SEric Badger 		breakpoint();
184482a4538fSEric Badger 		exit(1);
184582a4538fSEric Badger 	}
184682a4538fSEric Badger 
184782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
184882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1849*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
185082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
1851*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
185282a4538fSEric Badger 
185382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
1854*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
185582a4538fSEric Badger 
185682a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
185782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1858*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
185982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
1860*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
186182a4538fSEric Badger 
186282a4538fSEric Badger 	/* Kill the child process. */
1863*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
186482a4538fSEric Badger 
186582a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
186682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1867*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
186882a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
1869*96a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
187082a4538fSEric Badger 
187182a4538fSEric Badger 	wpid = wait(&status);
1872*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1873*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
187482a4538fSEric Badger }
1875403e331dSJohn Baldwin #endif /* HAVE_BREAKPOINT */
187682a4538fSEric Badger 
187782a4538fSEric Badger /*
187882a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
187982a4538fSEric Badger  * process exit when stopped inside of a system call.
188082a4538fSEric Badger  */
188182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
188282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
188382a4538fSEric Badger {
188482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
188582a4538fSEric Badger 	pid_t fpid, wpid;
188682a4538fSEric Badger 	int status;
188782a4538fSEric Badger 
188882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
188982a4538fSEric Badger 	if (fpid == 0) {
189082a4538fSEric Badger 		trace_me();
189182a4538fSEric Badger 		getpid();
189282a4538fSEric Badger 		exit(1);
189382a4538fSEric Badger 	}
189482a4538fSEric Badger 
189582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
189682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1897*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
189882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
1899*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
190082a4538fSEric Badger 
190182a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
1902*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
190382a4538fSEric Badger 
190482a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
190582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1906*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
190782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
1908*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
190982a4538fSEric Badger 
191082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
191182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
191282a4538fSEric Badger 
191382a4538fSEric Badger 	/* Kill the child process. */
1914*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
191582a4538fSEric Badger 
191682a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
191782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1918*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
191982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
1920*96a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
192182a4538fSEric Badger 
192282a4538fSEric Badger 	wpid = wait(&status);
1923*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1924*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
192582a4538fSEric Badger }
192682a4538fSEric Badger 
192782a4538fSEric Badger /*
192882a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
192982a4538fSEric Badger  * process exit when killing a multithreaded process.
193082a4538fSEric Badger  */
193182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
193282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
193382a4538fSEric Badger {
193482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
193582a4538fSEric Badger 	pid_t fpid, wpid;
193682a4538fSEric Badger 	lwpid_t main_lwp;
193782a4538fSEric Badger 	int status;
193882a4538fSEric Badger 
193982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
194082a4538fSEric Badger 	if (fpid == 0) {
194182a4538fSEric Badger 		trace_me();
194282a4538fSEric Badger 		simple_thread_main();
194382a4538fSEric Badger 	}
194482a4538fSEric Badger 
194582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
194682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1947*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
194882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
1949*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
195082a4538fSEric Badger 
195182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
195282a4538fSEric Badger 	    sizeof(pl)) != -1);
195382a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
195482a4538fSEric Badger 
1955*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
195682a4538fSEric Badger 
195782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
1958*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
195982a4538fSEric Badger 
196082a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
196182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1962*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
196382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
1964*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
196582a4538fSEric Badger 
196682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1967*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
196882a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
196982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
197082a4538fSEric Badger 
197182a4538fSEric Badger 	/* Kill the child process. */
1972*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
197382a4538fSEric Badger 
197482a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
197582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
1976*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
197782a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
1978*96a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
197982a4538fSEric Badger 
198082a4538fSEric Badger 	wpid = wait(&status);
1981*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
1982*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
198382a4538fSEric Badger }
198482a4538fSEric Badger 
198582a4538fSEric Badger static void *
198682a4538fSEric Badger mask_usr1_thread(void *arg)
198782a4538fSEric Badger {
198882a4538fSEric Badger 	pthread_barrier_t *pbarrier;
198982a4538fSEric Badger 	sigset_t sigmask;
199082a4538fSEric Badger 
199182a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
199282a4538fSEric Badger 
199382a4538fSEric Badger 	sigemptyset(&sigmask);
199482a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
1995*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
199682a4538fSEric Badger 
199782a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
199882a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
199982a4538fSEric Badger 
200082a4538fSEric Badger 	for (;;)
200182a4538fSEric Badger 		sleep(60);
200282a4538fSEric Badger 
200382a4538fSEric Badger 	return (NULL);
200482a4538fSEric Badger }
200582a4538fSEric Badger 
200682a4538fSEric Badger /*
200782a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
200882a4538fSEric Badger  * and prevents spurious stops due to those other signals.
200982a4538fSEric Badger  */
20103cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal);
20113cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
20123cf56bb4SEnji Cooper {
20133cf56bb4SEnji Cooper 
20143cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
20153cf56bb4SEnji Cooper }
201682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
201782a4538fSEric Badger {
201882a4538fSEric Badger 	pid_t fpid, wpid;
201982a4538fSEric Badger 	int status;
202082a4538fSEric Badger 	cpuset_t setmask;
202182a4538fSEric Badger 	pthread_t t;
202282a4538fSEric Badger 	pthread_barrier_t barrier;
2023bc2be1d3SEric Badger 	struct sched_param sched_param;
202482a4538fSEric Badger 
202582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
202682a4538fSEric Badger 	if (fpid == 0) {
2027bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
202882a4538fSEric Badger 		CPU_ZERO(&setmask);
202982a4538fSEric Badger 		CPU_SET(0, &setmask);
203082a4538fSEric Badger 		cpusetid_t setid;
2031*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(cpuset(&setid), 0);
203282a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
203382a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
203482a4538fSEric Badger 
2035*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
203682a4538fSEric Badger 
203782a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
203882a4538fSEric Badger 		    (void*)&barrier) == 0);
203982a4538fSEric Badger 
2040bc2be1d3SEric Badger 		/*
2041bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2042bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2043bc2be1d3SEric Badger 		 * thread runs first.
2044bc2be1d3SEric Badger 		 */
2045bc2be1d3SEric Badger 		sched_param.sched_priority =
2046bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2047bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2048bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2049bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2050bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2051bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2052bc2be1d3SEric Badger 		    &sched_param) == 0);
2053bc2be1d3SEric Badger 
205482a4538fSEric Badger 		sigset_t sigmask;
205582a4538fSEric Badger 		sigemptyset(&sigmask);
205682a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
2057*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
205882a4538fSEric Badger 
205982a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
206082a4538fSEric Badger 		pthread_barrier_wait(&barrier);
206182a4538fSEric Badger 
206282a4538fSEric Badger 		trace_me();
206382a4538fSEric Badger 
206482a4538fSEric Badger 		for (;;)
206582a4538fSEric Badger 			sleep(60);
206682a4538fSEric Badger 
206782a4538fSEric Badger 		exit(1);
206882a4538fSEric Badger 	}
206982a4538fSEric Badger 
207082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
207182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2072*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
207382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2074*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
207582a4538fSEric Badger 
207682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
2077*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
207882a4538fSEric Badger 
207982a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
2080*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
208182a4538fSEric Badger 
208282a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
208382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2084*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
208582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2086*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
208782a4538fSEric Badger 
208882a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
2089*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
209082a4538fSEric Badger 
209182a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
2092*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
209382a4538fSEric Badger 
209482a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
209582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2096*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
209782a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
2098*96a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
209982a4538fSEric Badger 
210082a4538fSEric Badger 	wpid = wait(&status);
2101*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2102*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
210382a4538fSEric Badger }
210482a4538fSEric Badger 
210582a4538fSEric Badger /*
210682a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
210782a4538fSEric Badger  * and prevents spurious stops caused by those events.
210882a4538fSEric Badger  */
21093cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop);
21103cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc)
21113cf56bb4SEnji Cooper {
21123cf56bb4SEnji Cooper 
21133cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
21143cf56bb4SEnji Cooper }
211582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
211682a4538fSEric Badger {
211782a4538fSEric Badger 	pid_t fpid, wpid;
2118bc2be1d3SEric Badger 	int status;
211982a4538fSEric Badger 	cpuset_t setmask;
212082a4538fSEric Badger 	pthread_t t;
212182a4538fSEric Badger 	pthread_barrier_t barrier;
212282a4538fSEric Badger 	lwpid_t main_lwp;
212382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2124bc2be1d3SEric Badger 	struct sched_param sched_param;
212582a4538fSEric Badger 
212684922a5dSLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
21277d1f7471SLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/220841");
21287d1f7471SLi-Wen Hsu 
212982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
213082a4538fSEric Badger 	if (fpid == 0) {
213182a4538fSEric Badger 		trace_me();
213282a4538fSEric Badger 
2133bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
213482a4538fSEric Badger 		CPU_ZERO(&setmask);
213582a4538fSEric Badger 		CPU_SET(0, &setmask);
213682a4538fSEric Badger 		cpusetid_t setid;
2137*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(cpuset(&setid), 0);
213882a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
213982a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
214082a4538fSEric Badger 
2141*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
214282a4538fSEric Badger 
214382a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
214482a4538fSEric Badger 		    (void*)&barrier) == 0);
214582a4538fSEric Badger 
2146bc2be1d3SEric Badger 		/*
2147bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2148bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2149bc2be1d3SEric Badger 		 * thread runs first.
2150bc2be1d3SEric Badger 		 */
2151bc2be1d3SEric Badger 		sched_param.sched_priority =
2152bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2153bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2154bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2155bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2156bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2157bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2158bc2be1d3SEric Badger 		    &sched_param) == 0);
2159bc2be1d3SEric Badger 
216082a4538fSEric Badger 		sigset_t sigmask;
216182a4538fSEric Badger 		sigemptyset(&sigmask);
216282a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
2163*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
216482a4538fSEric Badger 
216582a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
216682a4538fSEric Badger 		pthread_barrier_wait(&barrier);
216782a4538fSEric Badger 
216882a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
216982a4538fSEric Badger 		raise(SIGSTOP);
217082a4538fSEric Badger 
217182a4538fSEric Badger 		getpid();
217282a4538fSEric Badger 		exit(1);
217382a4538fSEric Badger 	}
217482a4538fSEric Badger 
217582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
217682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2177*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
217882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2179*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
218082a4538fSEric Badger 
218182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
218282a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
218382a4538fSEric Badger 
218482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
2185*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
218682a4538fSEric Badger 
218782a4538fSEric Badger 	/*
218882a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
218982a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
219082a4538fSEric Badger 	 */
219182a4538fSEric Badger 	for (;;) {
219282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
2193*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
219482a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
219582a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
219682a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
219782a4538fSEric Badger 			    sizeof(pl)) != -1);
219882a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
219982a4538fSEric Badger 		} else {
2200*96a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
220182a4538fSEric Badger 			break;
220282a4538fSEric Badger 		}
2203*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
220482a4538fSEric Badger 	}
220582a4538fSEric Badger 
2206bc2be1d3SEric Badger 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
2207*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
220882a4538fSEric Badger 
220982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2210*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
221182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2212*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
221382a4538fSEric Badger 
221482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
221582a4538fSEric Badger 	    sizeof(pl)) != -1);
2216*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, main_lwp);
221782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
2218bc2be1d3SEric Badger 	/* Prevent the main thread from hitting its syscall exit for now. */
2219*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SUSPEND, main_lwp, 0, 0), 0);
222082a4538fSEric Badger 
2221bc2be1d3SEric Badger 	/*
2222bc2be1d3SEric Badger 	 * Proceed, allowing second thread to hit syscall exit for
2223bc2be1d3SEric Badger 	 * pthread_barrier_wait().
2224bc2be1d3SEric Badger 	 */
2225*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
2226bc2be1d3SEric Badger 
2227bc2be1d3SEric Badger 	wpid = waitpid(fpid, &status, 0);
2228*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2229bc2be1d3SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2230*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
2231bc2be1d3SEric Badger 
2232bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
2233bc2be1d3SEric Badger 	    sizeof(pl)) != -1);
2234bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
2235bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
223682a4538fSEric Badger 
223782a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
2238*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
223982a4538fSEric Badger 
2240*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
224182a4538fSEric Badger 
2242bc2be1d3SEric Badger 	/* The next wait() should report the SIGUSR2. */
224382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2244*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
224582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2246*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
224782a4538fSEric Badger 
224882a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
2249*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_RESUME, main_lwp, 0, 0), 0);
225082a4538fSEric Badger 
225182a4538fSEric Badger 	/*
225282a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
2253bc2be1d3SEric Badger 	 * has been resumed. The second thread has taken a SIGUSR2 which will
2254bc2be1d3SEric Badger 	 * be replaced with a SIGKILL below. The main thread will get to run
2255bc2be1d3SEric Badger 	 * first. It should notice the kill request (even though the signal
2256bc2be1d3SEric Badger 	 * replacement occurred in the other thread) and exit accordingly.  It
2257bc2be1d3SEric Badger 	 * should not stop for the system call exit event.
225882a4538fSEric Badger 	 */
225982a4538fSEric Badger 
226082a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
2261*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
226282a4538fSEric Badger 
226382a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
226482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2265*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
226682a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
2267*96a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
226882a4538fSEric Badger 
226982a4538fSEric Badger 	wpid = wait(&status);
2270*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2271*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
227282a4538fSEric Badger }
227382a4538fSEric Badger 
227482a4538fSEric Badger static void
227582a4538fSEric Badger sigusr1_handler(int sig)
227682a4538fSEric Badger {
227782a4538fSEric Badger 
2278*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
227982a4538fSEric Badger 	_exit(2);
228082a4538fSEric Badger }
228182a4538fSEric Badger 
228282a4538fSEric Badger /*
228382a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
228482a4538fSEric Badger  * a PT_KILL will kill the process.
228582a4538fSEric Badger  */
228682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
228782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
228882a4538fSEric Badger {
228982a4538fSEric Badger 	pid_t fpid, wpid;
229082a4538fSEric Badger 	int status;
229182a4538fSEric Badger 	int max_pending_per_proc;
229282a4538fSEric Badger 	size_t len;
229382a4538fSEric Badger 	int i;
229482a4538fSEric Badger 
229582a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
229682a4538fSEric Badger 
229782a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
229882a4538fSEric Badger 	if (fpid == 0) {
229982a4538fSEric Badger 		trace_me();
230082a4538fSEric Badger 		exit(1);
230182a4538fSEric Badger 	}
230282a4538fSEric Badger 
230382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
230482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2305*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
230682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2307*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
230882a4538fSEric Badger 
230982a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
231082a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
231182a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
231282a4538fSEric Badger 
231382a4538fSEric Badger 	/* Fill the signal queue. */
231482a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
2315*96a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
231682a4538fSEric Badger 
231782a4538fSEric Badger 	/* Kill the child process. */
2318*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
231982a4538fSEric Badger 
232082a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
232182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2322*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
232382a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
2324*96a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
232582a4538fSEric Badger 
232682a4538fSEric Badger 	wpid = wait(&status);
2327*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2328*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
232982a4538fSEric Badger }
233082a4538fSEric Badger 
233182a4538fSEric Badger /*
233282a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
233382a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
233482a4538fSEric Badger  * call is complete.
233582a4538fSEric Badger  */
233682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
233782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
233882a4538fSEric Badger {
233982a4538fSEric Badger 	struct ptrace_lwpinfo pl;
234082a4538fSEric Badger 	pid_t fpid, wpid;
234182a4538fSEric Badger 	int status;
234282a4538fSEric Badger 
234382a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
234482a4538fSEric Badger 
234582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
234682a4538fSEric Badger 	if (fpid == 0) {
234782a4538fSEric Badger 		trace_me();
234882a4538fSEric Badger 		getpid();
234982a4538fSEric Badger 		exit(1);
235082a4538fSEric Badger 	}
235182a4538fSEric Badger 
235282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
235382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2354*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
235582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2356*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
235782a4538fSEric Badger 
235882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
2359*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
236082a4538fSEric Badger 
236182a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
236282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2363*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
236482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2365*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
236682a4538fSEric Badger 
236782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
236882a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
236982a4538fSEric Badger 
237082a4538fSEric Badger 	/* Continue the child process with a signal. */
2371*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
237282a4538fSEric Badger 
237382a4538fSEric Badger 	for (;;) {
237482a4538fSEric Badger 		/*
237582a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
237682a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
237782a4538fSEric Badger 		 * past any syscall stops.
237882a4538fSEric Badger 		 */
237982a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
2380*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
238182a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
238282a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
238382a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
2384*96a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
238582a4538fSEric Badger 		} else {
238682a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
2387*96a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
238882a4538fSEric Badger 			break;
238982a4538fSEric Badger 		}
239082a4538fSEric Badger 	}
239182a4538fSEric Badger 
239282a4538fSEric Badger 	wpid = wait(&status);
2393*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2394*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
239582a4538fSEric Badger }
239682a4538fSEric Badger 
239782a4538fSEric Badger static void
239882a4538fSEric Badger sigusr1_counting_handler(int sig)
239982a4538fSEric Badger {
240082a4538fSEric Badger 	static int counter = 0;
240182a4538fSEric Badger 
2402*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
240382a4538fSEric Badger 	counter++;
240482a4538fSEric Badger 	if (counter == 2)
240582a4538fSEric Badger 		_exit(2);
240682a4538fSEric Badger }
240782a4538fSEric Badger 
240882a4538fSEric Badger /*
240982a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
241082a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
241182a4538fSEric Badger  * the system call is complete.
241282a4538fSEric Badger  */
241382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
241482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
241582a4538fSEric Badger {
241682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
241782a4538fSEric Badger 	pid_t fpid, wpid;
241882a4538fSEric Badger 	int status;
241982a4538fSEric Badger 
242082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
242182a4538fSEric Badger 
242282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
242382a4538fSEric Badger 	if (fpid == 0) {
242482a4538fSEric Badger 		trace_me();
242582a4538fSEric Badger 		getpid();
242682a4538fSEric Badger 		exit(1);
242782a4538fSEric Badger 	}
242882a4538fSEric Badger 
242982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
243082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2431*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
243282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2433*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
243482a4538fSEric Badger 
243582a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
2436*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
243782a4538fSEric Badger 
243882a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
243982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2440*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
244182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2442*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
244382a4538fSEric Badger 
244482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
244582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
244682a4538fSEric Badger 
244782a4538fSEric Badger 	/* Continue the child process with a signal. */
2448*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
244982a4538fSEric Badger 
245082a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
245182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2452*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
245382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2454*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
245582a4538fSEric Badger 
245682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
245782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
245882a4538fSEric Badger 
245982a4538fSEric Badger 	/* Continue the child process with a signal. */
2460*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
246182a4538fSEric Badger 
246282a4538fSEric Badger 	for (;;) {
246382a4538fSEric Badger 		/*
246482a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
246582a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
246682a4538fSEric Badger 		 * past any syscall stops.
246782a4538fSEric Badger 		 */
246882a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
2469*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
247082a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
247182a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
247282a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
2473*96a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
247482a4538fSEric Badger 		} else {
247582a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
2476*96a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
247782a4538fSEric Badger 			break;
247882a4538fSEric Badger 		}
247982a4538fSEric Badger 	}
248082a4538fSEric Badger 
248182a4538fSEric Badger 	wpid = wait(&status);
2482*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2483*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
248482a4538fSEric Badger }
248582a4538fSEric Badger 
248682a4538fSEric Badger /*
248782a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
248882a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
248982a4538fSEric Badger  */
249082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
249182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
249282a4538fSEric Badger {
249382a4538fSEric Badger 	pid_t fpid, wpid;
249482a4538fSEric Badger 	int status;
249582a4538fSEric Badger 	int max_pending_per_proc;
249682a4538fSEric Badger 	size_t len;
249782a4538fSEric Badger 	int i;
249882a4538fSEric Badger 
249982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
250082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
250182a4538fSEric Badger 
250282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
250382a4538fSEric Badger 	if (fpid == 0) {
250482a4538fSEric Badger 		trace_me();
250582a4538fSEric Badger 		exit(1);
250682a4538fSEric Badger 	}
250782a4538fSEric Badger 
250882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
250982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2510*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
251182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2512*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
251382a4538fSEric Badger 
251482a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
251582a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
251682a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
251782a4538fSEric Badger 
251882a4538fSEric Badger 	/* Fill the signal queue. */
251982a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
2520*96a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
252182a4538fSEric Badger 
252282a4538fSEric Badger 	/* Continue with signal. */
2523*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
252482a4538fSEric Badger 
252582a4538fSEric Badger 	for (;;) {
252682a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
2527*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
252882a4538fSEric Badger 		if (WIFSTOPPED(status)) {
2529*96a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
2530*96a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
253182a4538fSEric Badger 		} else {
253282a4538fSEric Badger 			/*
253382a4538fSEric Badger 			 * The last wait() should report normal _exit from the
253482a4538fSEric Badger 			 * SIGUSR1 handler.
253582a4538fSEric Badger 			 */
253682a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
2537*96a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
253882a4538fSEric Badger 			break;
253982a4538fSEric Badger 		}
254082a4538fSEric Badger 	}
254182a4538fSEric Badger 
254282a4538fSEric Badger 	wpid = wait(&status);
2543*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2544*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
254582a4538fSEric Badger }
254682a4538fSEric Badger 
2547753e2922SBryan Drewery static sem_t sigusr1_sem;
2548753e2922SBryan Drewery static int got_usr1;
2549753e2922SBryan Drewery 
2550753e2922SBryan Drewery static void
2551753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused)
2552753e2922SBryan Drewery {
2553753e2922SBryan Drewery 
2554753e2922SBryan Drewery 	got_usr1++;
2555*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sem_post(&sigusr1_sem), 0);
2556753e2922SBryan Drewery }
2557753e2922SBryan Drewery 
2558753e2922SBryan Drewery /*
2559753e2922SBryan Drewery  * Verify that even if the signal queue is full for a child process,
2560753e2922SBryan Drewery  * and the signal is masked, a PT_CONTINUE with a signal will not
2561753e2922SBryan Drewery  * result in loss of that signal.
2562753e2922SBryan Drewery  */
2563753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
2564753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
2565753e2922SBryan Drewery {
2566753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2567753e2922SBryan Drewery 	pid_t fpid, wpid;
2568753e2922SBryan Drewery 	int status, err;
2569753e2922SBryan Drewery 	int max_pending_per_proc;
2570753e2922SBryan Drewery 	size_t len;
2571753e2922SBryan Drewery 	int i;
2572753e2922SBryan Drewery 	sigset_t sigmask;
2573753e2922SBryan Drewery 
2574753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
2575*96a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
2576753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2577753e2922SBryan Drewery 
2578753e2922SBryan Drewery 	got_usr1 = 0;
2579753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2580753e2922SBryan Drewery 	if (fpid == 0) {
2581*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
2582*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
2583*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
2584753e2922SBryan Drewery 
2585753e2922SBryan Drewery 		trace_me();
2586*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
2587753e2922SBryan Drewery 
2588753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2589*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
2590753e2922SBryan Drewery 		/* Wait to receive the SIGUSR1. */
2591753e2922SBryan Drewery 		do {
2592753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2593753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2594753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2595*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
2596753e2922SBryan Drewery 		exit(1);
2597753e2922SBryan Drewery 	}
2598753e2922SBryan Drewery 
2599753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2600753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2601*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2602753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2603*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
2604753e2922SBryan Drewery 
2605753e2922SBryan Drewery 	len = sizeof(max_pending_per_proc);
2606753e2922SBryan Drewery 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
2607753e2922SBryan Drewery 	    &max_pending_per_proc, &len, NULL, 0) == 0);
2608753e2922SBryan Drewery 
2609753e2922SBryan Drewery 	/* Fill the signal queue. */
2610753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i)
2611*96a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
2612753e2922SBryan Drewery 
2613753e2922SBryan Drewery 	/* Continue with signal. */
2614*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
2615753e2922SBryan Drewery 
2616753e2922SBryan Drewery 	/* Collect and ignore all of the SIGUSR2. */
2617753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i) {
2618753e2922SBryan Drewery 		wpid = waitpid(fpid, &status, 0);
2619*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
2620753e2922SBryan Drewery 		ATF_REQUIRE(WIFSTOPPED(status));
2621*96a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
2622*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2623753e2922SBryan Drewery 	}
2624753e2922SBryan Drewery 
2625753e2922SBryan Drewery 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
2626753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2627*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2628753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2629*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
2630753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2631*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
2632753e2922SBryan Drewery 
2633753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
2634*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2635753e2922SBryan Drewery 
2636753e2922SBryan Drewery 	/* The last wait() should report exit after receiving SIGUSR1. */
2637753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2638*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2639753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2640*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
2641753e2922SBryan Drewery 
2642753e2922SBryan Drewery 	wpid = wait(&status);
2643*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2644*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
2645753e2922SBryan Drewery }
2646753e2922SBryan Drewery 
264782a4538fSEric Badger /*
264882a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
264982a4538fSEric Badger  * replaced with another signal.
265082a4538fSEric Badger  */
265182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
265282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
265382a4538fSEric Badger {
265482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
265582a4538fSEric Badger 	pid_t fpid, wpid;
265682a4538fSEric Badger 	int status;
265782a4538fSEric Badger 
265882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
265982a4538fSEric Badger 	if (fpid == 0) {
266082a4538fSEric Badger 		trace_me();
266182a4538fSEric Badger 		sleep(20);
266282a4538fSEric Badger 		exit(1);
266382a4538fSEric Badger 	}
266482a4538fSEric Badger 
266582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
266682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2667*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
266882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2669*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
267082a4538fSEric Badger 
2671*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
267282a4538fSEric Badger 
267382a4538fSEric Badger 	/* Send a signal without ptrace. */
2674*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGINT), 0);
267582a4538fSEric Badger 
267682a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
267782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2678*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
267982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2680*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGINT);
268182a4538fSEric Badger 
268282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
268382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
2684*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGINT);
268582a4538fSEric Badger 
268682a4538fSEric Badger 	/* Continue the child process with a different signal. */
2687*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM), 0);
268882a4538fSEric Badger 
268982a4538fSEric Badger 	/*
269082a4538fSEric Badger 	 * The last wait() should report having died due to the new
269182a4538fSEric Badger 	 * signal, SIGTERM.
269282a4538fSEric Badger 	 */
269382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2694*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
269582a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
2696*96a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGTERM);
269782a4538fSEric Badger 
269882a4538fSEric Badger 	wpid = wait(&status);
2699*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2700*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
270182a4538fSEric Badger }
270282a4538fSEric Badger 
270382a4538fSEric Badger /*
270482a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
270582a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
270682a4538fSEric Badger  * invented for e.g, system call stops.
270782a4538fSEric Badger  */
270882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
270982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
271082a4538fSEric Badger {
271182a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2712fc1e29dcSBryan Drewery 	struct rlimit rl;
271382a4538fSEric Badger 	pid_t fpid, wpid;
271482a4538fSEric Badger 	int status;
271582a4538fSEric Badger 
271682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
271782a4538fSEric Badger 	if (fpid == 0) {
271882a4538fSEric Badger 		trace_me();
2719fc1e29dcSBryan Drewery 		/* SIGTRAP expected to cause exit on syscall entry. */
2720fc1e29dcSBryan Drewery 		rl.rlim_cur = rl.rlim_max = 0;
2721*96a9e50eSAlex Richardson 		REQUIRE_EQ(setrlimit(RLIMIT_CORE, &rl), 0);
272282a4538fSEric Badger 		getpid();
272382a4538fSEric Badger 		exit(1);
272482a4538fSEric Badger 	}
272582a4538fSEric Badger 
272682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
272782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2728*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
272982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2730*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
273182a4538fSEric Badger 
273282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
2733*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
273482a4538fSEric Badger 
273582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
273682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2737*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
273882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2739*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
274082a4538fSEric Badger 
274182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
274282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
274382a4538fSEric Badger 
274482a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
2745*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP), 0);
274682a4538fSEric Badger 
274782a4538fSEric Badger 	for (;;) {
274882a4538fSEric Badger 		/*
274982a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
275082a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
275182a4538fSEric Badger 		 */
275282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
2753*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
275482a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
275582a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
275682a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
2757*96a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
275882a4538fSEric Badger 		} else {
275982a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
2760*96a9e50eSAlex Richardson 			REQUIRE_EQ(WTERMSIG(status), SIGTRAP);
276182a4538fSEric Badger 			break;
276282a4538fSEric Badger 		}
276382a4538fSEric Badger 	}
276482a4538fSEric Badger 
276582a4538fSEric Badger 	wpid = wait(&status);
2766*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2767*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
276882a4538fSEric Badger }
276982a4538fSEric Badger 
277082a4538fSEric Badger /*
277182a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
277282a4538fSEric Badger  */
277382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
277482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
277582a4538fSEric Badger {
277682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
277782a4538fSEric Badger 	pid_t fpid, wpid;
277882a4538fSEric Badger 	int status;
277982a4538fSEric Badger 
278082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
278182a4538fSEric Badger 
278282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
278382a4538fSEric Badger 	if (fpid == 0) {
278482a4538fSEric Badger 		trace_me();
278582a4538fSEric Badger 		getpid();
278682a4538fSEric Badger 		exit(1);
278782a4538fSEric Badger 	}
278882a4538fSEric Badger 
278982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
279082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2791*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
279282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2793*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
279482a4538fSEric Badger 
279582a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
2796*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
279782a4538fSEric Badger 
279882a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
279982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2800*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
280182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2802*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
280382a4538fSEric Badger 
280482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
280582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
280682a4538fSEric Badger 
280782a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
2808*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
280982a4538fSEric Badger 
281082a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
281182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2812*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
281382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2814*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
281582a4538fSEric Badger 
281682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
281782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
281882a4538fSEric Badger 
281982a4538fSEric Badger 	/* Send an ABRT without ptrace. */
2820*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGABRT), 0);
282182a4538fSEric Badger 
282282a4538fSEric Badger 	/* Continue normally. */
2823*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
282482a4538fSEric Badger 
282582a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
282682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2827*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
282882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2829*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
283082a4538fSEric Badger 
283182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
283282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
2833*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
283482a4538fSEric Badger 
283582a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
2836*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
283782a4538fSEric Badger 
283882a4538fSEric Badger 	for (;;) {
283982a4538fSEric Badger 		/*
284082a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
284182a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
284282a4538fSEric Badger 		 * past any syscall stops.
284382a4538fSEric Badger 		 */
284482a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
2845*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
284682a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
284782a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
284882a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
2849*96a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
285082a4538fSEric Badger 		} else {
285182a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
2852*96a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
285382a4538fSEric Badger 			break;
285482a4538fSEric Badger 		}
285582a4538fSEric Badger 	}
285682a4538fSEric Badger 
285782a4538fSEric Badger 	wpid = wait(&status);
2858*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2859*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
286082a4538fSEric Badger }
286182a4538fSEric Badger 
286282a4538fSEric Badger /*
286382a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
286482a4538fSEric Badger  */
286582a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
286682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
286782a4538fSEric Badger {
286882a4538fSEric Badger 	pid_t fpid, wpid;
286982a4538fSEric Badger 	int status, kq, nevents;
287082a4538fSEric Badger 	struct kevent kev;
287182a4538fSEric Badger 
287282a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
287382a4538fSEric Badger 
287482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
287582a4538fSEric Badger 	if (fpid == 0) {
287682a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
287782a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
2878*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(kevent(kq, &kev, 1, NULL, 0, NULL), 0);
287982a4538fSEric Badger 
288082a4538fSEric Badger 		trace_me();
288182a4538fSEric Badger 
288282a4538fSEric Badger 		for (;;) {
288382a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
288482a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
288582a4538fSEric Badger 				continue;
288682a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
2887*96a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(kev.filter, EVFILT_SIGNAL);
2888*96a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(kev.ident, SIGUSR1);
288982a4538fSEric Badger 			break;
289082a4538fSEric Badger 		}
289182a4538fSEric Badger 
289282a4538fSEric Badger 		exit(1);
289382a4538fSEric Badger 	}
289482a4538fSEric Badger 
289582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
289682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2897*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
289882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2899*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
290082a4538fSEric Badger 
290182a4538fSEric Badger 	/* Continue with the SIGUSR1. */
2902*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
290382a4538fSEric Badger 
290482a4538fSEric Badger 	/*
290582a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
290682a4538fSEric Badger 	 */
290782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
2908*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
290982a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
2910*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
291182a4538fSEric Badger 
291282a4538fSEric Badger 	wpid = wait(&status);
2913*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
2914*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
291582a4538fSEric Badger }
291682a4538fSEric Badger 
291782a4538fSEric Badger static void *
291882a4538fSEric Badger signal_thread(void *arg)
291982a4538fSEric Badger {
292082a4538fSEric Badger 	int err;
292182a4538fSEric Badger 	sigset_t sigmask;
292282a4538fSEric Badger 
292382a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
292482a4538fSEric Badger 
292582a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
292682a4538fSEric Badger 	do {
292782a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
292882a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
292982a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
293082a4538fSEric Badger 
293182a4538fSEric Badger 	/* Free our companion thread from the barrier. */
293282a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
293382a4538fSEric Badger 
293482a4538fSEric Badger 	/*
293582a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
293682a4538fSEric Badger 	 * other thread.
293782a4538fSEric Badger 	 */
2938*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
2939*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
2940*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
294182a4538fSEric Badger 
294282a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
294382a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
294482a4538fSEric Badger 
294582a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
294682a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
294782a4538fSEric Badger 
294882a4538fSEric Badger 	return (NULL);
294982a4538fSEric Badger }
295082a4538fSEric Badger 
295182a4538fSEric Badger /*
2952753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2953753e2922SBryan Drewery  * signal from kill() once unmasked.
2954753e2922SBryan Drewery  */
2955753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
2956753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
2957753e2922SBryan Drewery {
2958753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2959753e2922SBryan Drewery 	pid_t fpid, wpid;
2960753e2922SBryan Drewery 	int status, err;
2961753e2922SBryan Drewery 	sigset_t sigmask;
2962753e2922SBryan Drewery 
2963*96a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
2964753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2965753e2922SBryan Drewery 	got_usr1 = 0;
2966753e2922SBryan Drewery 
2967753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2968753e2922SBryan Drewery 	if (fpid == 0) {
2969*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
2970*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
2971*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
2972753e2922SBryan Drewery 
2973753e2922SBryan Drewery 		trace_me();
2974*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
2975753e2922SBryan Drewery 
2976753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2977*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
2978753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2979753e2922SBryan Drewery 		do {
2980753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2981753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2982753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2983*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
2984753e2922SBryan Drewery 		exit(1);
2985753e2922SBryan Drewery 	}
2986753e2922SBryan Drewery 
2987753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2988753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2989*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2990753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2991*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
2992753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2993*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGSTOP);
2994753e2922SBryan Drewery 
2995753e2922SBryan Drewery 	/* Send blocked SIGUSR1 which should cause a stop. */
2996*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
2997753e2922SBryan Drewery 
2998753e2922SBryan Drewery 	/* Continue the child ignoring the SIGSTOP. */
2999*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3000753e2922SBryan Drewery 
3001753e2922SBryan Drewery 	/* The next wait() should report the kill(SIGUSR1) was received. */
3002753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3003*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3004753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
3005*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
3006753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
3007*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
3008753e2922SBryan Drewery 
3009753e2922SBryan Drewery 	/* Continue the child, allowing in the SIGUSR1. */
3010*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
3011753e2922SBryan Drewery 
3012753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3013753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3014*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3015753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
3016*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3017753e2922SBryan Drewery 
3018753e2922SBryan Drewery 	wpid = wait(&status);
3019*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3020*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3021753e2922SBryan Drewery }
3022753e2922SBryan Drewery 
3023753e2922SBryan Drewery /*
3024753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
3025753e2922SBryan Drewery  * signal from PT_CONTINUE once unmasked.
3026753e2922SBryan Drewery  */
3027753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
3028753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
3029753e2922SBryan Drewery {
3030753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
3031753e2922SBryan Drewery 	pid_t fpid, wpid;
3032753e2922SBryan Drewery 	int status, err;
3033753e2922SBryan Drewery 	sigset_t sigmask;
3034753e2922SBryan Drewery 
3035*96a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
3036753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
3037753e2922SBryan Drewery 	got_usr1 = 0;
3038753e2922SBryan Drewery 
3039753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
3040753e2922SBryan Drewery 	if (fpid == 0) {
3041*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
3042*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
3043*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
3044753e2922SBryan Drewery 
3045753e2922SBryan Drewery 		trace_me();
3046*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
3047753e2922SBryan Drewery 
3048753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
3049*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
3050753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
3051753e2922SBryan Drewery 		do {
3052753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
3053753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
3054753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
3055753e2922SBryan Drewery 
3056*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
3057753e2922SBryan Drewery 		exit(1);
3058753e2922SBryan Drewery 	}
3059753e2922SBryan Drewery 
3060753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
3061753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3062*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3063753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
3064*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3065753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
3066*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGSTOP);
3067753e2922SBryan Drewery 
3068753e2922SBryan Drewery 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
3069*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
3070753e2922SBryan Drewery 
3071753e2922SBryan Drewery 	/* The next wait() should report the SIGUSR1 was received. */
3072753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3073*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3074753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
3075*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
3076753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
3077*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
3078753e2922SBryan Drewery 
3079753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
3080*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3081753e2922SBryan Drewery 
3082753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3083753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3084*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3085753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
3086*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3087753e2922SBryan Drewery 
3088753e2922SBryan Drewery 	wpid = wait(&status);
3089*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3090*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3091753e2922SBryan Drewery }
3092753e2922SBryan Drewery 
3093753e2922SBryan Drewery /*
309482a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
309582a4538fSEric Badger  * a different signal that the new signal is routed to a thread
309699144520SEitan Adler  * that can accept it, and that the thread is awakened by the signal
309782a4538fSEric Badger  * in a timely manner.
309882a4538fSEric Badger  */
309982a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
310082a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
310182a4538fSEric Badger {
310282a4538fSEric Badger 	pid_t fpid, wpid;
310382a4538fSEric Badger 	int status, err;
310482a4538fSEric Badger 	pthread_t t;
310582a4538fSEric Badger 	sigset_t sigmask;
310682a4538fSEric Badger 	pthread_barrier_t barrier;
310782a4538fSEric Badger 
3108*96a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
3109*96a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
311082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
311182a4538fSEric Badger 
311282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
311382a4538fSEric Badger 	if (fpid == 0) {
3114*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_create(&t, NULL, signal_thread,
3115*96a9e50eSAlex Richardson 		    (void *)&barrier), 0);
311682a4538fSEric Badger 
311782a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
3118*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
3119*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
3120*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
312182a4538fSEric Badger 
312282a4538fSEric Badger 		trace_me();
312382a4538fSEric Badger 
312482a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
312582a4538fSEric Badger 		pthread_barrier_wait(&barrier);
312682a4538fSEric Badger 
312782a4538fSEric Badger 		/*
312882a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
312982a4538fSEric Badger 		 * thread.
313082a4538fSEric Badger 		 */
3131*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL),
3132*96a9e50eSAlex Richardson 		    0);
313382a4538fSEric Badger 
313482a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
313582a4538fSEric Badger 		pthread_barrier_wait(&barrier);
313682a4538fSEric Badger 
313782a4538fSEric Badger 		/*
313882a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
313982a4538fSEric Badger 		 * now.
314082a4538fSEric Badger 		 */
314182a4538fSEric Badger 		raise(SIGSTOP);
314282a4538fSEric Badger 
314382a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
314482a4538fSEric Badger 		do {
314582a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
314682a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
314782a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
314882a4538fSEric Badger 
314982a4538fSEric Badger 		/* Free the other thread from the barrier. */
315082a4538fSEric Badger 		pthread_barrier_wait(&barrier);
315182a4538fSEric Badger 
3152*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_join(t, NULL), 0);
315382a4538fSEric Badger 
315482a4538fSEric Badger 		exit(1);
315582a4538fSEric Badger 	}
315682a4538fSEric Badger 
315782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
315882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
3159*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
316082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3161*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
316282a4538fSEric Badger 
316382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
3164*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
316582a4538fSEric Badger 
316682a4538fSEric Badger 	/*
316782a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
316882a4538fSEric Badger 	 * in this case).
316982a4538fSEric Badger 	 */
3170*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
317182a4538fSEric Badger 
317282a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
317382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
3174*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
317582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3176*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
317782a4538fSEric Badger 
317882a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
3179*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
318082a4538fSEric Badger 
318182a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
318282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
3183*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
318482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3185*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
318682a4538fSEric Badger 
318782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
3188*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
318982a4538fSEric Badger 
3190*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
319182a4538fSEric Badger 
319282a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
319382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
3194*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
319582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3196*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
319782a4538fSEric Badger 
319882a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
3199*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
320082a4538fSEric Badger 
320182a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
320282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
3203*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
320482a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
3205*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
320682a4538fSEric Badger 
320782a4538fSEric Badger 	wpid = wait(&status);
3208*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3209*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
321082a4538fSEric Badger }
321182a4538fSEric Badger 
3212b38bd91fSEric Badger static void *
3213b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
3214b38bd91fSEric Badger {
3215b38bd91fSEric Badger 
3216b38bd91fSEric Badger 	raise(SIGSTOP);
3217b38bd91fSEric Badger 	return NULL;
3218b38bd91fSEric Badger }
3219b38bd91fSEric Badger 
3220b38bd91fSEric Badger static void *
3221b38bd91fSEric Badger sleep_thread(void *arg __unused)
3222b38bd91fSEric Badger {
3223b38bd91fSEric Badger 
3224b38bd91fSEric Badger 	sleep(60);
3225b38bd91fSEric Badger 	return NULL;
3226b38bd91fSEric Badger }
3227b38bd91fSEric Badger 
3228b38bd91fSEric Badger static void
3229b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
3230b38bd91fSEric Badger {
3231b38bd91fSEric Badger 	pid_t fpid, wpid;
3232b38bd91fSEric Badger 	int status, i;
3233b38bd91fSEric Badger 	cpuset_t setmask;
3234b38bd91fSEric Badger 	cpusetid_t setid;
3235b38bd91fSEric Badger 	pthread_t t;
3236b38bd91fSEric Badger 
3237b38bd91fSEric Badger 	/*
3238b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
3239b38bd91fSEric Badger 	 * that both child and grandchild have died.
3240b38bd91fSEric Badger 	 */
3241*96a9e50eSAlex Richardson 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
3242b38bd91fSEric Badger 
3243b38bd91fSEric Badger 	fpid = fork();
3244b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
3245b38bd91fSEric Badger 	if (fpid == 0) {
3246b38bd91fSEric Badger 		fpid = fork();
3247b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
3248b38bd91fSEric Badger 		if (fpid == 0) {
3249b38bd91fSEric Badger 			trace_me();
3250b38bd91fSEric Badger 
3251b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
3252b38bd91fSEric Badger 			CPU_ZERO(&setmask);
3253b38bd91fSEric Badger 			CPU_SET(0, &setmask);
3254*96a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(cpuset(&setid), 0);
3255b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
3256b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
3257b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
3258b38bd91fSEric Badger 
3259b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
3260b38bd91fSEric Badger 				/*
3261b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
3262b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
3263b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
3264b38bd91fSEric Badger 				 * threads compete.
3265b38bd91fSEric Badger 				 */
3266b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3267b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
3268b38bd91fSEric Badger 				raise(SIGSTOP);
3269b38bd91fSEric Badger 			} else {
3270b38bd91fSEric Badger 				/*
3271b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
3272b38bd91fSEric Badger 				 * this thread. After creating the new thread,
3273b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
3274b38bd91fSEric Badger 				 * raise the SIGSTOP.
3275b38bd91fSEric Badger 				 */
3276b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3277b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
3278b38bd91fSEric Badger 				sleep(60);
3279b38bd91fSEric Badger 			}
3280b38bd91fSEric Badger 
3281b38bd91fSEric Badger 			exit(0);
3282b38bd91fSEric Badger 		}
3283b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
3284b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3285*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, fpid);
3286b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3287*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3288b38bd91fSEric Badger 
3289*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3290b38bd91fSEric Badger 
3291b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
3292b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3293*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, fpid);
3294b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3295*96a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3296b38bd91fSEric Badger 
3297b38bd91fSEric Badger 		/*
3298b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
3299b38bd91fSEric Badger 		 * should be killed.
3300b38bd91fSEric Badger 		 */
3301b38bd91fSEric Badger 		exit(0);
3302b38bd91fSEric Badger 	}
3303b38bd91fSEric Badger 
3304b38bd91fSEric Badger 	/*
3305b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
3306b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
3307b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
3308b38bd91fSEric Badger 	 * left dangling when its parent died.
3309b38bd91fSEric Badger 	 */
3310b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
3311b38bd91fSEric Badger 		wpid = wait(&status);
3312*96a9e50eSAlex Richardson 		if (wpid == fpid) {
3313*96a9e50eSAlex Richardson 			ATF_REQUIRE(WIFEXITED(status));
3314*96a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 0);
3315*96a9e50eSAlex Richardson 		} else {
3316*96a9e50eSAlex Richardson 			ATF_REQUIRE(WIFSIGNALED(status));
3317*96a9e50eSAlex Richardson 			REQUIRE_EQ(WTERMSIG(status), SIGKILL);
3318*96a9e50eSAlex Richardson 		}
3319b38bd91fSEric Badger 	}
3320b38bd91fSEric Badger }
3321b38bd91fSEric Badger 
3322b38bd91fSEric Badger /*
3323b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
3324b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
3325b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
3326b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
3327b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
3328b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
3329b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
3330b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
3331b38bd91fSEric Badger  * past, so make no assumption.
3332b38bd91fSEric Badger  */
33333cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
33343cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
33353cf56bb4SEnji Cooper {
33363cf56bb4SEnji Cooper 
33373cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33383cf56bb4SEnji Cooper }
3339b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
3340b38bd91fSEric Badger {
3341b38bd91fSEric Badger 
3342b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
3343b38bd91fSEric Badger }
33443cf56bb4SEnji Cooper 
33453cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
33463cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
33473cf56bb4SEnji Cooper {
33483cf56bb4SEnji Cooper 
33493cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33503cf56bb4SEnji Cooper }
3351b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
3352b38bd91fSEric Badger {
3353b38bd91fSEric Badger 
3354b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
3355b38bd91fSEric Badger }
3356b38bd91fSEric Badger 
3357b4d33259SEric Badger /*
3358b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
3359b4d33259SEric Badger  * is not modified.
3360b4d33259SEric Badger  */
3361b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
3362b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
3363b4d33259SEric Badger {
3364b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
3365b4d33259SEric Badger 	pid_t fpid, wpid;
3366b4d33259SEric Badger 	int status, event_mask, new_event_mask;
3367b4d33259SEric Badger 
3368b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
3369b4d33259SEric Badger 	if (fpid == 0) {
3370b4d33259SEric Badger 		trace_me();
3371b4d33259SEric Badger 		raise(SIGSTOP);
3372b4d33259SEric Badger 		exit(0);
3373b4d33259SEric Badger 	}
3374b4d33259SEric Badger 
3375b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
3376b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3377*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3378b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3379*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3380b4d33259SEric Badger 
3381b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
3382b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
3383b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
3384b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
3385b4d33259SEric Badger 
3386b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
3387*96a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGKILL), 0);
3388b4d33259SEric Badger 
3389b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
3390*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3391b4d33259SEric Badger 
3392b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
3393b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3394*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3395b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3396*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGKILL);
3397b4d33259SEric Badger 
3398b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3399b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3400*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGKILL);
3401b4d33259SEric Badger 
3402b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
3403*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3404b4d33259SEric Badger 
3405b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
3406b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3407*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3408b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3409*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3410b4d33259SEric Badger 
3411b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
3412b4d33259SEric Badger 	new_event_mask = 0;
3413b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
3414b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
3415*96a9e50eSAlex Richardson 	REQUIRE_EQ(event_mask, new_event_mask);
3416b4d33259SEric Badger 
3417b4d33259SEric Badger 	/* Continue the child to let it exit. */
3418*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3419b4d33259SEric Badger 
3420b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
3421b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3422b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
3423*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
3424b4d33259SEric Badger 
3425b4d33259SEric Badger 	wpid = wait(&status);
3426*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3427*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3428b4d33259SEric Badger }
3429b4d33259SEric Badger 
3430d74da94cSMark Johnston static void *
3431d74da94cSMark Johnston flock_thread(void *arg)
3432d74da94cSMark Johnston {
3433d74da94cSMark Johnston 	int fd;
3434d74da94cSMark Johnston 
3435d74da94cSMark Johnston 	fd = *(int *)arg;
3436d74da94cSMark Johnston 	(void)flock(fd, LOCK_EX);
3437d74da94cSMark Johnston 	(void)flock(fd, LOCK_UN);
3438d74da94cSMark Johnston 	return (NULL);
3439d74da94cSMark Johnston }
3440d74da94cSMark Johnston 
3441d74da94cSMark Johnston /*
3442d74da94cSMark Johnston  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
3443d74da94cSMark Johnston  * We rely on the fact that the lockf implementation sets SBDRY before blocking
3444d74da94cSMark Johnston  * on a lock. This is a regression test for r318191.
3445d74da94cSMark Johnston  */
3446d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
3447d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
3448d74da94cSMark Johnston {
3449d74da94cSMark Johnston 	pthread_barrier_t barrier;
3450d74da94cSMark Johnston 	pthread_barrierattr_t battr;
3451d74da94cSMark Johnston 	char tmpfile[64];
3452d74da94cSMark Johnston 	pid_t child, wpid;
3453d74da94cSMark Johnston 	int error, fd, i, status;
3454d74da94cSMark Johnston 
3455*96a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrierattr_init(&battr), 0);
3456d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
3457d74da94cSMark Johnston 	    PTHREAD_PROCESS_SHARED) == 0);
3458*96a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrier_init(&barrier, &battr, 2), 0);
3459d74da94cSMark Johnston 
3460d74da94cSMark Johnston 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
3461d74da94cSMark Johnston 	fd = mkstemp(tmpfile);
3462d74da94cSMark Johnston 	ATF_REQUIRE(fd >= 0);
3463d74da94cSMark Johnston 
3464d74da94cSMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
3465d74da94cSMark Johnston 	if (child == 0) {
3466d74da94cSMark Johnston 		pthread_t t[2];
346796437391SBryan Drewery 		int cfd;
3468d74da94cSMark Johnston 
3469d74da94cSMark Johnston 		error = pthread_barrier_wait(&barrier);
3470d74da94cSMark Johnston 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
3471d74da94cSMark Johnston 			_exit(1);
3472d74da94cSMark Johnston 
3473d74da94cSMark Johnston 		cfd = open(tmpfile, O_RDONLY);
3474d74da94cSMark Johnston 		if (cfd < 0)
3475d74da94cSMark Johnston 			_exit(1);
3476d74da94cSMark Johnston 
3477d74da94cSMark Johnston 		/*
3478d74da94cSMark Johnston 		 * We want at least two threads blocked on the file lock since
3479d74da94cSMark Johnston 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
3480d74da94cSMark Johnston 		 * sleep.
3481d74da94cSMark Johnston 		 */
3482d74da94cSMark Johnston 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
3483d74da94cSMark Johnston 			_exit(1);
3484d74da94cSMark Johnston 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
3485d74da94cSMark Johnston 			_exit(1);
3486d74da94cSMark Johnston 		if (pthread_join(t[0], NULL) != 0)
3487d74da94cSMark Johnston 			_exit(1);
3488d74da94cSMark Johnston 		if (pthread_join(t[1], NULL) != 0)
3489d74da94cSMark Johnston 			_exit(1);
3490d74da94cSMark Johnston 		_exit(0);
3491d74da94cSMark Johnston 	}
3492d74da94cSMark Johnston 
3493*96a9e50eSAlex Richardson 	REQUIRE_EQ(flock(fd, LOCK_EX), 0);
3494d74da94cSMark Johnston 
3495d74da94cSMark Johnston 	error = pthread_barrier_wait(&barrier);
3496d74da94cSMark Johnston 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
3497d74da94cSMark Johnston 
3498d74da94cSMark Johnston 	/*
3499d74da94cSMark Johnston 	 * Give the child some time to block. Is there a better way to do this?
3500d74da94cSMark Johnston 	 */
3501d74da94cSMark Johnston 	sleep(1);
3502d74da94cSMark Johnston 
3503d74da94cSMark Johnston 	/*
3504d74da94cSMark Johnston 	 * Attach and give the child 3 seconds to stop.
3505d74da94cSMark Johnston 	 */
3506*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, child, NULL, 0), 0);
3507d74da94cSMark Johnston 	for (i = 0; i < 3; i++) {
3508d74da94cSMark Johnston 		wpid = waitpid(child, &status, WNOHANG);
3509d74da94cSMark Johnston 		if (wpid == child && WIFSTOPPED(status) &&
3510d74da94cSMark Johnston 		    WSTOPSIG(status) == SIGSTOP)
3511d74da94cSMark Johnston 			break;
3512d74da94cSMark Johnston 		sleep(1);
3513d74da94cSMark Johnston 	}
3514d74da94cSMark Johnston 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
3515d74da94cSMark Johnston 
3516*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_DETACH, child, NULL, 0), 0);
3517d74da94cSMark Johnston 
3518*96a9e50eSAlex Richardson 	REQUIRE_EQ(flock(fd, LOCK_UN), 0);
3519*96a9e50eSAlex Richardson 	REQUIRE_EQ(unlink(tmpfile), 0);
3520*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(fd), 0);
3521d74da94cSMark Johnston }
3522d74da94cSMark Johnston 
352354cfb29eSJohn Baldwin static void
352454cfb29eSJohn Baldwin sigusr1_step_handler(int sig)
352554cfb29eSJohn Baldwin {
352654cfb29eSJohn Baldwin 
3527*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
352854cfb29eSJohn Baldwin 	raise(SIGABRT);
352954cfb29eSJohn Baldwin }
353054cfb29eSJohn Baldwin 
353154cfb29eSJohn Baldwin /*
353254cfb29eSJohn Baldwin  * Verify that PT_STEP with a signal invokes the signal before
353354cfb29eSJohn Baldwin  * stepping the next instruction (and that the next instruction is
353454cfb29eSJohn Baldwin  * stepped correctly).
353554cfb29eSJohn Baldwin  */
353654cfb29eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal);
353754cfb29eSJohn Baldwin ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
353854cfb29eSJohn Baldwin {
353954cfb29eSJohn Baldwin 	struct ptrace_lwpinfo pl;
354054cfb29eSJohn Baldwin 	pid_t fpid, wpid;
354154cfb29eSJohn Baldwin 	int status;
354254cfb29eSJohn Baldwin 
354354cfb29eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
354454cfb29eSJohn Baldwin 	if (fpid == 0) {
354554cfb29eSJohn Baldwin 		trace_me();
354654cfb29eSJohn Baldwin 		signal(SIGUSR1, sigusr1_step_handler);
354754cfb29eSJohn Baldwin 		raise(SIGABRT);
354854cfb29eSJohn Baldwin 		exit(1);
354954cfb29eSJohn Baldwin 	}
355054cfb29eSJohn Baldwin 
355154cfb29eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
355254cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3553*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
355454cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3555*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
355654cfb29eSJohn Baldwin 
3557*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
355854cfb29eSJohn Baldwin 
355954cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
356054cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3561*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
356254cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3563*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
356454cfb29eSJohn Baldwin 
356554cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
356654cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3567*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
356854cfb29eSJohn Baldwin 
356954cfb29eSJohn Baldwin 	/* Step the child process inserting SIGUSR1. */
3570*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1), 0);
357154cfb29eSJohn Baldwin 
357254cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the signal handler. */
357354cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3574*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
357554cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3576*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
357754cfb29eSJohn Baldwin 
357854cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
357954cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3580*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
358154cfb29eSJohn Baldwin 
358254cfb29eSJohn Baldwin 	/* Continue the child process discarding the signal. */
3583*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
358454cfb29eSJohn Baldwin 
358554cfb29eSJohn Baldwin 	/* The next stop should report a trace trap from PT_STEP. */
358654cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3587*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
358854cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3589*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
359054cfb29eSJohn Baldwin 
359154cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
359254cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3593*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
3594*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_TRACE);
359554cfb29eSJohn Baldwin 
359654cfb29eSJohn Baldwin 	/* Continue the child to let it exit. */
3597*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
359854cfb29eSJohn Baldwin 
359954cfb29eSJohn Baldwin 	/* The last event should be for the child process's exit. */
360054cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
360154cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3602*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
360354cfb29eSJohn Baldwin 
360454cfb29eSJohn Baldwin 	wpid = wait(&status);
3605*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3606*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
360754cfb29eSJohn Baldwin }
360854cfb29eSJohn Baldwin 
3609643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3610643ce7deSJohn Baldwin /*
3611643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported
3612643ce7deSJohn Baldwin  * for a breakpoint trap.
3613643ce7deSJohn Baldwin  */
3614643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo);
3615643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__breakpoint_siginfo, tc)
3616643ce7deSJohn Baldwin {
3617643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3618643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3619643ce7deSJohn Baldwin 	int status;
3620643ce7deSJohn Baldwin 
3621643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3622643ce7deSJohn Baldwin 	if (fpid == 0) {
3623643ce7deSJohn Baldwin 		trace_me();
3624643ce7deSJohn Baldwin 		breakpoint();
3625643ce7deSJohn Baldwin 		exit(1);
3626643ce7deSJohn Baldwin 	}
3627643ce7deSJohn Baldwin 
3628643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3629643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3630*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3631643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3632*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3633643ce7deSJohn Baldwin 
3634643ce7deSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
3635*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3636643ce7deSJohn Baldwin 
3637643ce7deSJohn Baldwin 	/* The second wait() should report hitting the breakpoint. */
3638643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3639*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3640643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3641*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3642643ce7deSJohn Baldwin 
3643643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3644643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3645*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
3646*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3647643ce7deSJohn Baldwin 
3648643ce7deSJohn Baldwin 	/* Kill the child process. */
3649*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
3650643ce7deSJohn Baldwin 
3651643ce7deSJohn Baldwin 	/* The last wait() should report the SIGKILL. */
3652643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3653*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3654643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSIGNALED(status));
3655*96a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
3656643ce7deSJohn Baldwin 
3657643ce7deSJohn Baldwin 	wpid = wait(&status);
3658*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3659*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3660643ce7deSJohn Baldwin }
3661643ce7deSJohn Baldwin #endif /* HAVE_BREAKPOINT */
3662643ce7deSJohn Baldwin 
3663643ce7deSJohn Baldwin /*
3664643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_TRACE code is reported
3665643ce7deSJohn Baldwin  * for a single-step trap from PT_STEP.
3666643ce7deSJohn Baldwin  */
3667643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo);
3668643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__step_siginfo, tc)
3669643ce7deSJohn Baldwin {
3670643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3671643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3672643ce7deSJohn Baldwin 	int status;
3673643ce7deSJohn Baldwin 
3674643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3675643ce7deSJohn Baldwin 	if (fpid == 0) {
3676643ce7deSJohn Baldwin 		trace_me();
3677643ce7deSJohn Baldwin 		exit(1);
3678643ce7deSJohn Baldwin 	}
3679643ce7deSJohn Baldwin 
3680643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3681643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3682*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3683643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3684*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3685643ce7deSJohn Baldwin 
3686643ce7deSJohn Baldwin 	/* Step the child ignoring the SIGSTOP. */
3687*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, 0), 0);
3688643ce7deSJohn Baldwin 
3689643ce7deSJohn Baldwin 	/* The second wait() should report a single-step trap. */
3690643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3691*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3692643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3693*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3694643ce7deSJohn Baldwin 
3695643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3696643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3697*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
3698*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_TRACE);
3699643ce7deSJohn Baldwin 
3700643ce7deSJohn Baldwin 	/* Continue the child process. */
3701*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3702643ce7deSJohn Baldwin 
3703643ce7deSJohn Baldwin 	/* The last event should be for the child process's exit. */
3704643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3705643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3706*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3707643ce7deSJohn Baldwin 
3708643ce7deSJohn Baldwin 	wpid = wait(&status);
3709*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3710*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3711643ce7deSJohn Baldwin }
3712643ce7deSJohn Baldwin 
3713403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3714e012fe34SJohn Baldwin static void *
3715e0a40f30SJohn Baldwin continue_thread(void *arg __unused)
3716e012fe34SJohn Baldwin {
3717e012fe34SJohn Baldwin 	breakpoint();
3718e012fe34SJohn Baldwin 	return (NULL);
3719e012fe34SJohn Baldwin }
3720e012fe34SJohn Baldwin 
3721e012fe34SJohn Baldwin static __dead2 void
3722e012fe34SJohn Baldwin continue_thread_main(void)
3723e012fe34SJohn Baldwin {
3724e012fe34SJohn Baldwin 	pthread_t threads[2];
3725e012fe34SJohn Baldwin 
3726e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
3727e012fe34SJohn Baldwin 	    NULL) == 0);
3728e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
3729e012fe34SJohn Baldwin 	    NULL) == 0);
3730*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(threads[0], NULL), 0);
3731*96a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(threads[1], NULL), 0);
3732e012fe34SJohn Baldwin 	exit(1);
3733e012fe34SJohn Baldwin }
3734e012fe34SJohn Baldwin 
3735e012fe34SJohn Baldwin /*
3736e012fe34SJohn Baldwin  * Ensure that PT_CONTINUE clears the status of the thread that
3737e012fe34SJohn Baldwin  * triggered the stop even if a different thread's LWP was passed to
3738e012fe34SJohn Baldwin  * PT_CONTINUE.
3739e012fe34SJohn Baldwin  */
3740e012fe34SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
3741e012fe34SJohn Baldwin ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
3742e012fe34SJohn Baldwin {
3743e012fe34SJohn Baldwin 	struct ptrace_lwpinfo pl;
3744e012fe34SJohn Baldwin 	pid_t fpid, wpid;
3745e012fe34SJohn Baldwin 	lwpid_t lwps[2];
3746e012fe34SJohn Baldwin 	bool hit_break[2];
3747403e331dSJohn Baldwin 	struct reg reg;
3748e012fe34SJohn Baldwin 	int i, j, status;
3749e012fe34SJohn Baldwin 
3750e012fe34SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3751e012fe34SJohn Baldwin 	if (fpid == 0) {
3752e012fe34SJohn Baldwin 		trace_me();
3753e012fe34SJohn Baldwin 		continue_thread_main();
3754e012fe34SJohn Baldwin 	}
3755e012fe34SJohn Baldwin 
3756e012fe34SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3757e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3758*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3759e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3760*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3761e012fe34SJohn Baldwin 
3762e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3763e012fe34SJohn Baldwin 	    sizeof(pl)) != -1);
3764e012fe34SJohn Baldwin 
3765*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
3766e012fe34SJohn Baldwin 
3767e012fe34SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
3768*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3769e012fe34SJohn Baldwin 
3770e012fe34SJohn Baldwin 	/* One of the new threads should report it's birth. */
3771e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3772*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3773e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3774*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3775e012fe34SJohn Baldwin 
3776e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3777*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
3778e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3779e012fe34SJohn Baldwin 	lwps[0] = pl.pl_lwpid;
3780e012fe34SJohn Baldwin 
3781e012fe34SJohn Baldwin 	/*
3782e012fe34SJohn Baldwin 	 * Suspend this thread to ensure both threads are alive before
3783e012fe34SJohn Baldwin 	 * hitting the breakpoint.
3784e012fe34SJohn Baldwin 	 */
3785e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
3786e012fe34SJohn Baldwin 
3787*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3788e012fe34SJohn Baldwin 
3789e012fe34SJohn Baldwin 	/* Second thread should report it's birth. */
3790e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3791*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3792e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3793*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3794e012fe34SJohn Baldwin 
3795e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3796*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
3797e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3798e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
3799e012fe34SJohn Baldwin 	lwps[1] = pl.pl_lwpid;
3800e012fe34SJohn Baldwin 
3801e012fe34SJohn Baldwin 	/* Resume both threads waiting for breakpoint events. */
3802e012fe34SJohn Baldwin 	hit_break[0] = hit_break[1] = false;
3803e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
3804*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3805e012fe34SJohn Baldwin 
3806e012fe34SJohn Baldwin 	/* One thread should report a breakpoint. */
3807e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3808*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3809e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3810*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3811e012fe34SJohn Baldwin 
3812e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3813e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3814*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
3815*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3816e012fe34SJohn Baldwin 	if (pl.pl_lwpid == lwps[0])
3817e012fe34SJohn Baldwin 		i = 0;
3818e012fe34SJohn Baldwin 	else
3819e012fe34SJohn Baldwin 		i = 1;
3820e012fe34SJohn Baldwin 	hit_break[i] = true;
3821403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3822403e331dSJohn Baldwin 	SKIP_BREAK(&reg);
3823403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3824e012fe34SJohn Baldwin 
3825e012fe34SJohn Baldwin 	/*
3826e012fe34SJohn Baldwin 	 * Resume both threads but pass the other thread's LWPID to
3827e012fe34SJohn Baldwin 	 * PT_CONTINUE.
3828e012fe34SJohn Baldwin 	 */
3829*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0), 0);
3830e012fe34SJohn Baldwin 
3831e012fe34SJohn Baldwin 	/*
3832e012fe34SJohn Baldwin 	 * Will now get two thread exit events and one more breakpoint
3833e012fe34SJohn Baldwin 	 * event.
3834e012fe34SJohn Baldwin 	 */
3835e012fe34SJohn Baldwin 	for (j = 0; j < 3; j++) {
3836e012fe34SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
3837*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
3838e012fe34SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
3839*96a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3840e012fe34SJohn Baldwin 
3841e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3842e012fe34SJohn Baldwin 		    sizeof(pl)) != -1);
3843e012fe34SJohn Baldwin 
3844e012fe34SJohn Baldwin 		if (pl.pl_lwpid == lwps[0])
3845e012fe34SJohn Baldwin 			i = 0;
3846e012fe34SJohn Baldwin 		else
3847e012fe34SJohn Baldwin 			i = 1;
3848e012fe34SJohn Baldwin 
3849e012fe34SJohn Baldwin 		ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
3850e012fe34SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_EXITED) {
3851e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(hit_break[i],
3852e012fe34SJohn Baldwin 			    "exited thread did not report breakpoint");
3853e012fe34SJohn Baldwin 			lwps[i] = 0;
3854e012fe34SJohn Baldwin 		} else {
3855e012fe34SJohn Baldwin 			ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3856*96a9e50eSAlex Richardson 			REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
3857*96a9e50eSAlex Richardson 			REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3858e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(!hit_break[i],
3859e012fe34SJohn Baldwin 			    "double breakpoint event");
3860e012fe34SJohn Baldwin 			hit_break[i] = true;
3861403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
3862403e331dSJohn Baldwin 			    0) != -1);
3863403e331dSJohn Baldwin 			SKIP_BREAK(&reg);
3864403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
3865403e331dSJohn Baldwin 			    0) != -1);
3866e012fe34SJohn Baldwin 		}
3867e012fe34SJohn Baldwin 
3868*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3869e012fe34SJohn Baldwin 	}
3870e012fe34SJohn Baldwin 
3871e012fe34SJohn Baldwin 	/* Both threads should have exited. */
3872*96a9e50eSAlex Richardson 	REQUIRE_EQ(lwps[0], 0);
3873*96a9e50eSAlex Richardson 	REQUIRE_EQ(lwps[1], 0);
3874e012fe34SJohn Baldwin 
3875e012fe34SJohn Baldwin 	/* The last event should be for the child process's exit. */
3876e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3877e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3878*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3879e012fe34SJohn Baldwin 
3880e012fe34SJohn Baldwin 	wpid = wait(&status);
3881*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3882*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3883e012fe34SJohn Baldwin }
3884e012fe34SJohn Baldwin #endif
3885e012fe34SJohn Baldwin 
3886c5786670SJohn Baldwin /*
3887c5786670SJohn Baldwin  * Verify that PT_LWPINFO doesn't return stale siginfo.
3888c5786670SJohn Baldwin  */
3889c5786670SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_LWPINFO_stale_siginfo);
3890c5786670SJohn Baldwin ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo, tc)
3891c5786670SJohn Baldwin {
3892c5786670SJohn Baldwin 	struct ptrace_lwpinfo pl;
3893c5786670SJohn Baldwin 	pid_t fpid, wpid;
3894c5786670SJohn Baldwin 	int events, status;
3895c5786670SJohn Baldwin 
3896c5786670SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3897c5786670SJohn Baldwin 	if (fpid == 0) {
3898c5786670SJohn Baldwin 		trace_me();
3899c5786670SJohn Baldwin 		raise(SIGABRT);
3900c5786670SJohn Baldwin 		exit(1);
3901c5786670SJohn Baldwin 	}
3902c5786670SJohn Baldwin 
3903c5786670SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3904c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3905*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3906c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3907*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3908c5786670SJohn Baldwin 
3909*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3910c5786670SJohn Baldwin 
3911c5786670SJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
3912c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3913*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3914c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3915*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
3916c5786670SJohn Baldwin 
3917c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3918c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3919*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
3920c5786670SJohn Baldwin 
3921c5786670SJohn Baldwin 	/*
3922c5786670SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
3923c5786670SJohn Baldwin 	 * syscall traps.
3924c5786670SJohn Baldwin 	 */
3925*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
3926c5786670SJohn Baldwin 
3927c5786670SJohn Baldwin 	/*
3928c5786670SJohn Baldwin 	 * The next stop should report a system call entry from
3929c5786670SJohn Baldwin 	 * exit().  PL_FLAGS_SI should not be set.
3930c5786670SJohn Baldwin 	 */
3931c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3932*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3933c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3934*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3935c5786670SJohn Baldwin 
3936c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3937c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
3938*96a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & PL_FLAG_SI), 0);
3939c5786670SJohn Baldwin 
3940c5786670SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
3941c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
3942c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3943c5786670SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
3944c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
3945c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3946*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3947c5786670SJohn Baldwin 
3948c5786670SJohn Baldwin 	/* The last event should be for the child process's exit. */
3949c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3950c5786670SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3951*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3952c5786670SJohn Baldwin 
3953c5786670SJohn Baldwin 	wpid = wait(&status);
3954*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
3955*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3956c5786670SJohn Baldwin }
3957c5786670SJohn Baldwin 
3958c8ea8731SJohn Baldwin /*
395932451fb9SJohn Baldwin  * A simple test of PT_GET_SC_ARGS and PT_GET_SC_RET.
3960c8ea8731SJohn Baldwin  */
3961c8ea8731SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__syscall_args);
3962c8ea8731SJohn Baldwin ATF_TC_BODY(ptrace__syscall_args, tc)
3963c8ea8731SJohn Baldwin {
3964c8ea8731SJohn Baldwin 	struct ptrace_lwpinfo pl;
396532451fb9SJohn Baldwin 	struct ptrace_sc_ret psr;
3966c8ea8731SJohn Baldwin 	pid_t fpid, wpid;
3967c8ea8731SJohn Baldwin 	register_t args[2];
3968c8ea8731SJohn Baldwin 	int events, status;
3969c8ea8731SJohn Baldwin 
3970c8ea8731SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3971c8ea8731SJohn Baldwin 	if (fpid == 0) {
3972c8ea8731SJohn Baldwin 		trace_me();
3973c8ea8731SJohn Baldwin 		kill(getpid(), 0);
397432451fb9SJohn Baldwin 		close(3);
3975c8ea8731SJohn Baldwin 		exit(1);
3976c8ea8731SJohn Baldwin 	}
3977c8ea8731SJohn Baldwin 
3978c8ea8731SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3979c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3980*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3981c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3982*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3983c8ea8731SJohn Baldwin 
3984c8ea8731SJohn Baldwin 	/*
3985c8ea8731SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
398632451fb9SJohn Baldwin 	 * syscall traps.
3987c8ea8731SJohn Baldwin 	 */
3988*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
3989c8ea8731SJohn Baldwin 
3990c8ea8731SJohn Baldwin 	/*
3991c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from getpid().
3992c8ea8731SJohn Baldwin 	 */
3993c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3994*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3995c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3996*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3997c8ea8731SJohn Baldwin 
3998c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3999c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
4000*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, SYS_getpid);
4001c8ea8731SJohn Baldwin 
4002*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
4003c8ea8731SJohn Baldwin 
4004c8ea8731SJohn Baldwin 	/*
400532451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from getpid().
400632451fb9SJohn Baldwin 	 */
400732451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4008*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
400932451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
4010*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
401132451fb9SJohn Baldwin 
401232451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
401332451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
4014*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, SYS_getpid);
401532451fb9SJohn Baldwin 
401632451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
401732451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
4018*96a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, 0);
4019*96a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_retval[0], wpid);
402032451fb9SJohn Baldwin 
4021*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
402232451fb9SJohn Baldwin 
402332451fb9SJohn Baldwin 	/*
4024c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from kill().
4025c8ea8731SJohn Baldwin 	 */
4026c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4027*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
4028c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
4029*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
4030c8ea8731SJohn Baldwin 
4031c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
4032c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
4033*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, SYS_kill);
4034*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_narg, 2);
4035c8ea8731SJohn Baldwin 
4036c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
4037c8ea8731SJohn Baldwin 	    sizeof(args)) != -1);
4038*96a9e50eSAlex Richardson 	REQUIRE_EQ(args[0], wpid);
4039*96a9e50eSAlex Richardson 	REQUIRE_EQ(args[1], 0);
4040c8ea8731SJohn Baldwin 
4041*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
404232451fb9SJohn Baldwin 
404332451fb9SJohn Baldwin 	/*
404432451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from kill().
404532451fb9SJohn Baldwin 	 */
404632451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4047*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
404832451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
4049*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
405032451fb9SJohn Baldwin 
405132451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
405232451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
4053*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, SYS_kill);
405432451fb9SJohn Baldwin 
405532451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
405632451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
4057*96a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, 0);
405832451fb9SJohn Baldwin 
4059*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
406032451fb9SJohn Baldwin 
406132451fb9SJohn Baldwin 	/*
406232451fb9SJohn Baldwin 	 * The next stop should be the syscall entry from close().
406332451fb9SJohn Baldwin 	 */
406432451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4065*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
406632451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
4067*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
406832451fb9SJohn Baldwin 
406932451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
407032451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
4071*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, SYS_close);
4072*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_narg, 1);
407332451fb9SJohn Baldwin 
407432451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
407532451fb9SJohn Baldwin 	    sizeof(args)) != -1);
4076*96a9e50eSAlex Richardson 	REQUIRE_EQ(args[0], 3);
407732451fb9SJohn Baldwin 
4078*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
407932451fb9SJohn Baldwin 
408032451fb9SJohn Baldwin 	/*
408132451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from close().
408232451fb9SJohn Baldwin 	 */
408332451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4084*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
408532451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
4086*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
408732451fb9SJohn Baldwin 
408832451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
408932451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
4090*96a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, SYS_close);
409132451fb9SJohn Baldwin 
409232451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
409332451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
4094*96a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, EBADF);
409532451fb9SJohn Baldwin 
4096c8ea8731SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
4097c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
4098c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
4099c8ea8731SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
4100c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
4101c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
4102*96a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
4103c8ea8731SJohn Baldwin 
4104c8ea8731SJohn Baldwin 	/* The last event should be for the child process's exit. */
4105c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4106c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
4107*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
4108c8ea8731SJohn Baldwin 
4109c8ea8731SJohn Baldwin 	wpid = wait(&status);
4110*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
4111*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4112c8ea8731SJohn Baldwin }
4113c8ea8731SJohn Baldwin 
4114fd631bcdSMariusz Zaborski /*
4115fd631bcdSMariusz Zaborski  * Verify that when the process is traced that it isn't reparent
4116fd631bcdSMariusz Zaborski  * to the init process when we close all process descriptors.
4117fd631bcdSMariusz Zaborski  */
4118fd631bcdSMariusz Zaborski ATF_TC(ptrace__proc_reparent);
4119fd631bcdSMariusz Zaborski ATF_TC_HEAD(ptrace__proc_reparent, tc)
4120fd631bcdSMariusz Zaborski {
4121fd631bcdSMariusz Zaborski 
4122fd631bcdSMariusz Zaborski 	atf_tc_set_md_var(tc, "timeout", "2");
4123fd631bcdSMariusz Zaborski }
4124fd631bcdSMariusz Zaborski ATF_TC_BODY(ptrace__proc_reparent, tc)
4125fd631bcdSMariusz Zaborski {
4126fd631bcdSMariusz Zaborski 	pid_t traced, debuger, wpid;
4127fd631bcdSMariusz Zaborski 	int pd, status;
4128fd631bcdSMariusz Zaborski 
4129fd631bcdSMariusz Zaborski 	traced = pdfork(&pd, 0);
4130fd631bcdSMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
4131fd631bcdSMariusz Zaborski 	if (traced == 0) {
4132fd631bcdSMariusz Zaborski 		raise(SIGSTOP);
4133fd631bcdSMariusz Zaborski 		exit(0);
4134fd631bcdSMariusz Zaborski 	}
4135fd631bcdSMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
4136fd631bcdSMariusz Zaborski 
4137fd631bcdSMariusz Zaborski 	debuger = fork();
4138fd631bcdSMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
4139fd631bcdSMariusz Zaborski 	if (debuger == 0) {
4140fd631bcdSMariusz Zaborski 		/* The traced process is reparented to debuger. */
4141*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_ATTACH, traced, 0, 0), 0);
4142fd631bcdSMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
4143*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
4144fd631bcdSMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
4145*96a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
4146*96a9e50eSAlex Richardson 		REQUIRE_EQ(close(pd), 0);
4147*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_DETACH, traced, (caddr_t)1, 0), 0);
4148fd631bcdSMariusz Zaborski 
4149fd631bcdSMariusz Zaborski 		/* We closed pd so we should not have any child. */
4150fd631bcdSMariusz Zaborski 		wpid = wait(&status);
4151*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, -1);
4152*96a9e50eSAlex Richardson 		REQUIRE_EQ(errno, ECHILD);
4153fd631bcdSMariusz Zaborski 
4154fd631bcdSMariusz Zaborski 		exit(0);
4155fd631bcdSMariusz Zaborski 	}
4156fd631bcdSMariusz Zaborski 
4157*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(pd), 0);
4158fd631bcdSMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
4159*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debuger);
4160*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
4161fd631bcdSMariusz Zaborski 
4162fd631bcdSMariusz Zaborski 	/* Check if we still have any child. */
4163fd631bcdSMariusz Zaborski 	wpid = wait(&status);
4164*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
4165*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4166fd631bcdSMariusz Zaborski }
4167fd631bcdSMariusz Zaborski 
41688e493611SMariusz Zaborski /*
41698e493611SMariusz Zaborski  * Ensure that traced processes created with pdfork(2) are visible to
41708e493611SMariusz Zaborski  * waitid(P_ALL).
41718e493611SMariusz Zaborski  */
41728e493611SMariusz Zaborski ATF_TC_WITHOUT_HEAD(ptrace__procdesc_wait_child);
41738e493611SMariusz Zaborski ATF_TC_BODY(ptrace__procdesc_wait_child, tc)
41748e493611SMariusz Zaborski {
41758e493611SMariusz Zaborski 	pid_t child, wpid;
41768e493611SMariusz Zaborski 	int pd, status;
41778e493611SMariusz Zaborski 
41788e493611SMariusz Zaborski 	child = pdfork(&pd, 0);
41798e493611SMariusz Zaborski 	ATF_REQUIRE(child >= 0);
41808e493611SMariusz Zaborski 
41818e493611SMariusz Zaborski 	if (child == 0) {
41828e493611SMariusz Zaborski 		trace_me();
41838e493611SMariusz Zaborski 		(void)raise(SIGSTOP);
41848e493611SMariusz Zaborski 		exit(0);
41858e493611SMariusz Zaborski 	}
41868e493611SMariusz Zaborski 
41878e493611SMariusz Zaborski 	wpid = waitpid(child, &status, 0);
4188*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
41898e493611SMariusz Zaborski 	ATF_REQUIRE(WIFSTOPPED(status));
4190*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
41918e493611SMariusz Zaborski 
41928e493611SMariusz Zaborski 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
41938e493611SMariusz Zaborski 
41948e493611SMariusz Zaborski 	wpid = wait(&status);
4195*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
41968e493611SMariusz Zaborski 	ATF_REQUIRE(WIFSTOPPED(status));
4197*96a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
41988e493611SMariusz Zaborski 
41998e493611SMariusz Zaborski 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
42008e493611SMariusz Zaborski 
42018e493611SMariusz Zaborski 	/*
42028e493611SMariusz Zaborski 	 * If process was created by pdfork, the return code have to
42038e493611SMariusz Zaborski 	 * be collected through process descriptor.
42048e493611SMariusz Zaborski 	 */
42058e493611SMariusz Zaborski 	wpid = wait(&status);
4206*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
4207*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
42088e493611SMariusz Zaborski 
42098e493611SMariusz Zaborski 	ATF_REQUIRE(close(pd) != -1);
42108e493611SMariusz Zaborski }
42118e493611SMariusz Zaborski 
42128e493611SMariusz Zaborski /*
42138e493611SMariusz Zaborski  * Ensure that traced processes created with pdfork(2) are not visible
42148e493611SMariusz Zaborski  * after returning to parent - waitid(P_ALL).
42158e493611SMariusz Zaborski  */
42168e493611SMariusz Zaborski ATF_TC_WITHOUT_HEAD(ptrace__procdesc_reparent_wait_child);
42178e493611SMariusz Zaborski ATF_TC_BODY(ptrace__procdesc_reparent_wait_child, tc)
42188e493611SMariusz Zaborski {
42198e493611SMariusz Zaborski 	pid_t traced, debuger, wpid;
42208e493611SMariusz Zaborski 	int pd, status;
42218e493611SMariusz Zaborski 
4222fba0af0bSLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
4223fba0af0bSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/243605");
4224fba0af0bSLi-Wen Hsu 
42258e493611SMariusz Zaborski 	traced = pdfork(&pd, 0);
42268e493611SMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
42278e493611SMariusz Zaborski 	if (traced == 0) {
42288e493611SMariusz Zaborski 		raise(SIGSTOP);
42298e493611SMariusz Zaborski 		exit(0);
42308e493611SMariusz Zaborski 	}
42318e493611SMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
42328e493611SMariusz Zaborski 
42338e493611SMariusz Zaborski 	debuger = fork();
42348e493611SMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
42358e493611SMariusz Zaborski 	if (debuger == 0) {
42368e493611SMariusz Zaborski 		/* The traced process is reparented to debuger. */
4237*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_ATTACH, traced, 0, 0), 0);
42388e493611SMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
4239*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
42408e493611SMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
4241*96a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42428e493611SMariusz Zaborski 
42438e493611SMariusz Zaborski 		/* Allow process to die. */
4244*96a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, traced, (caddr_t)1, 0), 0);
42458e493611SMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
4246*96a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
42478e493611SMariusz Zaborski 		ATF_REQUIRE(WIFEXITED(status));
4248*96a9e50eSAlex Richardson 		REQUIRE_EQ(WEXITSTATUS(status), 0);
42498e493611SMariusz Zaborski 
42508e493611SMariusz Zaborski 		/* Reparent back to the orginal process. */
4251*96a9e50eSAlex Richardson 		REQUIRE_EQ(close(pd), 0);
42528e493611SMariusz Zaborski 		exit(0);
42538e493611SMariusz Zaborski 	}
42548e493611SMariusz Zaborski 
42558e493611SMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
4256*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debuger);
4257*96a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
42588e493611SMariusz Zaborski 
42598e493611SMariusz Zaborski 	/*
42608e493611SMariusz Zaborski 	 * We have a child but it has a process descriptori
42618e493611SMariusz Zaborski 	 * so we should not be able to collect it process.
42628e493611SMariusz Zaborski 	 */
42638e493611SMariusz Zaborski 	wpid = wait(&status);
4264*96a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
4265*96a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
42668e493611SMariusz Zaborski 
4267*96a9e50eSAlex Richardson 	REQUIRE_EQ(close(pd), 0);
42688e493611SMariusz Zaborski }
42698e493611SMariusz Zaborski 
4270c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
4271c209e3e2SJohn Baldwin {
4272c209e3e2SJohn Baldwin 
4273c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
4274c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
427557c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
427657c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
4277128c9bc0SMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
427898685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
427998685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
428098685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
428198685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
428298685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
428398685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
428498685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
428598685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
4286368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
4287189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
4288189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
4289189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
42905fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
42915fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
42923340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
42938d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
42948d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
42958d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
4296fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
4297fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
4298403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
429982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
4300e2ebfbbfSEric Badger #endif
430182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
430282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
430382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
430482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
430582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
430682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
430782a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
430882a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
430982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
4310753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
431182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
431282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
431382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
431482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
4315753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
4316753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
431782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
4318b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
4319b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
4320b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
4321d74da94cSMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
432254cfb29eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
4323643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
4324643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo);
4325643ce7deSJohn Baldwin #endif
4326643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__step_siginfo);
4327403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
4328e012fe34SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
4329e012fe34SJohn Baldwin #endif
4330c5786670SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
4331c8ea8731SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__syscall_args);
4332fd631bcdSMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__proc_reparent);
43338e493611SMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__procdesc_wait_child);
43348e493611SMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__procdesc_reparent_wait_child);
4335c209e3e2SJohn Baldwin 
4336c209e3e2SJohn Baldwin 	return (atf_no_error());
4337c209e3e2SJohn Baldwin }
4338