xref: /freebsd/tests/sys/kern/ptrace_test.c (revision 1fcbddec14dd693acf6a4be579f8d9e10b6a06a4)
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>
5096a9e50eSAlex 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__,	\
9596a9e50eSAlex Richardson 		    #exp " not met\n");			\
9696a9e50eSAlex Richardson } while (0)
9796a9e50eSAlex Richardson 
9896a9e50eSAlex Richardson #define	CHILD_REQUIRE_EQ(actual, expected) do {			\
9996a9e50eSAlex Richardson 	__typeof__(expected) _e = expected;			\
10096a9e50eSAlex Richardson 	__typeof__(actual) _a = actual;				\
10196a9e50eSAlex Richardson 	if (_e != _a)						\
10296a9e50eSAlex Richardson 		child_fail_require(__FILE__, __LINE__, #actual	\
10396a9e50eSAlex Richardson 		    " (%jd) == " #expected " (%jd) not met\n",	\
10496a9e50eSAlex Richardson 		    (intmax_t)_a, (intmax_t)_e);		\
105dfa8ba12SJohn Baldwin } while (0)
106dfa8ba12SJohn Baldwin 
10798685dc8SJohn Baldwin static __dead2 void
10896a9e50eSAlex Richardson child_fail_require(const char *file, int line, const char *fmt, ...)
109dfa8ba12SJohn Baldwin {
11096a9e50eSAlex Richardson 	va_list ap;
11196a9e50eSAlex Richardson 	char buf[1024];
112dfa8ba12SJohn Baldwin 
11396a9e50eSAlex Richardson 	/* Use write() not fprintf() to avoid possible duplicate output. */
11496a9e50eSAlex Richardson 	snprintf(buf, sizeof(buf), "%s:%d: ", file, line);
11596a9e50eSAlex Richardson 	write(STDERR_FILENO, buf, strlen(buf));
11696a9e50eSAlex Richardson 	va_start(ap, fmt);
11796a9e50eSAlex Richardson 	vsnprintf(buf, sizeof(buf), fmt, ap);
11896a9e50eSAlex Richardson 	write(STDERR_FILENO, buf, strlen(buf));
11996a9e50eSAlex Richardson 	va_end(ap);
12096a9e50eSAlex Richardson 
121dfa8ba12SJohn Baldwin 	_exit(32);
122dfa8ba12SJohn Baldwin }
123dfa8ba12SJohn Baldwin 
12496a9e50eSAlex Richardson #define	REQUIRE_EQ(actual, expected) do {				\
12596a9e50eSAlex Richardson 	__typeof__(expected) _e = expected;				\
12696a9e50eSAlex Richardson 	__typeof__(actual) _a = actual;					\
12796a9e50eSAlex Richardson 	ATF_REQUIRE_MSG(_e == _a, #actual " (%jd) == "			\
12896a9e50eSAlex Richardson 	    #expected " (%jd) not met", (intmax_t)_a, (intmax_t)_e);	\
12996a9e50eSAlex Richardson } while (0)
13096a9e50eSAlex 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 
14896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, pid, NULL, 0), 0);
14998685dc8SJohn Baldwin 
15098685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
15196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, pid);
15298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15396a9e50eSAlex 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) {
17996a9e50eSAlex 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);
21096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
211c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
21296a9e50eSAlex 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);
21996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
220c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
22196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
222c209e3e2SJohn Baldwin 
223c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
224c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
22596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
22696a9e50eSAlex 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 
24096a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
241c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
242c209e3e2SJohn Baldwin 	if (child == 0) {
243c209e3e2SJohn Baldwin 		/* Child process. */
244c209e3e2SJohn Baldwin 		close(cpipe[0]);
245c209e3e2SJohn Baldwin 
246c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
24796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(0, read(cpipe[1], &c, sizeof(c)));
248c209e3e2SJohn Baldwin 
249b98cb919SJohn Baldwin 		_exit(1);
250c209e3e2SJohn Baldwin 	}
251c209e3e2SJohn Baldwin 	close(cpipe[1]);
252c209e3e2SJohn Baldwin 
253c209e3e2SJohn Baldwin 	/* Parent process. */
254c209e3e2SJohn Baldwin 
255c209e3e2SJohn Baldwin 	/* Attach to the child process. */
25698685dc8SJohn Baldwin 	attach_child(child);
257c209e3e2SJohn Baldwin 
258c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
259c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
260c209e3e2SJohn Baldwin 
261c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
262c209e3e2SJohn Baldwin 	close(cpipe[0]);
263c209e3e2SJohn Baldwin 
264c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
265c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
26696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
267c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
26896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
269c209e3e2SJohn Baldwin 
270c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
271c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
27296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
27396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
274c209e3e2SJohn Baldwin }
275c209e3e2SJohn Baldwin 
27657c74f5bSJohn Baldwin /*
27757c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
27857c74f5bSJohn Baldwin  * after the debugger has seen it.
27957c74f5bSJohn Baldwin  */
28057c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
28157c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
28257c74f5bSJohn Baldwin {
28357c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
28457c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
28557c74f5bSJohn Baldwin 	char c;
28657c74f5bSJohn Baldwin 
28796a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
28857c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
28957c74f5bSJohn Baldwin 
29057c74f5bSJohn Baldwin 	if (child == 0) {
29157c74f5bSJohn Baldwin 		/* Child process. */
29257c74f5bSJohn Baldwin 		close(cpipe[0]);
29357c74f5bSJohn Baldwin 
29457c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
295*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
296*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
29757c74f5bSJohn Baldwin 
298b98cb919SJohn Baldwin 		_exit(1);
29957c74f5bSJohn Baldwin 	}
30057c74f5bSJohn Baldwin 	close(cpipe[1]);
30157c74f5bSJohn Baldwin 
30296a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
30357c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
30457c74f5bSJohn Baldwin 
30557c74f5bSJohn Baldwin 	if (debugger == 0) {
30657c74f5bSJohn Baldwin 		/* Debugger process. */
30757c74f5bSJohn Baldwin 		close(dpipe[0]);
30857c74f5bSJohn Baldwin 
309dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
31057c74f5bSJohn Baldwin 
31157c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
31296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
313dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
31496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
31557c74f5bSJohn Baldwin 
316dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
31757c74f5bSJohn Baldwin 
31857c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
319*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
320*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
32157c74f5bSJohn Baldwin 
32257c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
32396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(read(dpipe[1], &c, sizeof(c)), 0);
32457c74f5bSJohn Baldwin 
32557c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
32696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
327dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
32896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
32957c74f5bSJohn Baldwin 
330b98cb919SJohn Baldwin 		_exit(0);
33157c74f5bSJohn Baldwin 	}
33257c74f5bSJohn Baldwin 	close(dpipe[1]);
33357c74f5bSJohn Baldwin 
33457c74f5bSJohn Baldwin 	/* Parent process. */
33557c74f5bSJohn Baldwin 
33657c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
337*1fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
33857c74f5bSJohn Baldwin 
33957c74f5bSJohn Baldwin 	/* Release the child. */
340*1fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
34196a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &c, sizeof(c)), 0);
34257c74f5bSJohn Baldwin 	close(cpipe[0]);
34357c74f5bSJohn Baldwin 
34498685dc8SJohn Baldwin 	wait_for_zombie(child);
34557c74f5bSJohn Baldwin 
34657c74f5bSJohn Baldwin 	/*
3472f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3482f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3492f021998SJohn Baldwin 	 * until the debugger sees the exit.
35057c74f5bSJohn Baldwin 	 */
35157c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
35296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
35357c74f5bSJohn Baldwin 
35457c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
35557c74f5bSJohn Baldwin 	close(dpipe[0]);
35657c74f5bSJohn Baldwin 
35757c74f5bSJohn Baldwin 	/* Wait for the debugger. */
35857c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
35996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
36057c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
36196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
36257c74f5bSJohn Baldwin 
36357c74f5bSJohn Baldwin 	/* The child process should now be ready. */
36457c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
36596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
36657c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
36796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
36857c74f5bSJohn Baldwin }
36957c74f5bSJohn Baldwin 
37057c74f5bSJohn Baldwin /*
37157c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
37257c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
37357c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
37457c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
37557c74f5bSJohn Baldwin  */
37657c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
37757c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
37857c74f5bSJohn Baldwin {
37957c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
38057c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
38157c74f5bSJohn Baldwin 	char c;
38257c74f5bSJohn Baldwin 
38396a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
38457c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
38557c74f5bSJohn Baldwin 
38657c74f5bSJohn Baldwin 	if (child == 0) {
38757c74f5bSJohn Baldwin 		/* Child process. */
38857c74f5bSJohn Baldwin 		close(cpipe[0]);
38957c74f5bSJohn Baldwin 
39057c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
391*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
392*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
39357c74f5bSJohn Baldwin 
394b98cb919SJohn Baldwin 		_exit(1);
39557c74f5bSJohn Baldwin 	}
39657c74f5bSJohn Baldwin 	close(cpipe[1]);
39757c74f5bSJohn Baldwin 
39896a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
39957c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
40057c74f5bSJohn Baldwin 
40157c74f5bSJohn Baldwin 	if (debugger == 0) {
40257c74f5bSJohn Baldwin 		/* Debugger parent. */
40357c74f5bSJohn Baldwin 
40457c74f5bSJohn Baldwin 		/*
40557c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
40657c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
40757c74f5bSJohn Baldwin 		 */
408dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
40957c74f5bSJohn Baldwin 		if (fpid != 0)
410b98cb919SJohn Baldwin 			_exit(2);
41157c74f5bSJohn Baldwin 
41257c74f5bSJohn Baldwin 		/* Debugger process. */
41357c74f5bSJohn Baldwin 		close(dpipe[0]);
41457c74f5bSJohn Baldwin 
415dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
41657c74f5bSJohn Baldwin 
41757c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
41896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
419dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
42096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42157c74f5bSJohn Baldwin 
422dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
42357c74f5bSJohn Baldwin 
42457c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
425*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
426*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
42757c74f5bSJohn Baldwin 
42857c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
429*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(dpipe[1], &c, sizeof(c)),
430*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
43157c74f5bSJohn Baldwin 
43257c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
43396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
434dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
43596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
43657c74f5bSJohn Baldwin 
437b98cb919SJohn Baldwin 		_exit(0);
43857c74f5bSJohn Baldwin 	}
439eddb85c6SJohn Baldwin 	close(dpipe[1]);
44057c74f5bSJohn Baldwin 
44157c74f5bSJohn Baldwin 	/* Parent process. */
44257c74f5bSJohn Baldwin 
44357c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
44457c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
44596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
44657c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
44796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
44857c74f5bSJohn Baldwin 
44957c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
45057c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
45196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
45257c74f5bSJohn Baldwin 
45357c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
454*1fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
45557c74f5bSJohn Baldwin 
45657c74f5bSJohn Baldwin 	/* Release the child. */
457*1fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
45896a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &c, sizeof(c)), 0);
45957c74f5bSJohn Baldwin 	close(cpipe[0]);
46057c74f5bSJohn Baldwin 
46198685dc8SJohn Baldwin 	wait_for_zombie(child);
46257c74f5bSJohn Baldwin 
46357c74f5bSJohn Baldwin 	/*
4642f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
4652f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
4662f021998SJohn Baldwin 	 * until the debugger sees the exit.
46757c74f5bSJohn Baldwin 	 */
46857c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
46996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
47057c74f5bSJohn Baldwin 
47157c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
472*1fcbddecSAlex Richardson 	REQUIRE_EQ(write(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
47357c74f5bSJohn Baldwin 
47457c74f5bSJohn Baldwin 	/* Wait for the debugger. */
47596a9e50eSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), 0);
476eddb85c6SJohn Baldwin 	close(dpipe[0]);
47757c74f5bSJohn Baldwin 
47857c74f5bSJohn Baldwin 	/* The child process should now be ready. */
47957c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
48096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
48157c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
48296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
48357c74f5bSJohn Baldwin }
48457c74f5bSJohn Baldwin 
48598685dc8SJohn Baldwin /*
486128c9bc0SMark Johnston  * Make sure that we can collect the exit status of an orphaned process.
487128c9bc0SMark Johnston  */
488128c9bc0SMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
489128c9bc0SMark Johnston ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
490128c9bc0SMark Johnston {
491128c9bc0SMark Johnston 	ssize_t n;
492128c9bc0SMark Johnston 	int cpipe1[2], cpipe2[2], gcpipe[2], status;
493128c9bc0SMark Johnston 	pid_t child, gchild;
494128c9bc0SMark Johnston 
49596a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe1), 0);
49696a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe2), 0);
49796a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(gcpipe), 0);
498128c9bc0SMark Johnston 
49996a9e50eSAlex Richardson 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
500128c9bc0SMark Johnston 
501128c9bc0SMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
502128c9bc0SMark Johnston 	if (child == 0) {
503128c9bc0SMark Johnston 		CHILD_REQUIRE((gchild = fork()) != -1);
504128c9bc0SMark Johnston 		if (gchild == 0) {
505128c9bc0SMark Johnston 			status = 1;
506128c9bc0SMark Johnston 			do {
507128c9bc0SMark Johnston 				n = read(gcpipe[0], &status, sizeof(status));
508128c9bc0SMark Johnston 			} while (n == -1 && errno == EINTR);
509128c9bc0SMark Johnston 			_exit(status);
510128c9bc0SMark Johnston 		}
511128c9bc0SMark Johnston 
512*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(cpipe1[1], &gchild, sizeof(gchild)),
513*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(gchild));
514*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe2[0], &status, sizeof(status)),
515*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(status));
516128c9bc0SMark Johnston 		_exit(status);
517128c9bc0SMark Johnston 	}
518128c9bc0SMark Johnston 
519*1fcbddecSAlex Richardson 	REQUIRE_EQ(read(cpipe1[0], &gchild, sizeof(gchild)),
520*1fcbddecSAlex Richardson 	    (ssize_t)sizeof(gchild));
521128c9bc0SMark Johnston 
52296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, gchild, NULL, 0), 0);
523128c9bc0SMark Johnston 
524128c9bc0SMark Johnston 	status = 0;
525*1fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe2[1], &status, sizeof(status)),
526*1fcbddecSAlex Richardson 	    (ssize_t)sizeof(status));
52796a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(child, &status, 0), child);
52896a9e50eSAlex Richardson 	ATF_REQUIRE(WIFEXITED(status));
52996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
530128c9bc0SMark Johnston 
531128c9bc0SMark Johnston 	status = 0;
532*1fcbddecSAlex Richardson 	REQUIRE_EQ(write(gcpipe[1], &status, sizeof(status)),
533*1fcbddecSAlex Richardson 	    (ssize_t)sizeof(status));
53496a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(gchild, &status, 0), gchild);
535128c9bc0SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
53696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_DETACH, gchild, (caddr_t)1, 0), 0);
53796a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(gchild, &status, 0), gchild);
53896a9e50eSAlex Richardson 	ATF_REQUIRE(WIFEXITED(status));
53996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
540128c9bc0SMark Johnston 
54196a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe1[0]), 0);
54296a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe1[1]), 0);
54396a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe2[0]), 0);
54496a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe2[1]), 0);
54596a9e50eSAlex Richardson 	REQUIRE_EQ(close(gcpipe[0]), 0);
54696a9e50eSAlex Richardson 	REQUIRE_EQ(close(gcpipe[1]), 0);
547128c9bc0SMark Johnston }
548128c9bc0SMark Johnston 
549128c9bc0SMark Johnston /*
55098685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
55198685dc8SJohn Baldwin  * debugger is attached to it.
55298685dc8SJohn Baldwin  */
55398685dc8SJohn Baldwin static __dead2 void
554189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
55598685dc8SJohn Baldwin {
55698685dc8SJohn Baldwin 	pid_t fpid, wpid;
55798685dc8SJohn Baldwin 	int status;
55898685dc8SJohn Baldwin 
559189ac973SJohn Baldwin 	if (use_vfork)
560189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
561189ac973SJohn Baldwin 	else
56298685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
56398685dc8SJohn Baldwin 
56498685dc8SJohn Baldwin 	if (fpid == 0)
56598685dc8SJohn Baldwin 		/* Child */
566b98cb919SJohn Baldwin 		_exit(2);
56798685dc8SJohn Baldwin 
56898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
56996a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(wpid, fpid);
57098685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
57196a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(WEXITSTATUS(status), 2);
57298685dc8SJohn Baldwin 
573b98cb919SJohn Baldwin 	_exit(1);
57498685dc8SJohn Baldwin }
57598685dc8SJohn Baldwin 
57698685dc8SJohn Baldwin /*
57798685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
57898685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
57998685dc8SJohn Baldwin  * child process.
58098685dc8SJohn Baldwin  */
58198685dc8SJohn Baldwin static pid_t
582189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
58398685dc8SJohn Baldwin {
58498685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
58598685dc8SJohn Baldwin 	bool fork_reported[2];
58698685dc8SJohn Baldwin 	pid_t child, wpid;
58798685dc8SJohn Baldwin 	int i, status;
58898685dc8SJohn Baldwin 
58998685dc8SJohn Baldwin 	fork_reported[0] = false;
59098685dc8SJohn Baldwin 	fork_reported[1] = false;
59198685dc8SJohn Baldwin 	child = -1;
59298685dc8SJohn Baldwin 
59398685dc8SJohn Baldwin 	/*
59498685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
59598685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
59698685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
59798685dc8SJohn Baldwin 	 */
59898685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
59998685dc8SJohn Baldwin 		wpid = wait(&status);
60098685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
60198685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
60298685dc8SJohn Baldwin 
60398685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
60498685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
60598685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
60698685dc8SJohn Baldwin 		    0);
60798685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
60898685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
60998685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
61098685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
61196a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
61298685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
61398685dc8SJohn Baldwin 			if (child == -1)
61498685dc8SJohn Baldwin 				child = wpid;
61598685dc8SJohn Baldwin 			else
61696a9e50eSAlex Richardson 				REQUIRE_EQ(child, wpid);
617189ac973SJohn Baldwin 			if (ppl != NULL)
618189ac973SJohn Baldwin 				ppl[1] = pl;
61998685dc8SJohn Baldwin 			fork_reported[1] = true;
62098685dc8SJohn Baldwin 		} else {
62196a9e50eSAlex Richardson 			REQUIRE_EQ(wpid, parent);
62296a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
62398685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
62498685dc8SJohn Baldwin 			if (child == -1)
62598685dc8SJohn Baldwin 				child = pl.pl_child_pid;
62698685dc8SJohn Baldwin 			else
62796a9e50eSAlex Richardson 				REQUIRE_EQ(child, pl.pl_child_pid);
628189ac973SJohn Baldwin 			if (ppl != NULL)
629189ac973SJohn Baldwin 				ppl[0] = pl;
63098685dc8SJohn Baldwin 			fork_reported[0] = true;
63198685dc8SJohn Baldwin 		}
63298685dc8SJohn Baldwin 	}
63398685dc8SJohn Baldwin 
63498685dc8SJohn Baldwin 	return (child);
63598685dc8SJohn Baldwin }
63698685dc8SJohn Baldwin 
63798685dc8SJohn Baldwin /*
63898685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
63998685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
64098685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
64198685dc8SJohn Baldwin  */
64298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
64398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
64498685dc8SJohn Baldwin {
645479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
64698685dc8SJohn Baldwin 	int status;
64798685dc8SJohn Baldwin 
64898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
64998685dc8SJohn Baldwin 	if (fpid == 0) {
65098685dc8SJohn Baldwin 		trace_me();
651189ac973SJohn Baldwin 		follow_fork_parent(false);
65298685dc8SJohn Baldwin 	}
65398685dc8SJohn Baldwin 
65498685dc8SJohn Baldwin 	/* Parent process. */
65598685dc8SJohn Baldwin 	children[0] = fpid;
65698685dc8SJohn Baldwin 
65798685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
65898685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
65996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
66098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
66196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
66298685dc8SJohn Baldwin 
66398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
66498685dc8SJohn Baldwin 
66598685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
66698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
66798685dc8SJohn Baldwin 
668189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
66998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
67098685dc8SJohn Baldwin 
67198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
67298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
67398685dc8SJohn Baldwin 
67498685dc8SJohn Baldwin 	/*
67598685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
67698685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
67798685dc8SJohn Baldwin 	 */
67898685dc8SJohn Baldwin 	wpid = wait(&status);
67996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
68098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
68196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
68298685dc8SJohn Baldwin 
68398685dc8SJohn Baldwin 	wpid = wait(&status);
68496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
68598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
68696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
68798685dc8SJohn Baldwin 
68898685dc8SJohn Baldwin 	wpid = wait(&status);
68996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
69096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
69198685dc8SJohn Baldwin }
69298685dc8SJohn Baldwin 
69398685dc8SJohn Baldwin /*
69498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
69598685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
69698685dc8SJohn Baldwin  * child process is detached after it reports its fork.
69798685dc8SJohn Baldwin  */
69898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
69998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
70098685dc8SJohn Baldwin {
701479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
70298685dc8SJohn Baldwin 	int status;
70398685dc8SJohn Baldwin 
70498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
70598685dc8SJohn Baldwin 	if (fpid == 0) {
70698685dc8SJohn Baldwin 		trace_me();
707189ac973SJohn Baldwin 		follow_fork_parent(false);
70898685dc8SJohn Baldwin 	}
70998685dc8SJohn Baldwin 
71098685dc8SJohn Baldwin 	/* Parent process. */
71198685dc8SJohn Baldwin 	children[0] = fpid;
71298685dc8SJohn Baldwin 
71398685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
71498685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
71596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
71698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
71796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
71898685dc8SJohn Baldwin 
71998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
72098685dc8SJohn Baldwin 
72198685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
72298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
72398685dc8SJohn Baldwin 
724189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
72598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
72698685dc8SJohn Baldwin 
72798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
72898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
72998685dc8SJohn Baldwin 
73098685dc8SJohn Baldwin 	/*
73198685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
73298685dc8SJohn Baldwin 	 * child.
73398685dc8SJohn Baldwin 	 */
73498685dc8SJohn Baldwin 	wpid = wait(&status);
73596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
73698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
73796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
73898685dc8SJohn Baldwin 
73998685dc8SJohn Baldwin 	wpid = wait(&status);
74096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
74196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
74298685dc8SJohn Baldwin }
74398685dc8SJohn Baldwin 
74498685dc8SJohn Baldwin /*
74598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
74698685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
74798685dc8SJohn Baldwin  * traced parent is detached after the fork.
74898685dc8SJohn Baldwin  */
74998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
75098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
75198685dc8SJohn Baldwin {
752479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
75398685dc8SJohn Baldwin 	int status;
75498685dc8SJohn Baldwin 
75598685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
75698685dc8SJohn Baldwin 	if (fpid == 0) {
75798685dc8SJohn Baldwin 		trace_me();
758189ac973SJohn Baldwin 		follow_fork_parent(false);
75998685dc8SJohn Baldwin 	}
76098685dc8SJohn Baldwin 
76198685dc8SJohn Baldwin 	/* Parent process. */
76298685dc8SJohn Baldwin 	children[0] = fpid;
76398685dc8SJohn Baldwin 
76498685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
76598685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
76696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
76798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
76896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
76998685dc8SJohn Baldwin 
77098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
77198685dc8SJohn Baldwin 
77298685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
77398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
77498685dc8SJohn Baldwin 
775189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
77698685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
77798685dc8SJohn Baldwin 
77898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
77998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
78098685dc8SJohn Baldwin 
78198685dc8SJohn Baldwin 	/*
78298685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
78398685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
78498685dc8SJohn Baldwin 	 *
78598685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
78698685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
78798685dc8SJohn Baldwin 	 * after the grandchild.
78898685dc8SJohn Baldwin 	 */
78998685dc8SJohn Baldwin 	wpid = wait(&status);
79096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
79198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
79296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
79398685dc8SJohn Baldwin 
79498685dc8SJohn Baldwin 	wpid = wait(&status);
79596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
79698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
79796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
79898685dc8SJohn Baldwin 
79998685dc8SJohn Baldwin 	wpid = wait(&status);
80096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
80196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
80298685dc8SJohn Baldwin }
80398685dc8SJohn Baldwin 
80498685dc8SJohn Baldwin static void
80598685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
80698685dc8SJohn Baldwin {
80798685dc8SJohn Baldwin 	pid_t fpid;
80898685dc8SJohn Baldwin 
80998685dc8SJohn Baldwin 	close(cpipe[0]);
81098685dc8SJohn Baldwin 
81198685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
81298685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
81398685dc8SJohn Baldwin 	if (fpid != 0)
814b98cb919SJohn Baldwin 		_exit(3);
81598685dc8SJohn Baldwin 
81698685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
81798685dc8SJohn Baldwin 	fpid = getpid();
818*1fcbddecSAlex Richardson 	CHILD_REQUIRE_EQ(write(cpipe[1], &fpid, sizeof(fpid)),
819*1fcbddecSAlex Richardson 	    (ssize_t)sizeof(fpid));
82098685dc8SJohn Baldwin 
82198685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
82296a9e50eSAlex 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 
83796a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
83898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
83998685dc8SJohn Baldwin 	if (fpid == 0) {
84098685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
841189ac973SJohn Baldwin 		follow_fork_parent(false);
84298685dc8SJohn Baldwin 	}
84398685dc8SJohn Baldwin 
84498685dc8SJohn Baldwin 	/* Parent process. */
84598685dc8SJohn Baldwin 	close(cpipe[1]);
84698685dc8SJohn Baldwin 
84798685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
84898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
84996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
85098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
85196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
85298685dc8SJohn Baldwin 
85398685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
85496a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
855*1fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
85698685dc8SJohn Baldwin 
85798685dc8SJohn Baldwin 	/* Attach to the fork parent. */
85898685dc8SJohn Baldwin 	attach_child(children[0]);
85998685dc8SJohn Baldwin 
86098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
86198685dc8SJohn Baldwin 
86298685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
86398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
86498685dc8SJohn Baldwin 
86598685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
86698685dc8SJohn Baldwin 	close(cpipe[0]);
86798685dc8SJohn Baldwin 
868189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
86998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
87098685dc8SJohn Baldwin 
87198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
87298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
87398685dc8SJohn Baldwin 
87498685dc8SJohn Baldwin 	/*
87598685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
87698685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
87798685dc8SJohn Baldwin 	 */
87898685dc8SJohn Baldwin 	wpid = wait(&status);
87996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
88098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
88196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
88298685dc8SJohn Baldwin 
88398685dc8SJohn Baldwin 	wpid = wait(&status);
88496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
88598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
88696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
88798685dc8SJohn Baldwin 
88898685dc8SJohn Baldwin 	wpid = wait(&status);
88996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
89096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
89198685dc8SJohn Baldwin }
89298685dc8SJohn Baldwin 
89398685dc8SJohn Baldwin /*
89498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
89598685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
89698685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
89798685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
89898685dc8SJohn Baldwin  */
89998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
90098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
90198685dc8SJohn Baldwin {
902479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
90398685dc8SJohn Baldwin 	int cpipe[2], status;
90498685dc8SJohn Baldwin 
90596a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
90698685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
90798685dc8SJohn Baldwin 	if (fpid == 0) {
90898685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
909189ac973SJohn Baldwin 		follow_fork_parent(false);
91098685dc8SJohn Baldwin 	}
91198685dc8SJohn Baldwin 
91298685dc8SJohn Baldwin 	/* Parent process. */
91398685dc8SJohn Baldwin 	close(cpipe[1]);
91498685dc8SJohn Baldwin 
91598685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
91698685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
91796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
91898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
91996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
92098685dc8SJohn Baldwin 
92198685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
92296a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
923*1fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
92498685dc8SJohn Baldwin 
92598685dc8SJohn Baldwin 	/* Attach to the fork parent. */
92698685dc8SJohn Baldwin 	attach_child(children[0]);
92798685dc8SJohn Baldwin 
92898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
92998685dc8SJohn Baldwin 
93098685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
93198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
93298685dc8SJohn Baldwin 
93398685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
93498685dc8SJohn Baldwin 	close(cpipe[0]);
93598685dc8SJohn Baldwin 
936189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
93798685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
93898685dc8SJohn Baldwin 
93998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
94098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
94198685dc8SJohn Baldwin 
94298685dc8SJohn Baldwin 	/*
94398685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
94498685dc8SJohn Baldwin 	 * parent.
94598685dc8SJohn Baldwin 	 */
94698685dc8SJohn Baldwin 	wpid = wait(&status);
94796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
94898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
94996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
95098685dc8SJohn Baldwin 
95198685dc8SJohn Baldwin 	wpid = wait(&status);
95296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
95396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
95498685dc8SJohn Baldwin }
95598685dc8SJohn Baldwin 
95698685dc8SJohn Baldwin /*
95798685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
95898685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
95998685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
96098685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
96198685dc8SJohn Baldwin  */
96298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
96398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
96498685dc8SJohn Baldwin {
965479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
96698685dc8SJohn Baldwin 	int cpipe[2], status;
96798685dc8SJohn Baldwin 
96896a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
96998685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
97098685dc8SJohn Baldwin 	if (fpid == 0) {
97198685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
972189ac973SJohn Baldwin 		follow_fork_parent(false);
97398685dc8SJohn Baldwin 	}
97498685dc8SJohn Baldwin 
97598685dc8SJohn Baldwin 	/* Parent process. */
97698685dc8SJohn Baldwin 	close(cpipe[1]);
97798685dc8SJohn Baldwin 
97898685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
97998685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
98096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
98198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
98296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
98398685dc8SJohn Baldwin 
98498685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
98596a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
986*1fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
98798685dc8SJohn Baldwin 
98898685dc8SJohn Baldwin 	/* Attach to the fork parent. */
98998685dc8SJohn Baldwin 	attach_child(children[0]);
99098685dc8SJohn Baldwin 
99198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
99298685dc8SJohn Baldwin 
99398685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
99498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
99598685dc8SJohn Baldwin 
99698685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
99798685dc8SJohn Baldwin 	close(cpipe[0]);
99898685dc8SJohn Baldwin 
999189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
100098685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
100198685dc8SJohn Baldwin 
100298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
100398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
100498685dc8SJohn Baldwin 
100598685dc8SJohn Baldwin 	/*
100698685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
100798685dc8SJohn Baldwin 	 * the child.
100898685dc8SJohn Baldwin 	 */
100998685dc8SJohn Baldwin 	wpid = wait(&status);
101096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
101198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
101296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
101398685dc8SJohn Baldwin 
101498685dc8SJohn Baldwin 	wpid = wait(&status);
101596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
101696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
101798685dc8SJohn Baldwin }
101898685dc8SJohn Baldwin 
1019368b2b1cSJohn Baldwin /*
1020368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
1021368b2b1cSJohn Baldwin  * parent but sees its original parent process.
1022368b2b1cSJohn Baldwin  */
1023368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
1024368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
1025368b2b1cSJohn Baldwin {
1026368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
1027368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
1028368b2b1cSJohn Baldwin 	char c;
1029368b2b1cSJohn Baldwin 
103096a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
1031368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
1032368b2b1cSJohn Baldwin 
1033368b2b1cSJohn Baldwin 	if (child == 0) {
1034368b2b1cSJohn Baldwin 		/* Child process. */
1035368b2b1cSJohn Baldwin 		close(cpipe[0]);
1036368b2b1cSJohn Baldwin 
1037368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
1038*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
1039*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
1040368b2b1cSJohn Baldwin 
1041368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
1042368b2b1cSJohn Baldwin 		ppid = getppid();
1043*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(cpipe[1], &ppid, sizeof(ppid)),
1044*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(ppid));
1045368b2b1cSJohn Baldwin 
1046368b2b1cSJohn Baldwin 		_exit(1);
1047368b2b1cSJohn Baldwin 	}
1048368b2b1cSJohn Baldwin 	close(cpipe[1]);
1049368b2b1cSJohn Baldwin 
105096a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
1051368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
1052368b2b1cSJohn Baldwin 
1053368b2b1cSJohn Baldwin 	if (debugger == 0) {
1054368b2b1cSJohn Baldwin 		/* Debugger process. */
1055368b2b1cSJohn Baldwin 		close(dpipe[0]);
1056368b2b1cSJohn Baldwin 
1057368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
1058368b2b1cSJohn Baldwin 
1059368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
106096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
1061368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
106296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1063368b2b1cSJohn Baldwin 
1064368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
1065368b2b1cSJohn Baldwin 
1066368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
1067*1fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
1068*1fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
1069368b2b1cSJohn Baldwin 
1070368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
1071368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
107296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
1073368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
107496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
1075368b2b1cSJohn Baldwin 
1076368b2b1cSJohn Baldwin 		_exit(0);
1077368b2b1cSJohn Baldwin 	}
1078368b2b1cSJohn Baldwin 	close(dpipe[1]);
1079368b2b1cSJohn Baldwin 
1080368b2b1cSJohn Baldwin 	/* Parent process. */
1081368b2b1cSJohn Baldwin 
1082368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
1083*1fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
1084368b2b1cSJohn Baldwin 
1085368b2b1cSJohn Baldwin 	/* Release the child. */
1086*1fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
1087368b2b1cSJohn Baldwin 
1088368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
1089*1fcbddecSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &ppid, sizeof(ppid)), (ssize_t)sizeof(ppid));
1090368b2b1cSJohn Baldwin 	close(cpipe[0]);
1091368b2b1cSJohn Baldwin 
109296a9e50eSAlex Richardson 	REQUIRE_EQ(ppid, getpid());
1093368b2b1cSJohn Baldwin 
1094368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
1095368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
109696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
1097368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
109896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
1099368b2b1cSJohn Baldwin 
1100368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
1101368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
110296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
1103368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
110496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1105368b2b1cSJohn Baldwin }
1106368b2b1cSJohn Baldwin 
1107189ac973SJohn Baldwin /*
1108189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1109189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
1110189ac973SJohn Baldwin  */
1111189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
1112189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
1113189ac973SJohn Baldwin {
1114189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1115189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1116189ac973SJohn Baldwin 	int status;
1117189ac973SJohn Baldwin 
1118189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1119189ac973SJohn Baldwin 	if (fpid == 0) {
1120189ac973SJohn Baldwin 		trace_me();
1121189ac973SJohn Baldwin 		follow_fork_parent(false);
1122189ac973SJohn Baldwin 	}
1123189ac973SJohn Baldwin 
1124189ac973SJohn Baldwin 	/* Parent process. */
1125189ac973SJohn Baldwin 	children[0] = fpid;
1126189ac973SJohn Baldwin 
1127189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1128189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
112996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1130189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
113196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1132189ac973SJohn Baldwin 
1133189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1134189ac973SJohn Baldwin 
1135189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1136189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1137189ac973SJohn Baldwin 
1138189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1139189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1140189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1141189ac973SJohn Baldwin 
1142189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1143189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1144*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, (unsigned)SYS_fork);
114596a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, pl[1].pl_syscall_code);
114696a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_narg, pl[1].pl_syscall_narg);
1147189ac973SJohn Baldwin 
1148189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1149189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1150189ac973SJohn Baldwin 
1151189ac973SJohn Baldwin 	/*
1152189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1153189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1154189ac973SJohn Baldwin 	 */
1155189ac973SJohn Baldwin 	wpid = wait(&status);
115696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1157189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
115896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1159189ac973SJohn Baldwin 
1160189ac973SJohn Baldwin 	wpid = wait(&status);
116196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1162189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
116396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1164189ac973SJohn Baldwin 
1165189ac973SJohn Baldwin 	wpid = wait(&status);
116696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
116796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1168189ac973SJohn Baldwin }
1169189ac973SJohn Baldwin 
1170189ac973SJohn Baldwin /*
1171189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1172189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1173189ac973SJohn Baldwin  */
1174189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1175189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1176189ac973SJohn Baldwin {
1177189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1178189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1179189ac973SJohn Baldwin 	int status;
1180189ac973SJohn Baldwin 
1181189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1182189ac973SJohn Baldwin 	if (fpid == 0) {
1183189ac973SJohn Baldwin 		trace_me();
1184189ac973SJohn Baldwin 		follow_fork_parent(true);
1185189ac973SJohn Baldwin 	}
1186189ac973SJohn Baldwin 
1187189ac973SJohn Baldwin 	/* Parent process. */
1188189ac973SJohn Baldwin 	children[0] = fpid;
1189189ac973SJohn Baldwin 
1190189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1191189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
119296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1193189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
119496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1195189ac973SJohn Baldwin 
1196189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1197189ac973SJohn Baldwin 
1198189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1199189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1200189ac973SJohn Baldwin 
1201189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1202189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1203189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1204189ac973SJohn Baldwin 
1205189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1206189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1207*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, (unsigned)SYS_vfork);
120896a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, pl[1].pl_syscall_code);
120996a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_narg, pl[1].pl_syscall_narg);
1210189ac973SJohn Baldwin 
1211189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1212189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1213189ac973SJohn Baldwin 
1214189ac973SJohn Baldwin 	/*
1215189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1216189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1217189ac973SJohn Baldwin 	 */
1218189ac973SJohn Baldwin 	wpid = wait(&status);
121996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1220189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
122196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1222189ac973SJohn Baldwin 
1223189ac973SJohn Baldwin 	wpid = wait(&status);
122496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1225189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
122696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1227189ac973SJohn Baldwin 
1228189ac973SJohn Baldwin 	wpid = wait(&status);
122996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
123096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1231189ac973SJohn Baldwin }
1232189ac973SJohn Baldwin 
1233189ac973SJohn Baldwin static void *
1234189ac973SJohn Baldwin simple_thread(void *arg __unused)
1235189ac973SJohn Baldwin {
1236189ac973SJohn Baldwin 
1237189ac973SJohn Baldwin 	pthread_exit(NULL);
1238189ac973SJohn Baldwin }
1239189ac973SJohn Baldwin 
12405fcfab6eSJohn Baldwin static __dead2 void
12415fcfab6eSJohn Baldwin simple_thread_main(void)
12425fcfab6eSJohn Baldwin {
12435fcfab6eSJohn Baldwin 	pthread_t thread;
12445fcfab6eSJohn Baldwin 
124596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_create(&thread, NULL, simple_thread, NULL), 0);
124696a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(thread, NULL), 0);
12475fcfab6eSJohn Baldwin 	exit(1);
12485fcfab6eSJohn Baldwin }
12495fcfab6eSJohn Baldwin 
1250189ac973SJohn Baldwin /*
1251189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1252189ac973SJohn Baldwin  * thread reports the correct value.
1253189ac973SJohn Baldwin  */
1254189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1255189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1256189ac973SJohn Baldwin {
1257189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1258189ac973SJohn Baldwin 	pid_t fpid, wpid;
1259e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1260189ac973SJohn Baldwin 	int status;
1261189ac973SJohn Baldwin 
1262189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1263189ac973SJohn Baldwin 	if (fpid == 0) {
1264189ac973SJohn Baldwin 		trace_me();
12655fcfab6eSJohn Baldwin 		simple_thread_main();
1266189ac973SJohn Baldwin 	}
1267189ac973SJohn Baldwin 
1268189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1269189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
127096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1271189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
127296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1273189ac973SJohn Baldwin 
1274189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1275189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1276e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1277189ac973SJohn Baldwin 
1278189ac973SJohn Baldwin 	/*
1279189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1280189ac973SJohn Baldwin 	 * system call exits.
1281189ac973SJohn Baldwin 	 */
1282189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1283189ac973SJohn Baldwin 
1284189ac973SJohn Baldwin 	/*
1285189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1286189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1287189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1288189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1289189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1290189ac973SJohn Baldwin 	 */
1291189ac973SJohn Baldwin 	for (;;) {
1292189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
129396a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
1294189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
129596a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1296189ac973SJohn Baldwin 
1297189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1298189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1299189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1300189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1301e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1302189ac973SJohn Baldwin 			/* New thread seen. */
1303189ac973SJohn Baldwin 			break;
1304189ac973SJohn Baldwin 
130596a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1306189ac973SJohn Baldwin 	}
1307189ac973SJohn Baldwin 
1308189ac973SJohn Baldwin 	/* Wait for the child to exit. */
130996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1310189ac973SJohn Baldwin 	for (;;) {
1311189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
131296a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
1313189ac973SJohn Baldwin 		if (WIFEXITED(status))
1314189ac973SJohn Baldwin 			break;
1315189ac973SJohn Baldwin 
1316189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
131796a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
131896a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1319189ac973SJohn Baldwin 	}
1320189ac973SJohn Baldwin 
132196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1322189ac973SJohn Baldwin 
1323189ac973SJohn Baldwin 	wpid = wait(&status);
132496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
132596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1326189ac973SJohn Baldwin }
1327189ac973SJohn Baldwin 
13285fcfab6eSJohn Baldwin /*
13295fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
13305fcfab6eSJohn Baldwin  */
13315fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
13325fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
13335fcfab6eSJohn Baldwin {
13345fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
13355fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
13365fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
13375fcfab6eSJohn Baldwin 	int status;
13385fcfab6eSJohn Baldwin 
13395fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13405fcfab6eSJohn Baldwin 	if (fpid == 0) {
13415fcfab6eSJohn Baldwin 		trace_me();
13425fcfab6eSJohn Baldwin 		simple_thread_main();
13435fcfab6eSJohn Baldwin 	}
13445fcfab6eSJohn Baldwin 
13455fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13465fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
134796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13485fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
134996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
13505fcfab6eSJohn Baldwin 
13515fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13525fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13535fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13545fcfab6eSJohn Baldwin 
135596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
13565fcfab6eSJohn Baldwin 
13575fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
135896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13595fcfab6eSJohn Baldwin 
13605fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13615fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
136296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13635fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
136496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
13655fcfab6eSJohn Baldwin 
13665fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
136796a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
13685fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13695fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13705fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13715fcfab6eSJohn Baldwin 
137296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13735fcfab6eSJohn Baldwin 
13745fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
13755fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
137696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13775fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
137896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
13795fcfab6eSJohn Baldwin 
13805fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
138196a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)),
13825fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
138396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[1]);
13845fcfab6eSJohn Baldwin 
138596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13865fcfab6eSJohn Baldwin 
13875fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13885fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13895fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
139096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
13915fcfab6eSJohn Baldwin 
13925fcfab6eSJohn Baldwin 	wpid = wait(&status);
139396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
139496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
13955fcfab6eSJohn Baldwin }
13965fcfab6eSJohn Baldwin 
13975fcfab6eSJohn Baldwin static void *
13985fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
13995fcfab6eSJohn Baldwin {
14005fcfab6eSJohn Baldwin 
14015fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
14025fcfab6eSJohn Baldwin 	exit(127);
14035fcfab6eSJohn Baldwin }
14045fcfab6eSJohn Baldwin 
14055fcfab6eSJohn Baldwin static __dead2 void
14065fcfab6eSJohn Baldwin exec_thread_main(void)
14075fcfab6eSJohn Baldwin {
14085fcfab6eSJohn Baldwin 	pthread_t thread;
14095fcfab6eSJohn Baldwin 
141096a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_create(&thread, NULL, exec_thread, NULL), 0);
14115fcfab6eSJohn Baldwin 	for (;;)
14125fcfab6eSJohn Baldwin 		sleep(60);
14135fcfab6eSJohn Baldwin 	exit(1);
14145fcfab6eSJohn Baldwin }
14155fcfab6eSJohn Baldwin 
14165fcfab6eSJohn Baldwin /*
14175fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
14185fcfab6eSJohn Baldwin  * process that calls execve(2).
14195fcfab6eSJohn Baldwin  */
14205fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
14215fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
14225fcfab6eSJohn Baldwin {
14235fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
14245fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
14255fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
14265fcfab6eSJohn Baldwin 	int status;
14275fcfab6eSJohn Baldwin 
14285fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14295fcfab6eSJohn Baldwin 	if (fpid == 0) {
14305fcfab6eSJohn Baldwin 		trace_me();
14315fcfab6eSJohn Baldwin 		exec_thread_main();
14325fcfab6eSJohn Baldwin 	}
14335fcfab6eSJohn Baldwin 
14345fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14355fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
143696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14375fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
143896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
14395fcfab6eSJohn Baldwin 
14405fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
14415fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
14425fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
14435fcfab6eSJohn Baldwin 
144496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
14455fcfab6eSJohn Baldwin 
14465fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
144796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14485fcfab6eSJohn Baldwin 
14495fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
14505fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
145196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14525fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
145396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14545fcfab6eSJohn Baldwin 
14555fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
145696a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
14575fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
14585fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
14595fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
14605fcfab6eSJohn Baldwin 
146196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14625fcfab6eSJohn Baldwin 
14635fcfab6eSJohn Baldwin 	/*
14645fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
14655fcfab6eSJohn Baldwin 	 * single threading from execve().
14665fcfab6eSJohn Baldwin 	 */
14675fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
146896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14695fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
147096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14715fcfab6eSJohn Baldwin 
14725fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
147396a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)),
14745fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
147596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[0]);
14765fcfab6eSJohn Baldwin 
147796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14785fcfab6eSJohn Baldwin 
14795fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
14805fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14815fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
148296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14835fcfab6eSJohn Baldwin 
14845fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
148596a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)),
14865fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
148796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[1]);
14885fcfab6eSJohn Baldwin 
148996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14905fcfab6eSJohn Baldwin 
14915fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
14925fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14935fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
149496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
14955fcfab6eSJohn Baldwin 
14965fcfab6eSJohn Baldwin 	wpid = wait(&status);
149796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
149896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
14995fcfab6eSJohn Baldwin }
15005fcfab6eSJohn Baldwin 
15013340c45bSJohn Baldwin static void
15023340c45bSJohn Baldwin handler(int sig __unused)
15033340c45bSJohn Baldwin {
15043340c45bSJohn Baldwin }
15053340c45bSJohn Baldwin 
15063340c45bSJohn Baldwin static void
15073340c45bSJohn Baldwin signal_main(void)
15083340c45bSJohn Baldwin {
15093340c45bSJohn Baldwin 
15103340c45bSJohn Baldwin 	signal(SIGINFO, handler);
15113340c45bSJohn Baldwin 	raise(SIGINFO);
15123340c45bSJohn Baldwin 	exit(0);
15133340c45bSJohn Baldwin }
15143340c45bSJohn Baldwin 
15153340c45bSJohn Baldwin /*
15163340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
15173340c45bSJohn Baldwin  */
15183340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
15193340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
15203340c45bSJohn Baldwin {
15213340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
15223340c45bSJohn Baldwin 	pid_t fpid, wpid;
15233340c45bSJohn Baldwin 	int status;
15243340c45bSJohn Baldwin 
15253340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15263340c45bSJohn Baldwin 	if (fpid == 0) {
15273340c45bSJohn Baldwin 		trace_me();
15283340c45bSJohn Baldwin 		signal_main();
15293340c45bSJohn Baldwin 	}
15303340c45bSJohn Baldwin 
15313340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15323340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
153396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
15343340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
153596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15363340c45bSJohn Baldwin 
153796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15383340c45bSJohn Baldwin 
15393340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
15403340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15413340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
154296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGINFO);
15433340c45bSJohn Baldwin 
15443340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
154596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
15463340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
154796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, SI_LWP);
154896a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_pid, wpid);
15493340c45bSJohn Baldwin 
155096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15513340c45bSJohn Baldwin 
15523340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
15533340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15543340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
155596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
15563340c45bSJohn Baldwin 
15573340c45bSJohn Baldwin 	wpid = wait(&status);
155896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
155996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15603340c45bSJohn Baldwin }
15613340c45bSJohn Baldwin 
15628d570f64SJohn Baldwin /*
15638d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
15648d570f64SJohn Baldwin  */
15658d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
15668d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
15678d570f64SJohn Baldwin {
15688d570f64SJohn Baldwin 	pid_t fpid, wpid;
15698d570f64SJohn Baldwin 	int events, status;
15708d570f64SJohn Baldwin 
15718d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15728d570f64SJohn Baldwin 	if (fpid == 0) {
15738d570f64SJohn Baldwin 		trace_me();
15748d570f64SJohn Baldwin 		exec_thread(NULL);
15758d570f64SJohn Baldwin 	}
15768d570f64SJohn Baldwin 
15778d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15788d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
157996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
15808d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
158196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15828d570f64SJohn Baldwin 
15838d570f64SJohn Baldwin 	events = 0;
15848d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15858d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15868d570f64SJohn Baldwin 
158796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15888d570f64SJohn Baldwin 
15898d570f64SJohn Baldwin 	/* Should get one event at exit. */
15908d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15918d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
159296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
15938d570f64SJohn Baldwin 
15948d570f64SJohn Baldwin 	wpid = wait(&status);
159596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
159696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15978d570f64SJohn Baldwin }
15988d570f64SJohn Baldwin 
15998d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
16008d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
16018d570f64SJohn Baldwin {
16028d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
16038d570f64SJohn Baldwin 	pid_t fpid, wpid;
16048d570f64SJohn Baldwin 	int events, status;
16058d570f64SJohn Baldwin 
16068d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16078d570f64SJohn Baldwin 	if (fpid == 0) {
16088d570f64SJohn Baldwin 		trace_me();
16098d570f64SJohn Baldwin 		exec_thread(NULL);
16108d570f64SJohn Baldwin 	}
16118d570f64SJohn Baldwin 
16128d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16138d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
161496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
16158d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
161696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
16178d570f64SJohn Baldwin 
16188d570f64SJohn Baldwin 	events = PTRACE_EXEC;
16198d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
16208d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16218d570f64SJohn Baldwin 
162296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16238d570f64SJohn Baldwin 
16248d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
16258d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16268d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
162796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
16288d570f64SJohn Baldwin 
16298d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
163096a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)),
16318d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
16328d570f64SJohn Baldwin 
163396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16348d570f64SJohn Baldwin 
16358d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
16368d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16378d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
163896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16398d570f64SJohn Baldwin 
16408d570f64SJohn Baldwin 	wpid = wait(&status);
164196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
164296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
16438d570f64SJohn Baldwin }
16448d570f64SJohn Baldwin 
16458d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
16468d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
16478d570f64SJohn Baldwin {
16488d570f64SJohn Baldwin 	pid_t fpid, wpid;
16498d570f64SJohn Baldwin 	int events, status;
16508d570f64SJohn Baldwin 
16518d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16528d570f64SJohn Baldwin 	if (fpid == 0) {
16538d570f64SJohn Baldwin 		trace_me();
16548d570f64SJohn Baldwin 		exit(0);
16558d570f64SJohn Baldwin 	}
16568d570f64SJohn Baldwin 
16578d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16588d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
165996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
16608d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
166196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
16628d570f64SJohn Baldwin 
16638d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
16648d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
16658d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16668d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16678d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_FORK);
16688d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
16698d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16708d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16718d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_FORK));
16728d570f64SJohn Baldwin 
16738d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
16748d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, 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_LWP);
16788d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, 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_LWP));
16828d570f64SJohn Baldwin 
168396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16848d570f64SJohn Baldwin 
16858d570f64SJohn Baldwin 	/* Should get one event at exit. */
16868d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16878d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
168896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16898d570f64SJohn Baldwin 
16908d570f64SJohn Baldwin 	wpid = wait(&status);
169196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
169296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
16938d570f64SJohn Baldwin }
16948d570f64SJohn Baldwin 
1695fc4f075aSJohn Baldwin /*
1696fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1697fc4f075aSJohn Baldwin  */
1698fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
1699fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1700fc4f075aSJohn Baldwin {
1701fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1702fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1703fc4f075aSJohn Baldwin 	int events, status;
1704fc4f075aSJohn Baldwin 
1705fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1706fc4f075aSJohn Baldwin 	if (fpid == 0) {
1707fc4f075aSJohn Baldwin 		trace_me();
1708fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1709fc4f075aSJohn Baldwin 	}
1710fc4f075aSJohn Baldwin 
1711fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1712fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
171396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1714fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
171596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1716fc4f075aSJohn Baldwin 
1717fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1718fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1719fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1720fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1721fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1722fc4f075aSJohn Baldwin 
1723fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1724fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1725fc4f075aSJohn Baldwin 
1726fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1727fc4f075aSJohn Baldwin 	wpid = wait(&status);
172896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1729fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
173096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1731fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1732fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1733fc4f075aSJohn Baldwin 
1734fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1735fc4f075aSJohn Baldwin 
1736fc4f075aSJohn Baldwin 	wpid = wait(&status);
173796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1738fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
173996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1740fc4f075aSJohn Baldwin 
1741fc4f075aSJohn Baldwin 	wpid = wait(&status);
174296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
174396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1744fc4f075aSJohn Baldwin }
1745fc4f075aSJohn Baldwin 
1746fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
1747fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1748fc4f075aSJohn Baldwin {
1749fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1750fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1751fc4f075aSJohn Baldwin 	int events, status;
1752fc4f075aSJohn Baldwin 
1753fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1754fc4f075aSJohn Baldwin 	if (fpid == 0) {
1755fc4f075aSJohn Baldwin 		trace_me();
1756fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1757fc4f075aSJohn Baldwin 	}
1758fc4f075aSJohn Baldwin 
1759fc4f075aSJohn Baldwin 	/* Parent process. */
1760fc4f075aSJohn Baldwin 	children[0] = fpid;
1761fc4f075aSJohn Baldwin 
1762fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1763fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
176496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1765fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
176696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1767fc4f075aSJohn Baldwin 
1768fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1769fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1770fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1771fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1772fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1773fc4f075aSJohn Baldwin 
1774fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1775fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1776fc4f075aSJohn Baldwin 
1777fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1778fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1779fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1780fc4f075aSJohn Baldwin 
1781fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1782fc4f075aSJohn Baldwin 
1783fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1784fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1785fc4f075aSJohn Baldwin 
1786fc4f075aSJohn Baldwin 	/*
1787fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1788fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1789fc4f075aSJohn Baldwin 	 */
1790fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
179196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1792fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
179396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1794fc4f075aSJohn Baldwin 
1795fc4f075aSJohn Baldwin 	/*
1796fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1797fc4f075aSJohn Baldwin 	 * exits.
1798fc4f075aSJohn Baldwin 	 */
1799fc4f075aSJohn Baldwin 	wpid = wait(&status);
180096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1801fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
180296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1803fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1804fc4f075aSJohn Baldwin 	    -1);
1805fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1806fc4f075aSJohn Baldwin 
1807fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1808fc4f075aSJohn Baldwin 
1809fc4f075aSJohn Baldwin 	wpid = wait(&status);
181096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1811fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
181296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1813fc4f075aSJohn Baldwin 
1814fc4f075aSJohn Baldwin 	wpid = wait(&status);
181596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
181696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1817fc4f075aSJohn Baldwin }
1818fc4f075aSJohn Baldwin 
1819403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
1820e2ebfbbfSEric Badger /*
182182a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
182282a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
182382a4538fSEric Badger  */
182482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
182582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
182682a4538fSEric Badger {
182782a4538fSEric Badger 	pid_t fpid, wpid;
182882a4538fSEric Badger 	int status;
182982a4538fSEric Badger 
183082a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
183182a4538fSEric Badger 	if (fpid == 0) {
183282a4538fSEric Badger 		trace_me();
18339e0d1159SEric Badger 		breakpoint();
183482a4538fSEric Badger 		exit(1);
183582a4538fSEric Badger 	}
183682a4538fSEric Badger 
183782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
183882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
183996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
184082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
184196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
184282a4538fSEric Badger 
184382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
184496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
184582a4538fSEric Badger 
184682a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
184782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
184896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
184982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
185096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
185182a4538fSEric Badger 
185282a4538fSEric Badger 	/* Kill the child process. */
185396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
185482a4538fSEric Badger 
185582a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
185682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
185796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
185882a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
185996a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
186082a4538fSEric Badger 
186182a4538fSEric Badger 	wpid = wait(&status);
186296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
186396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
186482a4538fSEric Badger }
1865403e331dSJohn Baldwin #endif /* HAVE_BREAKPOINT */
186682a4538fSEric Badger 
186782a4538fSEric Badger /*
186882a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
186982a4538fSEric Badger  * process exit when stopped inside of a system call.
187082a4538fSEric Badger  */
187182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
187282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
187382a4538fSEric Badger {
187482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
187582a4538fSEric Badger 	pid_t fpid, wpid;
187682a4538fSEric Badger 	int status;
187782a4538fSEric Badger 
187882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
187982a4538fSEric Badger 	if (fpid == 0) {
188082a4538fSEric Badger 		trace_me();
188182a4538fSEric Badger 		getpid();
188282a4538fSEric Badger 		exit(1);
188382a4538fSEric Badger 	}
188482a4538fSEric Badger 
188582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
188682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
188796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
188882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
188996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
189082a4538fSEric Badger 
189182a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
189296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
189382a4538fSEric Badger 
189482a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
189582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
189696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
189782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
189896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
189982a4538fSEric Badger 
190082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
190182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
190282a4538fSEric Badger 
190382a4538fSEric Badger 	/* Kill the child process. */
190496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
190582a4538fSEric Badger 
190682a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
190782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
190896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
190982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
191096a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
191182a4538fSEric Badger 
191282a4538fSEric Badger 	wpid = wait(&status);
191396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
191496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
191582a4538fSEric Badger }
191682a4538fSEric Badger 
191782a4538fSEric Badger /*
191882a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
191982a4538fSEric Badger  * process exit when killing a multithreaded process.
192082a4538fSEric Badger  */
192182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
192282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
192382a4538fSEric Badger {
192482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
192582a4538fSEric Badger 	pid_t fpid, wpid;
192682a4538fSEric Badger 	lwpid_t main_lwp;
192782a4538fSEric Badger 	int status;
192882a4538fSEric Badger 
192982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
193082a4538fSEric Badger 	if (fpid == 0) {
193182a4538fSEric Badger 		trace_me();
193282a4538fSEric Badger 		simple_thread_main();
193382a4538fSEric Badger 	}
193482a4538fSEric Badger 
193582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
193682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
193796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
193882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
193996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
194082a4538fSEric Badger 
194182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
194282a4538fSEric Badger 	    sizeof(pl)) != -1);
194382a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
194482a4538fSEric Badger 
194596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
194682a4538fSEric Badger 
194782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
194896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
194982a4538fSEric Badger 
195082a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
195182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
195296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
195382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
195496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
195582a4538fSEric Badger 
195682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
195796a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
195882a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
195982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
196082a4538fSEric Badger 
196182a4538fSEric Badger 	/* Kill the child process. */
196296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
196382a4538fSEric Badger 
196482a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
196582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
196696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
196782a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
196896a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
196982a4538fSEric Badger 
197082a4538fSEric Badger 	wpid = wait(&status);
197196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
197296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
197382a4538fSEric Badger }
197482a4538fSEric Badger 
197582a4538fSEric Badger static void *
197682a4538fSEric Badger mask_usr1_thread(void *arg)
197782a4538fSEric Badger {
197882a4538fSEric Badger 	pthread_barrier_t *pbarrier;
197982a4538fSEric Badger 	sigset_t sigmask;
198082a4538fSEric Badger 
198182a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
198282a4538fSEric Badger 
198382a4538fSEric Badger 	sigemptyset(&sigmask);
198482a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
198596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
198682a4538fSEric Badger 
198782a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
198882a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
198982a4538fSEric Badger 
199082a4538fSEric Badger 	for (;;)
199182a4538fSEric Badger 		sleep(60);
199282a4538fSEric Badger 
199382a4538fSEric Badger 	return (NULL);
199482a4538fSEric Badger }
199582a4538fSEric Badger 
199682a4538fSEric Badger /*
199782a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
199882a4538fSEric Badger  * and prevents spurious stops due to those other signals.
199982a4538fSEric Badger  */
20003cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal);
20013cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
20023cf56bb4SEnji Cooper {
20033cf56bb4SEnji Cooper 
20043cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
20053cf56bb4SEnji Cooper }
200682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
200782a4538fSEric Badger {
200882a4538fSEric Badger 	pid_t fpid, wpid;
200982a4538fSEric Badger 	int status;
201082a4538fSEric Badger 	cpuset_t setmask;
201182a4538fSEric Badger 	pthread_t t;
201282a4538fSEric Badger 	pthread_barrier_t barrier;
2013bc2be1d3SEric Badger 	struct sched_param sched_param;
201482a4538fSEric Badger 
201582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
201682a4538fSEric Badger 	if (fpid == 0) {
2017bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
201882a4538fSEric Badger 		CPU_ZERO(&setmask);
201982a4538fSEric Badger 		CPU_SET(0, &setmask);
202082a4538fSEric Badger 		cpusetid_t setid;
202196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(cpuset(&setid), 0);
202282a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
202382a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
202482a4538fSEric Badger 
202596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
202682a4538fSEric Badger 
202782a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
202882a4538fSEric Badger 		    (void*)&barrier) == 0);
202982a4538fSEric Badger 
2030bc2be1d3SEric Badger 		/*
2031bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2032bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2033bc2be1d3SEric Badger 		 * thread runs first.
2034bc2be1d3SEric Badger 		 */
2035bc2be1d3SEric Badger 		sched_param.sched_priority =
2036bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2037bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2038bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2039bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2040bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2041bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2042bc2be1d3SEric Badger 		    &sched_param) == 0);
2043bc2be1d3SEric Badger 
204482a4538fSEric Badger 		sigset_t sigmask;
204582a4538fSEric Badger 		sigemptyset(&sigmask);
204682a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
204796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
204882a4538fSEric Badger 
204982a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
205082a4538fSEric Badger 		pthread_barrier_wait(&barrier);
205182a4538fSEric Badger 
205282a4538fSEric Badger 		trace_me();
205382a4538fSEric Badger 
205482a4538fSEric Badger 		for (;;)
205582a4538fSEric Badger 			sleep(60);
205682a4538fSEric Badger 
205782a4538fSEric Badger 		exit(1);
205882a4538fSEric Badger 	}
205982a4538fSEric Badger 
206082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
206182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
206296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
206382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
206496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
206582a4538fSEric Badger 
206682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
206796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
206882a4538fSEric Badger 
206982a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
207096a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
207182a4538fSEric Badger 
207282a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
207382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
207496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
207582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
207696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
207782a4538fSEric Badger 
207882a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
207996a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
208082a4538fSEric Badger 
208182a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
208296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
208382a4538fSEric Badger 
208482a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
208582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
208696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
208782a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
208896a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
208982a4538fSEric Badger 
209082a4538fSEric Badger 	wpid = wait(&status);
209196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
209296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
209382a4538fSEric Badger }
209482a4538fSEric Badger 
209582a4538fSEric Badger /*
209682a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
209782a4538fSEric Badger  * and prevents spurious stops caused by those events.
209882a4538fSEric Badger  */
20993cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop);
21003cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc)
21013cf56bb4SEnji Cooper {
21023cf56bb4SEnji Cooper 
21033cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
21043cf56bb4SEnji Cooper }
210582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
210682a4538fSEric Badger {
210782a4538fSEric Badger 	pid_t fpid, wpid;
2108bc2be1d3SEric Badger 	int status;
210982a4538fSEric Badger 	cpuset_t setmask;
211082a4538fSEric Badger 	pthread_t t;
211182a4538fSEric Badger 	pthread_barrier_t barrier;
211282a4538fSEric Badger 	lwpid_t main_lwp;
211382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2114bc2be1d3SEric Badger 	struct sched_param sched_param;
211582a4538fSEric Badger 
211682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
211782a4538fSEric Badger 	if (fpid == 0) {
211882a4538fSEric Badger 		trace_me();
211982a4538fSEric Badger 
2120bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
212182a4538fSEric Badger 		CPU_ZERO(&setmask);
212282a4538fSEric Badger 		CPU_SET(0, &setmask);
212382a4538fSEric Badger 		cpusetid_t setid;
212496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(cpuset(&setid), 0);
212582a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
212682a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
212782a4538fSEric Badger 
212896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
212982a4538fSEric Badger 
213082a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
213182a4538fSEric Badger 		    (void*)&barrier) == 0);
213282a4538fSEric Badger 
2133bc2be1d3SEric Badger 		/*
2134bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2135bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2136bc2be1d3SEric Badger 		 * thread runs first.
2137bc2be1d3SEric Badger 		 */
2138bc2be1d3SEric Badger 		sched_param.sched_priority =
2139bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2140bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2141bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2142bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2143bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2144bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2145bc2be1d3SEric Badger 		    &sched_param) == 0);
2146bc2be1d3SEric Badger 
214782a4538fSEric Badger 		sigset_t sigmask;
214882a4538fSEric Badger 		sigemptyset(&sigmask);
214982a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
215096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
215182a4538fSEric Badger 
215282a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
215382a4538fSEric Badger 		pthread_barrier_wait(&barrier);
215482a4538fSEric Badger 
215582a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
215682a4538fSEric Badger 		raise(SIGSTOP);
215782a4538fSEric Badger 
215882a4538fSEric Badger 		getpid();
215982a4538fSEric Badger 		exit(1);
216082a4538fSEric Badger 	}
216182a4538fSEric Badger 
216282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
216382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
216496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
216582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
216696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
216782a4538fSEric Badger 
216882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
216982a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
217082a4538fSEric Badger 
217182a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
217296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
217382a4538fSEric Badger 
217482a4538fSEric Badger 	/*
217582a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
217682a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
217782a4538fSEric Badger 	 */
217882a4538fSEric Badger 	for (;;) {
217982a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
218096a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
218182a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
218282a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
218382a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
218482a4538fSEric Badger 			    sizeof(pl)) != -1);
218582a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
218682a4538fSEric Badger 		} else {
218796a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
218882a4538fSEric Badger 			break;
218982a4538fSEric Badger 		}
219096a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
219182a4538fSEric Badger 	}
219282a4538fSEric Badger 
2193bc2be1d3SEric Badger 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
219496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
219582a4538fSEric Badger 
219682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
219796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
219882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
219996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
220082a4538fSEric Badger 
220182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
220282a4538fSEric Badger 	    sizeof(pl)) != -1);
220396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, main_lwp);
220482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
2205bc2be1d3SEric Badger 	/* Prevent the main thread from hitting its syscall exit for now. */
220696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SUSPEND, main_lwp, 0, 0), 0);
220782a4538fSEric Badger 
2208bc2be1d3SEric Badger 	/*
2209bc2be1d3SEric Badger 	 * Proceed, allowing second thread to hit syscall exit for
2210bc2be1d3SEric Badger 	 * pthread_barrier_wait().
2211bc2be1d3SEric Badger 	 */
221296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
2213bc2be1d3SEric Badger 
2214bc2be1d3SEric Badger 	wpid = waitpid(fpid, &status, 0);
221596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2216bc2be1d3SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
221796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
2218bc2be1d3SEric Badger 
2219bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
2220bc2be1d3SEric Badger 	    sizeof(pl)) != -1);
2221bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
2222bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
222382a4538fSEric Badger 
222482a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
222596a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
222682a4538fSEric Badger 
222796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
222882a4538fSEric Badger 
2229bc2be1d3SEric Badger 	/* The next wait() should report the SIGUSR2. */
223082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
223196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
223282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
223396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
223482a4538fSEric Badger 
223582a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
223696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_RESUME, main_lwp, 0, 0), 0);
223782a4538fSEric Badger 
223882a4538fSEric Badger 	/*
223982a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
2240bc2be1d3SEric Badger 	 * has been resumed. The second thread has taken a SIGUSR2 which will
2241bc2be1d3SEric Badger 	 * be replaced with a SIGKILL below. The main thread will get to run
2242bc2be1d3SEric Badger 	 * first. It should notice the kill request (even though the signal
2243bc2be1d3SEric Badger 	 * replacement occurred in the other thread) and exit accordingly.  It
2244bc2be1d3SEric Badger 	 * should not stop for the system call exit event.
224582a4538fSEric Badger 	 */
224682a4538fSEric Badger 
224782a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
224896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
224982a4538fSEric Badger 
225082a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
225182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
225296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
225382a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
225496a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
225582a4538fSEric Badger 
225682a4538fSEric Badger 	wpid = wait(&status);
225796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
225896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
225982a4538fSEric Badger }
226082a4538fSEric Badger 
226182a4538fSEric Badger static void
226282a4538fSEric Badger sigusr1_handler(int sig)
226382a4538fSEric Badger {
226482a4538fSEric Badger 
226596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
226682a4538fSEric Badger 	_exit(2);
226782a4538fSEric Badger }
226882a4538fSEric Badger 
226982a4538fSEric Badger /*
227082a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
227182a4538fSEric Badger  * a PT_KILL will kill the process.
227282a4538fSEric Badger  */
227382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
227482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
227582a4538fSEric Badger {
227682a4538fSEric Badger 	pid_t fpid, wpid;
227782a4538fSEric Badger 	int status;
227882a4538fSEric Badger 	int max_pending_per_proc;
227982a4538fSEric Badger 	size_t len;
228082a4538fSEric Badger 	int i;
228182a4538fSEric Badger 
228282a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
228382a4538fSEric Badger 
228482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
228582a4538fSEric Badger 	if (fpid == 0) {
228682a4538fSEric Badger 		trace_me();
228782a4538fSEric Badger 		exit(1);
228882a4538fSEric Badger 	}
228982a4538fSEric Badger 
229082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
229182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
229296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
229382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
229496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
229582a4538fSEric Badger 
229682a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
229782a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
229882a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
229982a4538fSEric Badger 
230082a4538fSEric Badger 	/* Fill the signal queue. */
230182a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
230296a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
230382a4538fSEric Badger 
230482a4538fSEric Badger 	/* Kill the child process. */
230596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
230682a4538fSEric Badger 
230782a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
230882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
230996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
231082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
231196a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
231282a4538fSEric Badger 
231382a4538fSEric Badger 	wpid = wait(&status);
231496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
231596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
231682a4538fSEric Badger }
231782a4538fSEric Badger 
231882a4538fSEric Badger /*
231982a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
232082a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
232182a4538fSEric Badger  * call is complete.
232282a4538fSEric Badger  */
232382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
232482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
232582a4538fSEric Badger {
232682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
232782a4538fSEric Badger 	pid_t fpid, wpid;
232882a4538fSEric Badger 	int status;
232982a4538fSEric Badger 
233082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
233182a4538fSEric Badger 
233282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
233382a4538fSEric Badger 	if (fpid == 0) {
233482a4538fSEric Badger 		trace_me();
233582a4538fSEric Badger 		getpid();
233682a4538fSEric Badger 		exit(1);
233782a4538fSEric Badger 	}
233882a4538fSEric Badger 
233982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
234082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
234196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
234282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
234396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
234482a4538fSEric Badger 
234582a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
234696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
234782a4538fSEric Badger 
234882a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
234982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
235096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
235182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
235296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
235382a4538fSEric Badger 
235482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
235582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
235682a4538fSEric Badger 
235782a4538fSEric Badger 	/* Continue the child process with a signal. */
235896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
235982a4538fSEric Badger 
236082a4538fSEric Badger 	for (;;) {
236182a4538fSEric Badger 		/*
236282a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
236382a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
236482a4538fSEric Badger 		 * past any syscall stops.
236582a4538fSEric Badger 		 */
236682a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
236796a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
236882a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
236982a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
237082a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
237196a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
237282a4538fSEric Badger 		} else {
237382a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
237496a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
237582a4538fSEric Badger 			break;
237682a4538fSEric Badger 		}
237782a4538fSEric Badger 	}
237882a4538fSEric Badger 
237982a4538fSEric Badger 	wpid = wait(&status);
238096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
238196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
238282a4538fSEric Badger }
238382a4538fSEric Badger 
238482a4538fSEric Badger static void
238582a4538fSEric Badger sigusr1_counting_handler(int sig)
238682a4538fSEric Badger {
238782a4538fSEric Badger 	static int counter = 0;
238882a4538fSEric Badger 
238996a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
239082a4538fSEric Badger 	counter++;
239182a4538fSEric Badger 	if (counter == 2)
239282a4538fSEric Badger 		_exit(2);
239382a4538fSEric Badger }
239482a4538fSEric Badger 
239582a4538fSEric Badger /*
239682a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
239782a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
239882a4538fSEric Badger  * the system call is complete.
239982a4538fSEric Badger  */
240082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
240182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
240282a4538fSEric Badger {
240382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
240482a4538fSEric Badger 	pid_t fpid, wpid;
240582a4538fSEric Badger 	int status;
240682a4538fSEric Badger 
240782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
240882a4538fSEric Badger 
240982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
241082a4538fSEric Badger 	if (fpid == 0) {
241182a4538fSEric Badger 		trace_me();
241282a4538fSEric Badger 		getpid();
241382a4538fSEric Badger 		exit(1);
241482a4538fSEric Badger 	}
241582a4538fSEric Badger 
241682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
241782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
241896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
241982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
242096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
242182a4538fSEric Badger 
242282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
242396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
242482a4538fSEric Badger 
242582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
242682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
242796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
242882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
242996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
243082a4538fSEric Badger 
243182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
243282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
243382a4538fSEric Badger 
243482a4538fSEric Badger 	/* Continue the child process with a signal. */
243596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
243682a4538fSEric Badger 
243782a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
243882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
243996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
244082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
244196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
244282a4538fSEric Badger 
244382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
244482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
244582a4538fSEric Badger 
244682a4538fSEric Badger 	/* Continue the child process with a signal. */
244796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
244882a4538fSEric Badger 
244982a4538fSEric Badger 	for (;;) {
245082a4538fSEric Badger 		/*
245182a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
245282a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
245382a4538fSEric Badger 		 * past any syscall stops.
245482a4538fSEric Badger 		 */
245582a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
245696a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
245782a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
245882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
245982a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
246096a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
246182a4538fSEric Badger 		} else {
246282a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
246396a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
246482a4538fSEric Badger 			break;
246582a4538fSEric Badger 		}
246682a4538fSEric Badger 	}
246782a4538fSEric Badger 
246882a4538fSEric Badger 	wpid = wait(&status);
246996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
247096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
247182a4538fSEric Badger }
247282a4538fSEric Badger 
247382a4538fSEric Badger /*
247482a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
247582a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
247682a4538fSEric Badger  */
247782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
247882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
247982a4538fSEric Badger {
248082a4538fSEric Badger 	pid_t fpid, wpid;
248182a4538fSEric Badger 	int status;
248282a4538fSEric Badger 	int max_pending_per_proc;
248382a4538fSEric Badger 	size_t len;
248482a4538fSEric Badger 	int i;
248582a4538fSEric Badger 
248682a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
248782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
248882a4538fSEric Badger 
248982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
249082a4538fSEric Badger 	if (fpid == 0) {
249182a4538fSEric Badger 		trace_me();
249282a4538fSEric Badger 		exit(1);
249382a4538fSEric Badger 	}
249482a4538fSEric Badger 
249582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
249682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
249796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
249882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
249996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
250082a4538fSEric Badger 
250182a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
250282a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
250382a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
250482a4538fSEric Badger 
250582a4538fSEric Badger 	/* Fill the signal queue. */
250682a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
250796a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
250882a4538fSEric Badger 
250982a4538fSEric Badger 	/* Continue with signal. */
251096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
251182a4538fSEric Badger 
251282a4538fSEric Badger 	for (;;) {
251382a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
251496a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
251582a4538fSEric Badger 		if (WIFSTOPPED(status)) {
251696a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
251796a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
251882a4538fSEric Badger 		} else {
251982a4538fSEric Badger 			/*
252082a4538fSEric Badger 			 * The last wait() should report normal _exit from the
252182a4538fSEric Badger 			 * SIGUSR1 handler.
252282a4538fSEric Badger 			 */
252382a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
252496a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
252582a4538fSEric Badger 			break;
252682a4538fSEric Badger 		}
252782a4538fSEric Badger 	}
252882a4538fSEric Badger 
252982a4538fSEric Badger 	wpid = wait(&status);
253096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
253196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
253282a4538fSEric Badger }
253382a4538fSEric Badger 
2534753e2922SBryan Drewery static sem_t sigusr1_sem;
2535753e2922SBryan Drewery static int got_usr1;
2536753e2922SBryan Drewery 
2537753e2922SBryan Drewery static void
2538753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused)
2539753e2922SBryan Drewery {
2540753e2922SBryan Drewery 
2541753e2922SBryan Drewery 	got_usr1++;
254296a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sem_post(&sigusr1_sem), 0);
2543753e2922SBryan Drewery }
2544753e2922SBryan Drewery 
2545753e2922SBryan Drewery /*
2546753e2922SBryan Drewery  * Verify that even if the signal queue is full for a child process,
2547753e2922SBryan Drewery  * and the signal is masked, a PT_CONTINUE with a signal will not
2548753e2922SBryan Drewery  * result in loss of that signal.
2549753e2922SBryan Drewery  */
2550753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
2551753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
2552753e2922SBryan Drewery {
2553753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2554753e2922SBryan Drewery 	pid_t fpid, wpid;
2555753e2922SBryan Drewery 	int status, err;
2556753e2922SBryan Drewery 	int max_pending_per_proc;
2557753e2922SBryan Drewery 	size_t len;
2558753e2922SBryan Drewery 	int i;
2559753e2922SBryan Drewery 	sigset_t sigmask;
2560753e2922SBryan Drewery 
2561753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
256296a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
2563753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2564753e2922SBryan Drewery 
2565753e2922SBryan Drewery 	got_usr1 = 0;
2566753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2567753e2922SBryan Drewery 	if (fpid == 0) {
256896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
256996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
257096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
2571753e2922SBryan Drewery 
2572753e2922SBryan Drewery 		trace_me();
257396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
2574753e2922SBryan Drewery 
2575753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
257696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
2577753e2922SBryan Drewery 		/* Wait to receive the SIGUSR1. */
2578753e2922SBryan Drewery 		do {
2579753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2580753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2581753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
258296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
2583753e2922SBryan Drewery 		exit(1);
2584753e2922SBryan Drewery 	}
2585753e2922SBryan Drewery 
2586753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2587753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
258896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2589753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
259096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
2591753e2922SBryan Drewery 
2592753e2922SBryan Drewery 	len = sizeof(max_pending_per_proc);
2593753e2922SBryan Drewery 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
2594753e2922SBryan Drewery 	    &max_pending_per_proc, &len, NULL, 0) == 0);
2595753e2922SBryan Drewery 
2596753e2922SBryan Drewery 	/* Fill the signal queue. */
2597753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i)
259896a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
2599753e2922SBryan Drewery 
2600753e2922SBryan Drewery 	/* Continue with signal. */
260196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
2602753e2922SBryan Drewery 
2603753e2922SBryan Drewery 	/* Collect and ignore all of the SIGUSR2. */
2604753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i) {
2605753e2922SBryan Drewery 		wpid = waitpid(fpid, &status, 0);
260696a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
2607753e2922SBryan Drewery 		ATF_REQUIRE(WIFSTOPPED(status));
260896a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
260996a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2610753e2922SBryan Drewery 	}
2611753e2922SBryan Drewery 
2612753e2922SBryan Drewery 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
2613753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
261496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2615753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
261696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
2617753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
261896a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
2619753e2922SBryan Drewery 
2620753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
262196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2622753e2922SBryan Drewery 
2623753e2922SBryan Drewery 	/* The last wait() should report exit after receiving SIGUSR1. */
2624753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
262596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2626753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
262796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
2628753e2922SBryan Drewery 
2629753e2922SBryan Drewery 	wpid = wait(&status);
263096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
263196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
2632753e2922SBryan Drewery }
2633753e2922SBryan Drewery 
263482a4538fSEric Badger /*
263582a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
263682a4538fSEric Badger  * replaced with another signal.
263782a4538fSEric Badger  */
263882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
263982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
264082a4538fSEric Badger {
264182a4538fSEric Badger 	struct ptrace_lwpinfo pl;
264282a4538fSEric Badger 	pid_t fpid, wpid;
264382a4538fSEric Badger 	int status;
264482a4538fSEric Badger 
264582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
264682a4538fSEric Badger 	if (fpid == 0) {
264782a4538fSEric Badger 		trace_me();
264882a4538fSEric Badger 		sleep(20);
264982a4538fSEric Badger 		exit(1);
265082a4538fSEric Badger 	}
265182a4538fSEric Badger 
265282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
265382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
265496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
265582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
265696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
265782a4538fSEric Badger 
265896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
265982a4538fSEric Badger 
266082a4538fSEric Badger 	/* Send a signal without ptrace. */
266196a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGINT), 0);
266282a4538fSEric Badger 
266382a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
266482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
266596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
266682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
266796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGINT);
266882a4538fSEric Badger 
266982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
267082a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
267196a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGINT);
267282a4538fSEric Badger 
267382a4538fSEric Badger 	/* Continue the child process with a different signal. */
267496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM), 0);
267582a4538fSEric Badger 
267682a4538fSEric Badger 	/*
267782a4538fSEric Badger 	 * The last wait() should report having died due to the new
267882a4538fSEric Badger 	 * signal, SIGTERM.
267982a4538fSEric Badger 	 */
268082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
268196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
268282a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
268396a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGTERM);
268482a4538fSEric Badger 
268582a4538fSEric Badger 	wpid = wait(&status);
268696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
268796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
268882a4538fSEric Badger }
268982a4538fSEric Badger 
269082a4538fSEric Badger /*
269182a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
269282a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
269382a4538fSEric Badger  * invented for e.g, system call stops.
269482a4538fSEric Badger  */
269582a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
269682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
269782a4538fSEric Badger {
269882a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2699fc1e29dcSBryan Drewery 	struct rlimit rl;
270082a4538fSEric Badger 	pid_t fpid, wpid;
270182a4538fSEric Badger 	int status;
270282a4538fSEric Badger 
270382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
270482a4538fSEric Badger 	if (fpid == 0) {
270582a4538fSEric Badger 		trace_me();
2706fc1e29dcSBryan Drewery 		/* SIGTRAP expected to cause exit on syscall entry. */
2707fc1e29dcSBryan Drewery 		rl.rlim_cur = rl.rlim_max = 0;
270896a9e50eSAlex Richardson 		REQUIRE_EQ(setrlimit(RLIMIT_CORE, &rl), 0);
270982a4538fSEric Badger 		getpid();
271082a4538fSEric Badger 		exit(1);
271182a4538fSEric Badger 	}
271282a4538fSEric Badger 
271382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
271482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
271596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
271682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
271796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
271882a4538fSEric Badger 
271982a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
272096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
272182a4538fSEric Badger 
272282a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
272382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
272496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
272582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
272696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
272782a4538fSEric Badger 
272882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
272982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
273082a4538fSEric Badger 
273182a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
273296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP), 0);
273382a4538fSEric Badger 
273482a4538fSEric Badger 	for (;;) {
273582a4538fSEric Badger 		/*
273682a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
273782a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
273882a4538fSEric Badger 		 */
273982a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
274096a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
274182a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
274282a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
274382a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
274496a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
274582a4538fSEric Badger 		} else {
274682a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
274796a9e50eSAlex Richardson 			REQUIRE_EQ(WTERMSIG(status), SIGTRAP);
274882a4538fSEric Badger 			break;
274982a4538fSEric Badger 		}
275082a4538fSEric Badger 	}
275182a4538fSEric Badger 
275282a4538fSEric Badger 	wpid = wait(&status);
275396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
275496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
275582a4538fSEric Badger }
275682a4538fSEric Badger 
275782a4538fSEric Badger /*
275882a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
275982a4538fSEric Badger  */
276082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
276182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
276282a4538fSEric Badger {
276382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
276482a4538fSEric Badger 	pid_t fpid, wpid;
276582a4538fSEric Badger 	int status;
276682a4538fSEric Badger 
276782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
276882a4538fSEric Badger 
276982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
277082a4538fSEric Badger 	if (fpid == 0) {
277182a4538fSEric Badger 		trace_me();
277282a4538fSEric Badger 		getpid();
277382a4538fSEric Badger 		exit(1);
277482a4538fSEric Badger 	}
277582a4538fSEric Badger 
277682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
277782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
277896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
277982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
278096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
278182a4538fSEric Badger 
278282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
278396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
278482a4538fSEric Badger 
278582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
278682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
278796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
278882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
278996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
279082a4538fSEric Badger 
279182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
279282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
279382a4538fSEric Badger 
279482a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
279596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
279682a4538fSEric Badger 
279782a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
279882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
279996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
280082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
280196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
280282a4538fSEric Badger 
280382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
280482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
280582a4538fSEric Badger 
280682a4538fSEric Badger 	/* Send an ABRT without ptrace. */
280796a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGABRT), 0);
280882a4538fSEric Badger 
280982a4538fSEric Badger 	/* Continue normally. */
281096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
281182a4538fSEric Badger 
281282a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
281382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
281496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
281582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
281696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
281782a4538fSEric Badger 
281882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
281982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
282096a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
282182a4538fSEric Badger 
282282a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
282396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
282482a4538fSEric Badger 
282582a4538fSEric Badger 	for (;;) {
282682a4538fSEric Badger 		/*
282782a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
282882a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
282982a4538fSEric Badger 		 * past any syscall stops.
283082a4538fSEric Badger 		 */
283182a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
283296a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
283382a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
283482a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
283582a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
283696a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
283782a4538fSEric Badger 		} else {
283882a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
283996a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
284082a4538fSEric Badger 			break;
284182a4538fSEric Badger 		}
284282a4538fSEric Badger 	}
284382a4538fSEric Badger 
284482a4538fSEric Badger 	wpid = wait(&status);
284596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
284696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
284782a4538fSEric Badger }
284882a4538fSEric Badger 
284982a4538fSEric Badger /*
285082a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
285182a4538fSEric Badger  */
285282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
285382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
285482a4538fSEric Badger {
285582a4538fSEric Badger 	pid_t fpid, wpid;
285682a4538fSEric Badger 	int status, kq, nevents;
285782a4538fSEric Badger 	struct kevent kev;
285882a4538fSEric Badger 
285982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
286082a4538fSEric Badger 
286182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
286282a4538fSEric Badger 	if (fpid == 0) {
286382a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
286482a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
286596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(kevent(kq, &kev, 1, NULL, 0, NULL), 0);
286682a4538fSEric Badger 
286782a4538fSEric Badger 		trace_me();
286882a4538fSEric Badger 
286982a4538fSEric Badger 		for (;;) {
287082a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
287182a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
287282a4538fSEric Badger 				continue;
287382a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
287496a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(kev.filter, EVFILT_SIGNAL);
2875*1fcbddecSAlex Richardson 			CHILD_REQUIRE_EQ(kev.ident, (uintptr_t)SIGUSR1);
287682a4538fSEric Badger 			break;
287782a4538fSEric Badger 		}
287882a4538fSEric Badger 
287982a4538fSEric Badger 		exit(1);
288082a4538fSEric Badger 	}
288182a4538fSEric Badger 
288282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
288382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
288496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
288582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
288696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
288782a4538fSEric Badger 
288882a4538fSEric Badger 	/* Continue with the SIGUSR1. */
288996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
289082a4538fSEric Badger 
289182a4538fSEric Badger 	/*
289282a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
289382a4538fSEric Badger 	 */
289482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
289596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
289682a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
289796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
289882a4538fSEric Badger 
289982a4538fSEric Badger 	wpid = wait(&status);
290096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
290196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
290282a4538fSEric Badger }
290382a4538fSEric Badger 
290482a4538fSEric Badger static void *
290582a4538fSEric Badger signal_thread(void *arg)
290682a4538fSEric Badger {
290782a4538fSEric Badger 	int err;
290882a4538fSEric Badger 	sigset_t sigmask;
290982a4538fSEric Badger 
291082a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
291182a4538fSEric Badger 
291282a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
291382a4538fSEric Badger 	do {
291482a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
291582a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
291682a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
291782a4538fSEric Badger 
291882a4538fSEric Badger 	/* Free our companion thread from the barrier. */
291982a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
292082a4538fSEric Badger 
292182a4538fSEric Badger 	/*
292282a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
292382a4538fSEric Badger 	 * other thread.
292482a4538fSEric Badger 	 */
292596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
292696a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
292796a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
292882a4538fSEric Badger 
292982a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
293082a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
293182a4538fSEric Badger 
293282a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
293382a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
293482a4538fSEric Badger 
293582a4538fSEric Badger 	return (NULL);
293682a4538fSEric Badger }
293782a4538fSEric Badger 
293882a4538fSEric Badger /*
2939753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2940753e2922SBryan Drewery  * signal from kill() once unmasked.
2941753e2922SBryan Drewery  */
2942753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
2943753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
2944753e2922SBryan Drewery {
2945753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2946753e2922SBryan Drewery 	pid_t fpid, wpid;
2947753e2922SBryan Drewery 	int status, err;
2948753e2922SBryan Drewery 	sigset_t sigmask;
2949753e2922SBryan Drewery 
295096a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
2951753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2952753e2922SBryan Drewery 	got_usr1 = 0;
2953753e2922SBryan Drewery 
2954753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2955753e2922SBryan Drewery 	if (fpid == 0) {
295696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
295796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
295896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
2959753e2922SBryan Drewery 
2960753e2922SBryan Drewery 		trace_me();
296196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
2962753e2922SBryan Drewery 
2963753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
296496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
2965753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2966753e2922SBryan Drewery 		do {
2967753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2968753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2969753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
297096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
2971753e2922SBryan Drewery 		exit(1);
2972753e2922SBryan Drewery 	}
2973753e2922SBryan Drewery 
2974753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2975753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
297696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2977753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
297896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
2979753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
298096a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGSTOP);
2981753e2922SBryan Drewery 
2982753e2922SBryan Drewery 	/* Send blocked SIGUSR1 which should cause a stop. */
298396a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
2984753e2922SBryan Drewery 
2985753e2922SBryan Drewery 	/* Continue the child ignoring the SIGSTOP. */
298696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2987753e2922SBryan Drewery 
2988753e2922SBryan Drewery 	/* The next wait() should report the kill(SIGUSR1) was received. */
2989753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
299096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2991753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
299296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
2993753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
299496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
2995753e2922SBryan Drewery 
2996753e2922SBryan Drewery 	/* Continue the child, allowing in the SIGUSR1. */
299796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
2998753e2922SBryan Drewery 
2999753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3000753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
300196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3002753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
300396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3004753e2922SBryan Drewery 
3005753e2922SBryan Drewery 	wpid = wait(&status);
300696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
300796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3008753e2922SBryan Drewery }
3009753e2922SBryan Drewery 
3010753e2922SBryan Drewery /*
3011753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
3012753e2922SBryan Drewery  * signal from PT_CONTINUE once unmasked.
3013753e2922SBryan Drewery  */
3014753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
3015753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
3016753e2922SBryan Drewery {
3017753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
3018753e2922SBryan Drewery 	pid_t fpid, wpid;
3019753e2922SBryan Drewery 	int status, err;
3020753e2922SBryan Drewery 	sigset_t sigmask;
3021753e2922SBryan Drewery 
302296a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
3023753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
3024753e2922SBryan Drewery 	got_usr1 = 0;
3025753e2922SBryan Drewery 
3026753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
3027753e2922SBryan Drewery 	if (fpid == 0) {
302896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
302996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
303096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
3031753e2922SBryan Drewery 
3032753e2922SBryan Drewery 		trace_me();
303396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
3034753e2922SBryan Drewery 
3035753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
303696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
3037753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
3038753e2922SBryan Drewery 		do {
3039753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
3040753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
3041753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
3042753e2922SBryan Drewery 
304396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
3044753e2922SBryan Drewery 		exit(1);
3045753e2922SBryan Drewery 	}
3046753e2922SBryan Drewery 
3047753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
3048753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
304996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3050753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
305196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3052753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
305396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGSTOP);
3054753e2922SBryan Drewery 
3055753e2922SBryan Drewery 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
305696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
3057753e2922SBryan Drewery 
3058753e2922SBryan Drewery 	/* The next wait() should report the SIGUSR1 was received. */
3059753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
306096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3061753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
306296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
3063753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
306496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
3065753e2922SBryan Drewery 
3066753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
306796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3068753e2922SBryan Drewery 
3069753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3070753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
307196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3072753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
307396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3074753e2922SBryan Drewery 
3075753e2922SBryan Drewery 	wpid = wait(&status);
307696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
307796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3078753e2922SBryan Drewery }
3079753e2922SBryan Drewery 
3080753e2922SBryan Drewery /*
308182a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
308282a4538fSEric Badger  * a different signal that the new signal is routed to a thread
308399144520SEitan Adler  * that can accept it, and that the thread is awakened by the signal
308482a4538fSEric Badger  * in a timely manner.
308582a4538fSEric Badger  */
308682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
308782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
308882a4538fSEric Badger {
308982a4538fSEric Badger 	pid_t fpid, wpid;
309082a4538fSEric Badger 	int status, err;
309182a4538fSEric Badger 	pthread_t t;
309282a4538fSEric Badger 	sigset_t sigmask;
309382a4538fSEric Badger 	pthread_barrier_t barrier;
309482a4538fSEric Badger 
309596a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
309696a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
309782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
309882a4538fSEric Badger 
309982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
310082a4538fSEric Badger 	if (fpid == 0) {
310196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_create(&t, NULL, signal_thread,
310296a9e50eSAlex Richardson 		    (void *)&barrier), 0);
310382a4538fSEric Badger 
310482a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
310596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
310696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
310796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
310882a4538fSEric Badger 
310982a4538fSEric Badger 		trace_me();
311082a4538fSEric Badger 
311182a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
311282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
311382a4538fSEric Badger 
311482a4538fSEric Badger 		/*
311582a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
311682a4538fSEric Badger 		 * thread.
311782a4538fSEric Badger 		 */
311896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL),
311996a9e50eSAlex Richardson 		    0);
312082a4538fSEric Badger 
312182a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
312282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
312382a4538fSEric Badger 
312482a4538fSEric Badger 		/*
312582a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
312682a4538fSEric Badger 		 * now.
312782a4538fSEric Badger 		 */
312882a4538fSEric Badger 		raise(SIGSTOP);
312982a4538fSEric Badger 
313082a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
313182a4538fSEric Badger 		do {
313282a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
313382a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
313482a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
313582a4538fSEric Badger 
313682a4538fSEric Badger 		/* Free the other thread from the barrier. */
313782a4538fSEric Badger 		pthread_barrier_wait(&barrier);
313882a4538fSEric Badger 
313996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_join(t, NULL), 0);
314082a4538fSEric Badger 
314182a4538fSEric Badger 		exit(1);
314282a4538fSEric Badger 	}
314382a4538fSEric Badger 
314482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
314582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
314696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
314782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
314896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
314982a4538fSEric Badger 
315082a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
315196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
315282a4538fSEric Badger 
315382a4538fSEric Badger 	/*
315482a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
315582a4538fSEric Badger 	 * in this case).
315682a4538fSEric Badger 	 */
315796a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
315882a4538fSEric Badger 
315982a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
316082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
316196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
316282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
316396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
316482a4538fSEric Badger 
316582a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
316696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
316782a4538fSEric Badger 
316882a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
316982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
317096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
317182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
317296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
317382a4538fSEric Badger 
317482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
317596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
317682a4538fSEric Badger 
317796a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
317882a4538fSEric Badger 
317982a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
318082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
318196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
318282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
318396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
318482a4538fSEric Badger 
318582a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
318696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
318782a4538fSEric Badger 
318882a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
318982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
319096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
319182a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
319296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
319382a4538fSEric Badger 
319482a4538fSEric Badger 	wpid = wait(&status);
319596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
319696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
319782a4538fSEric Badger }
319882a4538fSEric Badger 
3199b38bd91fSEric Badger static void *
3200b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
3201b38bd91fSEric Badger {
3202b38bd91fSEric Badger 
3203b38bd91fSEric Badger 	raise(SIGSTOP);
3204b38bd91fSEric Badger 	return NULL;
3205b38bd91fSEric Badger }
3206b38bd91fSEric Badger 
3207b38bd91fSEric Badger static void *
3208b38bd91fSEric Badger sleep_thread(void *arg __unused)
3209b38bd91fSEric Badger {
3210b38bd91fSEric Badger 
3211b38bd91fSEric Badger 	sleep(60);
3212b38bd91fSEric Badger 	return NULL;
3213b38bd91fSEric Badger }
3214b38bd91fSEric Badger 
3215b38bd91fSEric Badger static void
3216b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
3217b38bd91fSEric Badger {
3218b38bd91fSEric Badger 	pid_t fpid, wpid;
3219b38bd91fSEric Badger 	int status, i;
3220b38bd91fSEric Badger 	cpuset_t setmask;
3221b38bd91fSEric Badger 	cpusetid_t setid;
3222b38bd91fSEric Badger 	pthread_t t;
3223b38bd91fSEric Badger 
3224b38bd91fSEric Badger 	/*
3225b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
3226b38bd91fSEric Badger 	 * that both child and grandchild have died.
3227b38bd91fSEric Badger 	 */
322896a9e50eSAlex Richardson 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
3229b38bd91fSEric Badger 
3230b38bd91fSEric Badger 	fpid = fork();
3231b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
3232b38bd91fSEric Badger 	if (fpid == 0) {
3233b38bd91fSEric Badger 		fpid = fork();
3234b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
3235b38bd91fSEric Badger 		if (fpid == 0) {
3236b38bd91fSEric Badger 			trace_me();
3237b38bd91fSEric Badger 
3238b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
3239b38bd91fSEric Badger 			CPU_ZERO(&setmask);
3240b38bd91fSEric Badger 			CPU_SET(0, &setmask);
324196a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(cpuset(&setid), 0);
3242b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
3243b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
3244b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
3245b38bd91fSEric Badger 
3246b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
3247b38bd91fSEric Badger 				/*
3248b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
3249b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
3250b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
3251b38bd91fSEric Badger 				 * threads compete.
3252b38bd91fSEric Badger 				 */
3253b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3254b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
3255b38bd91fSEric Badger 				raise(SIGSTOP);
3256b38bd91fSEric Badger 			} else {
3257b38bd91fSEric Badger 				/*
3258b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
3259b38bd91fSEric Badger 				 * this thread. After creating the new thread,
3260b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
3261b38bd91fSEric Badger 				 * raise the SIGSTOP.
3262b38bd91fSEric Badger 				 */
3263b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3264b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
3265b38bd91fSEric Badger 				sleep(60);
3266b38bd91fSEric Badger 			}
3267b38bd91fSEric Badger 
3268b38bd91fSEric Badger 			exit(0);
3269b38bd91fSEric Badger 		}
3270b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
3271b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
327296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, fpid);
3273b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
327496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3275b38bd91fSEric Badger 
327696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3277b38bd91fSEric Badger 
3278b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
3279b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
328096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, fpid);
3281b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
328296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3283b38bd91fSEric Badger 
3284b38bd91fSEric Badger 		/*
3285b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
3286b38bd91fSEric Badger 		 * should be killed.
3287b38bd91fSEric Badger 		 */
3288b38bd91fSEric Badger 		exit(0);
3289b38bd91fSEric Badger 	}
3290b38bd91fSEric Badger 
3291b38bd91fSEric Badger 	/*
3292b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
3293b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
3294b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
3295b38bd91fSEric Badger 	 * left dangling when its parent died.
3296b38bd91fSEric Badger 	 */
3297b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
3298b38bd91fSEric Badger 		wpid = wait(&status);
329996a9e50eSAlex Richardson 		if (wpid == fpid) {
330096a9e50eSAlex Richardson 			ATF_REQUIRE(WIFEXITED(status));
330196a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 0);
330296a9e50eSAlex Richardson 		} else {
330396a9e50eSAlex Richardson 			ATF_REQUIRE(WIFSIGNALED(status));
330496a9e50eSAlex Richardson 			REQUIRE_EQ(WTERMSIG(status), SIGKILL);
330596a9e50eSAlex Richardson 		}
3306b38bd91fSEric Badger 	}
3307b38bd91fSEric Badger }
3308b38bd91fSEric Badger 
3309b38bd91fSEric Badger /*
3310b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
3311b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
3312b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
3313b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
3314b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
3315b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
3316b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
3317b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
3318b38bd91fSEric Badger  * past, so make no assumption.
3319b38bd91fSEric Badger  */
33203cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
33213cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
33223cf56bb4SEnji Cooper {
33233cf56bb4SEnji Cooper 
33243cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33253cf56bb4SEnji Cooper }
3326b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
3327b38bd91fSEric Badger {
3328b38bd91fSEric Badger 
3329b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
3330b38bd91fSEric Badger }
33313cf56bb4SEnji Cooper 
33323cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
33333cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
33343cf56bb4SEnji Cooper {
33353cf56bb4SEnji Cooper 
33363cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33373cf56bb4SEnji Cooper }
3338b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
3339b38bd91fSEric Badger {
3340b38bd91fSEric Badger 
3341b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
3342b38bd91fSEric Badger }
3343b38bd91fSEric Badger 
3344b4d33259SEric Badger /*
3345b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
3346b4d33259SEric Badger  * is not modified.
3347b4d33259SEric Badger  */
3348b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
3349b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
3350b4d33259SEric Badger {
3351b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
3352b4d33259SEric Badger 	pid_t fpid, wpid;
3353b4d33259SEric Badger 	int status, event_mask, new_event_mask;
3354b4d33259SEric Badger 
3355b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
3356b4d33259SEric Badger 	if (fpid == 0) {
3357b4d33259SEric Badger 		trace_me();
3358b4d33259SEric Badger 		raise(SIGSTOP);
3359b4d33259SEric Badger 		exit(0);
3360b4d33259SEric Badger 	}
3361b4d33259SEric Badger 
3362b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
3363b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
336496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3365b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
336696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3367b4d33259SEric Badger 
3368b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
3369b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
3370b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
3371b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
3372b4d33259SEric Badger 
3373b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
337496a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGKILL), 0);
3375b4d33259SEric Badger 
3376b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
337796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3378b4d33259SEric Badger 
3379b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
3380b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
338196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3382b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
338396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGKILL);
3384b4d33259SEric Badger 
3385b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3386b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
338796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGKILL);
3388b4d33259SEric Badger 
3389b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
339096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3391b4d33259SEric Badger 
3392b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
3393b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
339496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3395b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
339696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3397b4d33259SEric Badger 
3398b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
3399b4d33259SEric Badger 	new_event_mask = 0;
3400b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
3401b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
340296a9e50eSAlex Richardson 	REQUIRE_EQ(event_mask, new_event_mask);
3403b4d33259SEric Badger 
3404b4d33259SEric Badger 	/* Continue the child to let it exit. */
340596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3406b4d33259SEric Badger 
3407b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
3408b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3409b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
341096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
3411b4d33259SEric Badger 
3412b4d33259SEric Badger 	wpid = wait(&status);
341396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
341496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3415b4d33259SEric Badger }
3416b4d33259SEric Badger 
3417d74da94cSMark Johnston static void *
3418d74da94cSMark Johnston flock_thread(void *arg)
3419d74da94cSMark Johnston {
3420d74da94cSMark Johnston 	int fd;
3421d74da94cSMark Johnston 
3422d74da94cSMark Johnston 	fd = *(int *)arg;
3423d74da94cSMark Johnston 	(void)flock(fd, LOCK_EX);
3424d74da94cSMark Johnston 	(void)flock(fd, LOCK_UN);
3425d74da94cSMark Johnston 	return (NULL);
3426d74da94cSMark Johnston }
3427d74da94cSMark Johnston 
3428d74da94cSMark Johnston /*
3429d74da94cSMark Johnston  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
3430d74da94cSMark Johnston  * We rely on the fact that the lockf implementation sets SBDRY before blocking
3431d74da94cSMark Johnston  * on a lock. This is a regression test for r318191.
3432d74da94cSMark Johnston  */
3433d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
3434d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
3435d74da94cSMark Johnston {
3436d74da94cSMark Johnston 	pthread_barrier_t barrier;
3437d74da94cSMark Johnston 	pthread_barrierattr_t battr;
3438d74da94cSMark Johnston 	char tmpfile[64];
3439d74da94cSMark Johnston 	pid_t child, wpid;
3440d74da94cSMark Johnston 	int error, fd, i, status;
3441d74da94cSMark Johnston 
344296a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrierattr_init(&battr), 0);
3443d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
3444d74da94cSMark Johnston 	    PTHREAD_PROCESS_SHARED) == 0);
344596a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrier_init(&barrier, &battr, 2), 0);
3446d74da94cSMark Johnston 
3447d74da94cSMark Johnston 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
3448d74da94cSMark Johnston 	fd = mkstemp(tmpfile);
3449d74da94cSMark Johnston 	ATF_REQUIRE(fd >= 0);
3450d74da94cSMark Johnston 
3451d74da94cSMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
3452d74da94cSMark Johnston 	if (child == 0) {
3453d74da94cSMark Johnston 		pthread_t t[2];
345496437391SBryan Drewery 		int cfd;
3455d74da94cSMark Johnston 
3456d74da94cSMark Johnston 		error = pthread_barrier_wait(&barrier);
3457d74da94cSMark Johnston 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
3458d74da94cSMark Johnston 			_exit(1);
3459d74da94cSMark Johnston 
3460d74da94cSMark Johnston 		cfd = open(tmpfile, O_RDONLY);
3461d74da94cSMark Johnston 		if (cfd < 0)
3462d74da94cSMark Johnston 			_exit(1);
3463d74da94cSMark Johnston 
3464d74da94cSMark Johnston 		/*
3465d74da94cSMark Johnston 		 * We want at least two threads blocked on the file lock since
3466d74da94cSMark Johnston 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
3467d74da94cSMark Johnston 		 * sleep.
3468d74da94cSMark Johnston 		 */
3469d74da94cSMark Johnston 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
3470d74da94cSMark Johnston 			_exit(1);
3471d74da94cSMark Johnston 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
3472d74da94cSMark Johnston 			_exit(1);
3473d74da94cSMark Johnston 		if (pthread_join(t[0], NULL) != 0)
3474d74da94cSMark Johnston 			_exit(1);
3475d74da94cSMark Johnston 		if (pthread_join(t[1], NULL) != 0)
3476d74da94cSMark Johnston 			_exit(1);
3477d74da94cSMark Johnston 		_exit(0);
3478d74da94cSMark Johnston 	}
3479d74da94cSMark Johnston 
348096a9e50eSAlex Richardson 	REQUIRE_EQ(flock(fd, LOCK_EX), 0);
3481d74da94cSMark Johnston 
3482d74da94cSMark Johnston 	error = pthread_barrier_wait(&barrier);
3483d74da94cSMark Johnston 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
3484d74da94cSMark Johnston 
3485d74da94cSMark Johnston 	/*
3486d74da94cSMark Johnston 	 * Give the child some time to block. Is there a better way to do this?
3487d74da94cSMark Johnston 	 */
3488d74da94cSMark Johnston 	sleep(1);
3489d74da94cSMark Johnston 
3490d74da94cSMark Johnston 	/*
3491d74da94cSMark Johnston 	 * Attach and give the child 3 seconds to stop.
3492d74da94cSMark Johnston 	 */
349396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, child, NULL, 0), 0);
3494d74da94cSMark Johnston 	for (i = 0; i < 3; i++) {
3495d74da94cSMark Johnston 		wpid = waitpid(child, &status, WNOHANG);
3496d74da94cSMark Johnston 		if (wpid == child && WIFSTOPPED(status) &&
3497d74da94cSMark Johnston 		    WSTOPSIG(status) == SIGSTOP)
3498d74da94cSMark Johnston 			break;
3499d74da94cSMark Johnston 		sleep(1);
3500d74da94cSMark Johnston 	}
3501d74da94cSMark Johnston 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
3502d74da94cSMark Johnston 
350396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_DETACH, child, NULL, 0), 0);
3504d74da94cSMark Johnston 
350596a9e50eSAlex Richardson 	REQUIRE_EQ(flock(fd, LOCK_UN), 0);
350696a9e50eSAlex Richardson 	REQUIRE_EQ(unlink(tmpfile), 0);
350796a9e50eSAlex Richardson 	REQUIRE_EQ(close(fd), 0);
3508d74da94cSMark Johnston }
3509d74da94cSMark Johnston 
351054cfb29eSJohn Baldwin static void
351154cfb29eSJohn Baldwin sigusr1_step_handler(int sig)
351254cfb29eSJohn Baldwin {
351354cfb29eSJohn Baldwin 
351496a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
351554cfb29eSJohn Baldwin 	raise(SIGABRT);
351654cfb29eSJohn Baldwin }
351754cfb29eSJohn Baldwin 
351854cfb29eSJohn Baldwin /*
351954cfb29eSJohn Baldwin  * Verify that PT_STEP with a signal invokes the signal before
352054cfb29eSJohn Baldwin  * stepping the next instruction (and that the next instruction is
352154cfb29eSJohn Baldwin  * stepped correctly).
352254cfb29eSJohn Baldwin  */
352354cfb29eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal);
352454cfb29eSJohn Baldwin ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
352554cfb29eSJohn Baldwin {
352654cfb29eSJohn Baldwin 	struct ptrace_lwpinfo pl;
352754cfb29eSJohn Baldwin 	pid_t fpid, wpid;
352854cfb29eSJohn Baldwin 	int status;
352954cfb29eSJohn Baldwin 
353054cfb29eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
353154cfb29eSJohn Baldwin 	if (fpid == 0) {
353254cfb29eSJohn Baldwin 		trace_me();
353354cfb29eSJohn Baldwin 		signal(SIGUSR1, sigusr1_step_handler);
353454cfb29eSJohn Baldwin 		raise(SIGABRT);
353554cfb29eSJohn Baldwin 		exit(1);
353654cfb29eSJohn Baldwin 	}
353754cfb29eSJohn Baldwin 
353854cfb29eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
353954cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
354096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
354154cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
354296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
354354cfb29eSJohn Baldwin 
354496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
354554cfb29eSJohn Baldwin 
354654cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
354754cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
354896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
354954cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
355096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
355154cfb29eSJohn Baldwin 
355254cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
355354cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
355496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
355554cfb29eSJohn Baldwin 
355654cfb29eSJohn Baldwin 	/* Step the child process inserting SIGUSR1. */
355796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1), 0);
355854cfb29eSJohn Baldwin 
355954cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the signal handler. */
356054cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
356196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
356254cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
356396a9e50eSAlex 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);
356796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
356854cfb29eSJohn Baldwin 
356954cfb29eSJohn Baldwin 	/* Continue the child process discarding the signal. */
357096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
357154cfb29eSJohn Baldwin 
357254cfb29eSJohn Baldwin 	/* The next stop should report a trace trap from PT_STEP. */
357354cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
357496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
357554cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
357696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
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);
358096a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
358196a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_TRACE);
358254cfb29eSJohn Baldwin 
358354cfb29eSJohn Baldwin 	/* Continue the child to let it exit. */
358496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
358554cfb29eSJohn Baldwin 
358654cfb29eSJohn Baldwin 	/* The last event should be for the child process's exit. */
358754cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
358854cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
358996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
359054cfb29eSJohn Baldwin 
359154cfb29eSJohn Baldwin 	wpid = wait(&status);
359296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
359396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
359454cfb29eSJohn Baldwin }
359554cfb29eSJohn Baldwin 
3596643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3597643ce7deSJohn Baldwin /*
3598643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported
3599643ce7deSJohn Baldwin  * for a breakpoint trap.
3600643ce7deSJohn Baldwin  */
3601643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo);
3602643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__breakpoint_siginfo, tc)
3603643ce7deSJohn Baldwin {
3604643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3605643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3606643ce7deSJohn Baldwin 	int status;
3607643ce7deSJohn Baldwin 
3608643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3609643ce7deSJohn Baldwin 	if (fpid == 0) {
3610643ce7deSJohn Baldwin 		trace_me();
3611643ce7deSJohn Baldwin 		breakpoint();
3612643ce7deSJohn Baldwin 		exit(1);
3613643ce7deSJohn Baldwin 	}
3614643ce7deSJohn Baldwin 
3615643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3616643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
361796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3618643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
361996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3620643ce7deSJohn Baldwin 
3621643ce7deSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
362296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3623643ce7deSJohn Baldwin 
3624643ce7deSJohn Baldwin 	/* The second wait() should report hitting the breakpoint. */
3625643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
362696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3627643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
362896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3629643ce7deSJohn Baldwin 
3630643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3631643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
363296a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
363396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3634643ce7deSJohn Baldwin 
3635643ce7deSJohn Baldwin 	/* Kill the child process. */
363696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
3637643ce7deSJohn Baldwin 
3638643ce7deSJohn Baldwin 	/* The last wait() should report the SIGKILL. */
3639643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
364096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3641643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSIGNALED(status));
364296a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
3643643ce7deSJohn Baldwin 
3644643ce7deSJohn Baldwin 	wpid = wait(&status);
364596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
364696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3647643ce7deSJohn Baldwin }
3648643ce7deSJohn Baldwin #endif /* HAVE_BREAKPOINT */
3649643ce7deSJohn Baldwin 
3650643ce7deSJohn Baldwin /*
3651643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_TRACE code is reported
3652643ce7deSJohn Baldwin  * for a single-step trap from PT_STEP.
3653643ce7deSJohn Baldwin  */
3654643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo);
3655643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__step_siginfo, tc)
3656643ce7deSJohn Baldwin {
3657643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3658643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3659643ce7deSJohn Baldwin 	int status;
3660643ce7deSJohn Baldwin 
3661643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3662643ce7deSJohn Baldwin 	if (fpid == 0) {
3663643ce7deSJohn Baldwin 		trace_me();
3664643ce7deSJohn Baldwin 		exit(1);
3665643ce7deSJohn Baldwin 	}
3666643ce7deSJohn Baldwin 
3667643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3668643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
366996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3670643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
367196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3672643ce7deSJohn Baldwin 
3673643ce7deSJohn Baldwin 	/* Step the child ignoring the SIGSTOP. */
367496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, 0), 0);
3675643ce7deSJohn Baldwin 
3676643ce7deSJohn Baldwin 	/* The second wait() should report a single-step trap. */
3677643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
367896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3679643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
368096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3681643ce7deSJohn Baldwin 
3682643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3683643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
368496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
368596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_TRACE);
3686643ce7deSJohn Baldwin 
3687643ce7deSJohn Baldwin 	/* Continue the child process. */
368896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3689643ce7deSJohn Baldwin 
3690643ce7deSJohn Baldwin 	/* The last event should be for the child process's exit. */
3691643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3692643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
369396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3694643ce7deSJohn Baldwin 
3695643ce7deSJohn Baldwin 	wpid = wait(&status);
369696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
369796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3698643ce7deSJohn Baldwin }
3699643ce7deSJohn Baldwin 
3700403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3701e012fe34SJohn Baldwin static void *
3702e0a40f30SJohn Baldwin continue_thread(void *arg __unused)
3703e012fe34SJohn Baldwin {
3704e012fe34SJohn Baldwin 	breakpoint();
3705e012fe34SJohn Baldwin 	return (NULL);
3706e012fe34SJohn Baldwin }
3707e012fe34SJohn Baldwin 
3708e012fe34SJohn Baldwin static __dead2 void
3709e012fe34SJohn Baldwin continue_thread_main(void)
3710e012fe34SJohn Baldwin {
3711e012fe34SJohn Baldwin 	pthread_t threads[2];
3712e012fe34SJohn Baldwin 
3713e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
3714e012fe34SJohn Baldwin 	    NULL) == 0);
3715e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
3716e012fe34SJohn Baldwin 	    NULL) == 0);
371796a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(threads[0], NULL), 0);
371896a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(threads[1], NULL), 0);
3719e012fe34SJohn Baldwin 	exit(1);
3720e012fe34SJohn Baldwin }
3721e012fe34SJohn Baldwin 
3722e012fe34SJohn Baldwin /*
3723e012fe34SJohn Baldwin  * Ensure that PT_CONTINUE clears the status of the thread that
3724e012fe34SJohn Baldwin  * triggered the stop even if a different thread's LWP was passed to
3725e012fe34SJohn Baldwin  * PT_CONTINUE.
3726e012fe34SJohn Baldwin  */
3727e012fe34SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
3728e012fe34SJohn Baldwin ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
3729e012fe34SJohn Baldwin {
3730e012fe34SJohn Baldwin 	struct ptrace_lwpinfo pl;
3731e012fe34SJohn Baldwin 	pid_t fpid, wpid;
3732e012fe34SJohn Baldwin 	lwpid_t lwps[2];
3733e012fe34SJohn Baldwin 	bool hit_break[2];
3734403e331dSJohn Baldwin 	struct reg reg;
3735e012fe34SJohn Baldwin 	int i, j, status;
3736e012fe34SJohn Baldwin 
3737e012fe34SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3738e012fe34SJohn Baldwin 	if (fpid == 0) {
3739e012fe34SJohn Baldwin 		trace_me();
3740e012fe34SJohn Baldwin 		continue_thread_main();
3741e012fe34SJohn Baldwin 	}
3742e012fe34SJohn Baldwin 
3743e012fe34SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3744e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
374596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3746e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
374796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3748e012fe34SJohn Baldwin 
3749e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3750e012fe34SJohn Baldwin 	    sizeof(pl)) != -1);
3751e012fe34SJohn Baldwin 
375296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
3753e012fe34SJohn Baldwin 
3754e012fe34SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
375596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3756e012fe34SJohn Baldwin 
3757e012fe34SJohn Baldwin 	/* One of the new threads should report it's birth. */
3758e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
375996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3760e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
376196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3762e012fe34SJohn Baldwin 
3763e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
376496a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
3765e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3766e012fe34SJohn Baldwin 	lwps[0] = pl.pl_lwpid;
3767e012fe34SJohn Baldwin 
3768e012fe34SJohn Baldwin 	/*
3769e012fe34SJohn Baldwin 	 * Suspend this thread to ensure both threads are alive before
3770e012fe34SJohn Baldwin 	 * hitting the breakpoint.
3771e012fe34SJohn Baldwin 	 */
3772e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
3773e012fe34SJohn Baldwin 
377496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3775e012fe34SJohn Baldwin 
3776e012fe34SJohn Baldwin 	/* Second thread should report it's birth. */
3777e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
377896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3779e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
378096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3781e012fe34SJohn Baldwin 
3782e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
378396a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
3784e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3785e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
3786e012fe34SJohn Baldwin 	lwps[1] = pl.pl_lwpid;
3787e012fe34SJohn Baldwin 
3788e012fe34SJohn Baldwin 	/* Resume both threads waiting for breakpoint events. */
3789e012fe34SJohn Baldwin 	hit_break[0] = hit_break[1] = false;
3790e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
379196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3792e012fe34SJohn Baldwin 
3793e012fe34SJohn Baldwin 	/* One thread should report a breakpoint. */
3794e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
379596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3796e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
379796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3798e012fe34SJohn Baldwin 
3799e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3800e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
380196a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
380296a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3803e012fe34SJohn Baldwin 	if (pl.pl_lwpid == lwps[0])
3804e012fe34SJohn Baldwin 		i = 0;
3805e012fe34SJohn Baldwin 	else
3806e012fe34SJohn Baldwin 		i = 1;
3807e012fe34SJohn Baldwin 	hit_break[i] = true;
3808403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3809403e331dSJohn Baldwin 	SKIP_BREAK(&reg);
3810403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3811e012fe34SJohn Baldwin 
3812e012fe34SJohn Baldwin 	/*
3813e012fe34SJohn Baldwin 	 * Resume both threads but pass the other thread's LWPID to
3814e012fe34SJohn Baldwin 	 * PT_CONTINUE.
3815e012fe34SJohn Baldwin 	 */
381696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0), 0);
3817e012fe34SJohn Baldwin 
3818e012fe34SJohn Baldwin 	/*
3819e012fe34SJohn Baldwin 	 * Will now get two thread exit events and one more breakpoint
3820e012fe34SJohn Baldwin 	 * event.
3821e012fe34SJohn Baldwin 	 */
3822e012fe34SJohn Baldwin 	for (j = 0; j < 3; j++) {
3823e012fe34SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
382496a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
3825e012fe34SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
382696a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3827e012fe34SJohn Baldwin 
3828e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3829e012fe34SJohn Baldwin 		    sizeof(pl)) != -1);
3830e012fe34SJohn Baldwin 
3831e012fe34SJohn Baldwin 		if (pl.pl_lwpid == lwps[0])
3832e012fe34SJohn Baldwin 			i = 0;
3833e012fe34SJohn Baldwin 		else
3834e012fe34SJohn Baldwin 			i = 1;
3835e012fe34SJohn Baldwin 
3836e012fe34SJohn Baldwin 		ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
3837e012fe34SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_EXITED) {
3838e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(hit_break[i],
3839e012fe34SJohn Baldwin 			    "exited thread did not report breakpoint");
3840e012fe34SJohn Baldwin 			lwps[i] = 0;
3841e012fe34SJohn Baldwin 		} else {
3842e012fe34SJohn Baldwin 			ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
384396a9e50eSAlex Richardson 			REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
384496a9e50eSAlex Richardson 			REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3845e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(!hit_break[i],
3846e012fe34SJohn Baldwin 			    "double breakpoint event");
3847e012fe34SJohn Baldwin 			hit_break[i] = true;
3848403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
3849403e331dSJohn Baldwin 			    0) != -1);
3850403e331dSJohn Baldwin 			SKIP_BREAK(&reg);
3851403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
3852403e331dSJohn Baldwin 			    0) != -1);
3853e012fe34SJohn Baldwin 		}
3854e012fe34SJohn Baldwin 
385596a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3856e012fe34SJohn Baldwin 	}
3857e012fe34SJohn Baldwin 
3858e012fe34SJohn Baldwin 	/* Both threads should have exited. */
385996a9e50eSAlex Richardson 	REQUIRE_EQ(lwps[0], 0);
386096a9e50eSAlex Richardson 	REQUIRE_EQ(lwps[1], 0);
3861e012fe34SJohn Baldwin 
3862e012fe34SJohn Baldwin 	/* The last event should be for the child process's exit. */
3863e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3864e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
386596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3866e012fe34SJohn Baldwin 
3867e012fe34SJohn Baldwin 	wpid = wait(&status);
386896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
386996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3870e012fe34SJohn Baldwin }
3871e012fe34SJohn Baldwin #endif
3872e012fe34SJohn Baldwin 
3873c5786670SJohn Baldwin /*
3874c5786670SJohn Baldwin  * Verify that PT_LWPINFO doesn't return stale siginfo.
3875c5786670SJohn Baldwin  */
3876c5786670SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_LWPINFO_stale_siginfo);
3877c5786670SJohn Baldwin ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo, tc)
3878c5786670SJohn Baldwin {
3879c5786670SJohn Baldwin 	struct ptrace_lwpinfo pl;
3880c5786670SJohn Baldwin 	pid_t fpid, wpid;
3881c5786670SJohn Baldwin 	int events, status;
3882c5786670SJohn Baldwin 
3883c5786670SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3884c5786670SJohn Baldwin 	if (fpid == 0) {
3885c5786670SJohn Baldwin 		trace_me();
3886c5786670SJohn Baldwin 		raise(SIGABRT);
3887c5786670SJohn Baldwin 		exit(1);
3888c5786670SJohn Baldwin 	}
3889c5786670SJohn Baldwin 
3890c5786670SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3891c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
389296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3893c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
389496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3895c5786670SJohn Baldwin 
389696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3897c5786670SJohn Baldwin 
3898c5786670SJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
3899c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
390096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3901c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
390296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
3903c5786670SJohn Baldwin 
3904c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3905c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
390696a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
3907c5786670SJohn Baldwin 
3908c5786670SJohn Baldwin 	/*
3909c5786670SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
3910c5786670SJohn Baldwin 	 * syscall traps.
3911c5786670SJohn Baldwin 	 */
391296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
3913c5786670SJohn Baldwin 
3914c5786670SJohn Baldwin 	/*
3915c5786670SJohn Baldwin 	 * The next stop should report a system call entry from
3916c5786670SJohn Baldwin 	 * exit().  PL_FLAGS_SI should not be set.
3917c5786670SJohn Baldwin 	 */
3918c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
391996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3920c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
392196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3922c5786670SJohn Baldwin 
3923c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3924c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
392596a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & PL_FLAG_SI), 0);
3926c5786670SJohn Baldwin 
3927c5786670SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
3928c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
3929c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3930c5786670SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
3931c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
3932c5786670SJohn Baldwin 	    sizeof(events)) == 0);
393396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3934c5786670SJohn Baldwin 
3935c5786670SJohn Baldwin 	/* The last event should be for the child process's exit. */
3936c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3937c5786670SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
393896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3939c5786670SJohn Baldwin 
3940c5786670SJohn Baldwin 	wpid = wait(&status);
394196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
394296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3943c5786670SJohn Baldwin }
3944c5786670SJohn Baldwin 
3945c8ea8731SJohn Baldwin /*
394632451fb9SJohn Baldwin  * A simple test of PT_GET_SC_ARGS and PT_GET_SC_RET.
3947c8ea8731SJohn Baldwin  */
3948c8ea8731SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__syscall_args);
3949c8ea8731SJohn Baldwin ATF_TC_BODY(ptrace__syscall_args, tc)
3950c8ea8731SJohn Baldwin {
3951c8ea8731SJohn Baldwin 	struct ptrace_lwpinfo pl;
395232451fb9SJohn Baldwin 	struct ptrace_sc_ret psr;
3953c8ea8731SJohn Baldwin 	pid_t fpid, wpid;
3954c8ea8731SJohn Baldwin 	register_t args[2];
3955c8ea8731SJohn Baldwin 	int events, status;
3956c8ea8731SJohn Baldwin 
3957c8ea8731SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3958c8ea8731SJohn Baldwin 	if (fpid == 0) {
3959c8ea8731SJohn Baldwin 		trace_me();
3960c8ea8731SJohn Baldwin 		kill(getpid(), 0);
396117cc2009SAlex Richardson 		/* Close a fd that should not exist. */
396217cc2009SAlex Richardson 		close(12345);
3963c8ea8731SJohn Baldwin 		exit(1);
3964c8ea8731SJohn Baldwin 	}
3965c8ea8731SJohn Baldwin 
3966c8ea8731SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3967c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
396896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3969c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
397096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3971c8ea8731SJohn Baldwin 
3972c8ea8731SJohn Baldwin 	/*
3973c8ea8731SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
397432451fb9SJohn Baldwin 	 * syscall traps.
3975c8ea8731SJohn Baldwin 	 */
397696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
3977c8ea8731SJohn Baldwin 
3978c8ea8731SJohn Baldwin 	/*
3979c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from getpid().
3980c8ea8731SJohn Baldwin 	 */
3981c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
398296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3983c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
398496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3985c8ea8731SJohn Baldwin 
3986c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3987c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
3988*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_getpid);
3989c8ea8731SJohn Baldwin 
399096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3991c8ea8731SJohn Baldwin 
3992c8ea8731SJohn Baldwin 	/*
399332451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from getpid().
399432451fb9SJohn Baldwin 	 */
399532451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
399696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
399732451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
399896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
399932451fb9SJohn Baldwin 
400032451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
400132451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
4002*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_getpid);
400332451fb9SJohn Baldwin 
400432451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
400532451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
400696a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, 0);
400796a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_retval[0], wpid);
400832451fb9SJohn Baldwin 
400996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
401032451fb9SJohn Baldwin 
401132451fb9SJohn Baldwin 	/*
4012c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from kill().
4013c8ea8731SJohn Baldwin 	 */
4014c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
401596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
4016c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
401796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
4018c8ea8731SJohn Baldwin 
4019c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
4020c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
4021*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_kill);
4022*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_narg, 2u);
4023c8ea8731SJohn Baldwin 
4024c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
4025c8ea8731SJohn Baldwin 	    sizeof(args)) != -1);
402696a9e50eSAlex Richardson 	REQUIRE_EQ(args[0], wpid);
402796a9e50eSAlex Richardson 	REQUIRE_EQ(args[1], 0);
4028c8ea8731SJohn Baldwin 
402996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
403032451fb9SJohn Baldwin 
403132451fb9SJohn Baldwin 	/*
403232451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from kill().
403332451fb9SJohn Baldwin 	 */
403432451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
403596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
403632451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
403796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
403832451fb9SJohn Baldwin 
403932451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
404032451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
4041*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_kill);
404232451fb9SJohn Baldwin 
404332451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
404432451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
404596a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, 0);
404632451fb9SJohn Baldwin 
404796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
404832451fb9SJohn Baldwin 
404932451fb9SJohn Baldwin 	/*
405032451fb9SJohn Baldwin 	 * The next stop should be the syscall entry from close().
405132451fb9SJohn Baldwin 	 */
405232451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
405396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
405432451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
405596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
405632451fb9SJohn Baldwin 
405732451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
405832451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
4059*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_close);
4060*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_narg, 1u);
406132451fb9SJohn Baldwin 
406232451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
406332451fb9SJohn Baldwin 	    sizeof(args)) != -1);
406417cc2009SAlex Richardson 	REQUIRE_EQ(args[0], 12345);
406532451fb9SJohn Baldwin 
406696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
406732451fb9SJohn Baldwin 
406832451fb9SJohn Baldwin 	/*
406932451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from close().
407032451fb9SJohn Baldwin 	 */
407132451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
407296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
407332451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
407496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
407532451fb9SJohn Baldwin 
407632451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
407732451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
4078*1fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_close);
407932451fb9SJohn Baldwin 
408032451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
408132451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
408296a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, EBADF);
408332451fb9SJohn Baldwin 
4084c8ea8731SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
4085c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
4086c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
4087c8ea8731SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
4088c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
4089c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
409096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
4091c8ea8731SJohn Baldwin 
4092c8ea8731SJohn Baldwin 	/* The last event should be for the child process's exit. */
4093c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4094c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
409596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
4096c8ea8731SJohn Baldwin 
4097c8ea8731SJohn Baldwin 	wpid = wait(&status);
409896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
409996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4100c8ea8731SJohn Baldwin }
4101c8ea8731SJohn Baldwin 
4102fd631bcdSMariusz Zaborski /*
4103fd631bcdSMariusz Zaborski  * Verify that when the process is traced that it isn't reparent
4104fd631bcdSMariusz Zaborski  * to the init process when we close all process descriptors.
4105fd631bcdSMariusz Zaborski  */
4106fd631bcdSMariusz Zaborski ATF_TC(ptrace__proc_reparent);
4107fd631bcdSMariusz Zaborski ATF_TC_HEAD(ptrace__proc_reparent, tc)
4108fd631bcdSMariusz Zaborski {
4109fd631bcdSMariusz Zaborski 
4110fd631bcdSMariusz Zaborski 	atf_tc_set_md_var(tc, "timeout", "2");
4111fd631bcdSMariusz Zaborski }
4112fd631bcdSMariusz Zaborski ATF_TC_BODY(ptrace__proc_reparent, tc)
4113fd631bcdSMariusz Zaborski {
4114fd631bcdSMariusz Zaborski 	pid_t traced, debuger, wpid;
4115fd631bcdSMariusz Zaborski 	int pd, status;
4116fd631bcdSMariusz Zaborski 
4117fd631bcdSMariusz Zaborski 	traced = pdfork(&pd, 0);
4118fd631bcdSMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
4119fd631bcdSMariusz Zaborski 	if (traced == 0) {
4120fd631bcdSMariusz Zaborski 		raise(SIGSTOP);
4121fd631bcdSMariusz Zaborski 		exit(0);
4122fd631bcdSMariusz Zaborski 	}
4123fd631bcdSMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
4124fd631bcdSMariusz Zaborski 
4125fd631bcdSMariusz Zaborski 	debuger = fork();
4126fd631bcdSMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
4127fd631bcdSMariusz Zaborski 	if (debuger == 0) {
4128fd631bcdSMariusz Zaborski 		/* The traced process is reparented to debuger. */
412996a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_ATTACH, traced, 0, 0), 0);
4130fd631bcdSMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
413196a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
4132fd631bcdSMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
413396a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
413496a9e50eSAlex Richardson 		REQUIRE_EQ(close(pd), 0);
413596a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_DETACH, traced, (caddr_t)1, 0), 0);
4136fd631bcdSMariusz Zaborski 
4137fd631bcdSMariusz Zaborski 		/* We closed pd so we should not have any child. */
4138fd631bcdSMariusz Zaborski 		wpid = wait(&status);
413996a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, -1);
414096a9e50eSAlex Richardson 		REQUIRE_EQ(errno, ECHILD);
4141fd631bcdSMariusz Zaborski 
4142fd631bcdSMariusz Zaborski 		exit(0);
4143fd631bcdSMariusz Zaborski 	}
4144fd631bcdSMariusz Zaborski 
414596a9e50eSAlex Richardson 	REQUIRE_EQ(close(pd), 0);
4146fd631bcdSMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
414796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debuger);
414896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
4149fd631bcdSMariusz Zaborski 
4150fd631bcdSMariusz Zaborski 	/* Check if we still have any child. */
4151fd631bcdSMariusz Zaborski 	wpid = wait(&status);
415296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
415396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4154fd631bcdSMariusz Zaborski }
4155fd631bcdSMariusz Zaborski 
41568e493611SMariusz Zaborski /*
41578e493611SMariusz Zaborski  * Ensure that traced processes created with pdfork(2) are visible to
41588e493611SMariusz Zaborski  * waitid(P_ALL).
41598e493611SMariusz Zaborski  */
41608e493611SMariusz Zaborski ATF_TC_WITHOUT_HEAD(ptrace__procdesc_wait_child);
41618e493611SMariusz Zaborski ATF_TC_BODY(ptrace__procdesc_wait_child, tc)
41628e493611SMariusz Zaborski {
41638e493611SMariusz Zaborski 	pid_t child, wpid;
41648e493611SMariusz Zaborski 	int pd, status;
41658e493611SMariusz Zaborski 
41668e493611SMariusz Zaborski 	child = pdfork(&pd, 0);
41678e493611SMariusz Zaborski 	ATF_REQUIRE(child >= 0);
41688e493611SMariusz Zaborski 
41698e493611SMariusz Zaborski 	if (child == 0) {
41708e493611SMariusz Zaborski 		trace_me();
41718e493611SMariusz Zaborski 		(void)raise(SIGSTOP);
41728e493611SMariusz Zaborski 		exit(0);
41738e493611SMariusz Zaborski 	}
41748e493611SMariusz Zaborski 
41758e493611SMariusz Zaborski 	wpid = waitpid(child, &status, 0);
417696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
41778e493611SMariusz Zaborski 	ATF_REQUIRE(WIFSTOPPED(status));
417896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
41798e493611SMariusz Zaborski 
41808e493611SMariusz Zaborski 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
41818e493611SMariusz Zaborski 
41828e493611SMariusz Zaborski 	wpid = wait(&status);
418396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
41848e493611SMariusz Zaborski 	ATF_REQUIRE(WIFSTOPPED(status));
418596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
41868e493611SMariusz Zaborski 
41878e493611SMariusz Zaborski 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
41888e493611SMariusz Zaborski 
41898e493611SMariusz Zaborski 	/*
41908e493611SMariusz Zaborski 	 * If process was created by pdfork, the return code have to
41918e493611SMariusz Zaborski 	 * be collected through process descriptor.
41928e493611SMariusz Zaborski 	 */
41938e493611SMariusz Zaborski 	wpid = wait(&status);
419496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
419596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
41968e493611SMariusz Zaborski 
41978e493611SMariusz Zaborski 	ATF_REQUIRE(close(pd) != -1);
41988e493611SMariusz Zaborski }
41998e493611SMariusz Zaborski 
42008e493611SMariusz Zaborski /*
42018e493611SMariusz Zaborski  * Ensure that traced processes created with pdfork(2) are not visible
42028e493611SMariusz Zaborski  * after returning to parent - waitid(P_ALL).
42038e493611SMariusz Zaborski  */
42048e493611SMariusz Zaborski ATF_TC_WITHOUT_HEAD(ptrace__procdesc_reparent_wait_child);
42058e493611SMariusz Zaborski ATF_TC_BODY(ptrace__procdesc_reparent_wait_child, tc)
42068e493611SMariusz Zaborski {
42078e493611SMariusz Zaborski 	pid_t traced, debuger, wpid;
42088e493611SMariusz Zaborski 	int pd, status;
42098e493611SMariusz Zaborski 
42108e493611SMariusz Zaborski 	traced = pdfork(&pd, 0);
42118e493611SMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
42128e493611SMariusz Zaborski 	if (traced == 0) {
42138e493611SMariusz Zaborski 		raise(SIGSTOP);
42148e493611SMariusz Zaborski 		exit(0);
42158e493611SMariusz Zaborski 	}
42168e493611SMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
42178e493611SMariusz Zaborski 
421810321314SAlex Richardson 	/* Wait until the child process has stopped before fork()ing again. */
421910321314SAlex Richardson 	REQUIRE_EQ(traced, waitpid(traced, &status, WSTOPPED));
42208e493611SMariusz Zaborski 	debuger = fork();
42218e493611SMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
42228e493611SMariusz Zaborski 	if (debuger == 0) {
42238e493611SMariusz Zaborski 		/* The traced process is reparented to debuger. */
422496a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_ATTACH, traced, 0, 0), 0);
42258e493611SMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
422696a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
42278e493611SMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
422896a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42298e493611SMariusz Zaborski 
42308e493611SMariusz Zaborski 		/* Allow process to die. */
423196a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, traced, (caddr_t)1, 0), 0);
42328e493611SMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
423396a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
42348e493611SMariusz Zaborski 		ATF_REQUIRE(WIFEXITED(status));
423596a9e50eSAlex Richardson 		REQUIRE_EQ(WEXITSTATUS(status), 0);
42368e493611SMariusz Zaborski 
42378e493611SMariusz Zaborski 		/* Reparent back to the orginal process. */
423896a9e50eSAlex Richardson 		REQUIRE_EQ(close(pd), 0);
42398e493611SMariusz Zaborski 		exit(0);
42408e493611SMariusz Zaborski 	}
42418e493611SMariusz Zaborski 
42428e493611SMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
424396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debuger);
424496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
42458e493611SMariusz Zaborski 
42468e493611SMariusz Zaborski 	/*
42478e493611SMariusz Zaborski 	 * We have a child but it has a process descriptori
42488e493611SMariusz Zaborski 	 * so we should not be able to collect it process.
42498e493611SMariusz Zaborski 	 */
42508e493611SMariusz Zaborski 	wpid = wait(&status);
425196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
425296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
42538e493611SMariusz Zaborski 
425496a9e50eSAlex Richardson 	REQUIRE_EQ(close(pd), 0);
42558e493611SMariusz Zaborski }
42568e493611SMariusz Zaborski 
4257c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
4258c209e3e2SJohn Baldwin {
4259c209e3e2SJohn Baldwin 
4260c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
4261c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
426257c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
426357c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
4264128c9bc0SMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
426598685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
426698685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
426798685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
426898685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
426998685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
427098685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
427198685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
427298685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
4273368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
4274189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
4275189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
4276189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
42775fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
42785fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
42793340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
42808d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
42818d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
42828d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
4283fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
4284fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
4285403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
428682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
4287e2ebfbbfSEric Badger #endif
428882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
428982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
429082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
429182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
429282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
429382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
429482a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
429582a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
429682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
4297753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
429882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
429982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
430082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
430182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
4302753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
4303753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
430482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
4305b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
4306b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
4307b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
4308d74da94cSMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
430954cfb29eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
4310643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
4311643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo);
4312643ce7deSJohn Baldwin #endif
4313643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__step_siginfo);
4314403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
4315e012fe34SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
4316e012fe34SJohn Baldwin #endif
4317c5786670SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
4318c8ea8731SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__syscall_args);
4319fd631bcdSMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__proc_reparent);
43208e493611SMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__procdesc_wait_child);
43218e493611SMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__procdesc_reparent_wait_child);
4322c209e3e2SJohn Baldwin 
4323c209e3e2SJohn Baldwin 	return (atf_no_error());
4324c209e3e2SJohn Baldwin }
4325