xref: /freebsd/tests/sys/kern/ptrace_test.c (revision 548a2ec49bd4ebf9ab00d362257c6bb4d2d7edbc)
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>
31*548a2ec4SAndrew Turner #include <sys/elf.h>
3282a4538fSEric Badger #include <sys/event.h>
33d74da94cSMark Johnston #include <sys/file.h>
3482a4538fSEric Badger #include <sys/time.h>
35b38bd91fSEric Badger #include <sys/procctl.h>
36fd631bcdSMariusz Zaborski #include <sys/procdesc.h>
37e21f96a8SKyle Evans #define	_WANT_MIPS_REGNUM
38c209e3e2SJohn Baldwin #include <sys/ptrace.h>
39*548a2ec4SAndrew Turner #include <sys/procfs.h>
40bc2be1d3SEric Badger #include <sys/queue.h>
41bc2be1d3SEric Badger #include <sys/runq.h>
42189ac973SJohn Baldwin #include <sys/syscall.h>
4357c74f5bSJohn Baldwin #include <sys/sysctl.h>
4457c74f5bSJohn Baldwin #include <sys/user.h>
45c209e3e2SJohn Baldwin #include <sys/wait.h>
46c209e3e2SJohn Baldwin #include <errno.h>
479e0d1159SEric Badger #include <machine/cpufunc.h>
48189ac973SJohn Baldwin #include <pthread.h>
49bc2be1d3SEric Badger #include <sched.h>
5082a4538fSEric Badger #include <semaphore.h>
51c209e3e2SJohn Baldwin #include <signal.h>
5296a9e50eSAlex Richardson #include <stdarg.h>
53dfa8ba12SJohn Baldwin #include <stdio.h>
54c209e3e2SJohn Baldwin #include <stdlib.h>
55c209e3e2SJohn Baldwin #include <unistd.h>
56c209e3e2SJohn Baldwin #include <atf-c.h>
57c209e3e2SJohn Baldwin 
58c209e3e2SJohn Baldwin /*
59403e331dSJohn Baldwin  * Architectures with a user-visible breakpoint().
60403e331dSJohn Baldwin  */
61a9c91abdSJohn Baldwin #if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) ||	\
62a9c91abdSJohn Baldwin     defined(__i386__) || defined(__mips__) || defined(__riscv) ||	\
63a9c91abdSJohn Baldwin     defined(__sparc64__)
64403e331dSJohn Baldwin #define	HAVE_BREAKPOINT
65403e331dSJohn Baldwin #endif
66403e331dSJohn Baldwin 
67403e331dSJohn Baldwin /*
68403e331dSJohn Baldwin  * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap.
69403e331dSJohn Baldwin  */
70403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
71a9c91abdSJohn Baldwin #if defined(__aarch64__)
72a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->elr += 4)
73a9c91abdSJohn Baldwin #elif defined(__amd64__) || defined(__i386__)
74403e331dSJohn Baldwin #define	SKIP_BREAK(reg)
75a9c91abdSJohn Baldwin #elif defined(__arm__)
76a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_pc += 4)
77bd061c39SJohn Baldwin #elif defined(__mips__)
78bd061c39SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_regs[PC] += 4)
79ca75fa17SJohn Baldwin #elif defined(__riscv)
80ca75fa17SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->sepc += 4)
81403e331dSJohn Baldwin #elif defined(__sparc64__)
82403e331dSJohn Baldwin #define	SKIP_BREAK(reg)	do {						\
83403e331dSJohn Baldwin 	(reg)->r_tpc = (reg)->r_tnpc + 4;				\
84403e331dSJohn Baldwin 	(reg)->r_tnpc += 8;						\
85403e331dSJohn Baldwin } while (0)
86403e331dSJohn Baldwin #endif
87403e331dSJohn Baldwin #endif
88403e331dSJohn Baldwin 
89403e331dSJohn Baldwin /*
90dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
91dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
92dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
93dfa8ba12SJohn Baldwin  */
94dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {				\
95dfa8ba12SJohn Baldwin 	if (!(exp))					\
96dfa8ba12SJohn Baldwin 		child_fail_require(__FILE__, __LINE__,	\
9796a9e50eSAlex Richardson 		    #exp " not met\n");			\
9896a9e50eSAlex Richardson } while (0)
9996a9e50eSAlex Richardson 
10096a9e50eSAlex Richardson #define	CHILD_REQUIRE_EQ(actual, expected) do {			\
10196a9e50eSAlex Richardson 	__typeof__(expected) _e = expected;			\
10296a9e50eSAlex Richardson 	__typeof__(actual) _a = actual;				\
10396a9e50eSAlex Richardson 	if (_e != _a)						\
10496a9e50eSAlex Richardson 		child_fail_require(__FILE__, __LINE__, #actual	\
10596a9e50eSAlex Richardson 		    " (%jd) == " #expected " (%jd) not met\n",	\
10696a9e50eSAlex Richardson 		    (intmax_t)_a, (intmax_t)_e);		\
107dfa8ba12SJohn Baldwin } while (0)
108dfa8ba12SJohn Baldwin 
10998685dc8SJohn Baldwin static __dead2 void
11096a9e50eSAlex Richardson child_fail_require(const char *file, int line, const char *fmt, ...)
111dfa8ba12SJohn Baldwin {
11296a9e50eSAlex Richardson 	va_list ap;
11396a9e50eSAlex Richardson 	char buf[1024];
114dfa8ba12SJohn Baldwin 
11596a9e50eSAlex Richardson 	/* Use write() not fprintf() to avoid possible duplicate output. */
11696a9e50eSAlex Richardson 	snprintf(buf, sizeof(buf), "%s:%d: ", file, line);
11796a9e50eSAlex Richardson 	write(STDERR_FILENO, buf, strlen(buf));
11896a9e50eSAlex Richardson 	va_start(ap, fmt);
11996a9e50eSAlex Richardson 	vsnprintf(buf, sizeof(buf), fmt, ap);
12096a9e50eSAlex Richardson 	write(STDERR_FILENO, buf, strlen(buf));
12196a9e50eSAlex Richardson 	va_end(ap);
12296a9e50eSAlex Richardson 
123dfa8ba12SJohn Baldwin 	_exit(32);
124dfa8ba12SJohn Baldwin }
125dfa8ba12SJohn Baldwin 
12696a9e50eSAlex Richardson #define	REQUIRE_EQ(actual, expected) do {				\
12796a9e50eSAlex Richardson 	__typeof__(expected) _e = expected;				\
12896a9e50eSAlex Richardson 	__typeof__(actual) _a = actual;					\
12996a9e50eSAlex Richardson 	ATF_REQUIRE_MSG(_e == _a, #actual " (%jd) == "			\
13096a9e50eSAlex Richardson 	    #expected " (%jd) not met", (intmax_t)_a, (intmax_t)_e);	\
13196a9e50eSAlex Richardson } while (0)
13296a9e50eSAlex Richardson 
13398685dc8SJohn Baldwin static void
13498685dc8SJohn Baldwin trace_me(void)
13598685dc8SJohn Baldwin {
13698685dc8SJohn Baldwin 
13798685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
13898685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13998685dc8SJohn Baldwin 
14098685dc8SJohn Baldwin 	/* Trigger a stop. */
14198685dc8SJohn Baldwin 	raise(SIGSTOP);
14298685dc8SJohn Baldwin }
14398685dc8SJohn Baldwin 
14498685dc8SJohn Baldwin static void
14598685dc8SJohn Baldwin attach_child(pid_t pid)
14698685dc8SJohn Baldwin {
14798685dc8SJohn Baldwin 	pid_t wpid;
14898685dc8SJohn Baldwin 	int status;
14998685dc8SJohn Baldwin 
15096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, pid, NULL, 0), 0);
15198685dc8SJohn Baldwin 
15298685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
15396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, pid);
15498685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15698685dc8SJohn Baldwin }
15798685dc8SJohn Baldwin 
15898685dc8SJohn Baldwin static void
15998685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
16098685dc8SJohn Baldwin {
16198685dc8SJohn Baldwin 
16298685dc8SJohn Baldwin 	/*
16398685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
16498685dc8SJohn Baldwin 	 * there is not a better way.
1653a014c56SJohn Baldwin 	 *
1663a014c56SJohn Baldwin 	 * Prior to r325719, the kern.proc.pid.<pid> sysctl failed
1673a014c56SJohn Baldwin 	 * with ESRCH.  After that change, a valid struct kinfo_proc
1683a014c56SJohn Baldwin 	 * is returned for zombies with ki_stat set to SZOMB.
16998685dc8SJohn Baldwin 	 */
17098685dc8SJohn Baldwin 	for (;;) {
17198685dc8SJohn Baldwin 		struct kinfo_proc kp;
17298685dc8SJohn Baldwin 		size_t len;
17398685dc8SJohn Baldwin 		int mib[4];
17498685dc8SJohn Baldwin 
17598685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
17698685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
17798685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
17898685dc8SJohn Baldwin 		mib[3] = pid;
17998685dc8SJohn Baldwin 		len = sizeof(kp);
18098685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
18196a9e50eSAlex Richardson 			REQUIRE_EQ(errno, ESRCH);
18298685dc8SJohn Baldwin 			break;
18398685dc8SJohn Baldwin 		}
1843a014c56SJohn Baldwin 		if (kp.ki_stat == SZOMB)
1853a014c56SJohn Baldwin 			break;
18698685dc8SJohn Baldwin 		usleep(5000);
18798685dc8SJohn Baldwin 	}
18898685dc8SJohn Baldwin }
18998685dc8SJohn Baldwin 
190dfa8ba12SJohn Baldwin /*
191c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
192c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
193c209e3e2SJohn Baldwin  */
194c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
195c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
196c209e3e2SJohn Baldwin {
197c209e3e2SJohn Baldwin 	pid_t child, wpid;
198c209e3e2SJohn Baldwin 	int status;
199c209e3e2SJohn Baldwin 
200c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
201c209e3e2SJohn Baldwin 	if (child == 0) {
202c209e3e2SJohn Baldwin 		/* Child process. */
20398685dc8SJohn Baldwin 		trace_me();
204c209e3e2SJohn Baldwin 
205b98cb919SJohn Baldwin 		_exit(1);
206c209e3e2SJohn Baldwin 	}
207c209e3e2SJohn Baldwin 
208c209e3e2SJohn Baldwin 	/* Parent process. */
209c209e3e2SJohn Baldwin 
210c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
211c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
21296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
213c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
21496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
215c209e3e2SJohn Baldwin 
216c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
217c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
218c209e3e2SJohn Baldwin 
219c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
220c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
22196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
222c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
22396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
224c209e3e2SJohn Baldwin 
225c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
226c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
22796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
22896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
229c209e3e2SJohn Baldwin }
230c209e3e2SJohn Baldwin 
231c209e3e2SJohn Baldwin /*
232c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
233c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
234c209e3e2SJohn Baldwin  */
235c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
236c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
237c209e3e2SJohn Baldwin {
238c209e3e2SJohn Baldwin 	pid_t child, wpid;
239c209e3e2SJohn Baldwin 	int cpipe[2], status;
240c209e3e2SJohn Baldwin 	char c;
241c209e3e2SJohn Baldwin 
24296a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
243c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
244c209e3e2SJohn Baldwin 	if (child == 0) {
245c209e3e2SJohn Baldwin 		/* Child process. */
246c209e3e2SJohn Baldwin 		close(cpipe[0]);
247c209e3e2SJohn Baldwin 
248c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
24996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(0, read(cpipe[1], &c, sizeof(c)));
250c209e3e2SJohn Baldwin 
251b98cb919SJohn Baldwin 		_exit(1);
252c209e3e2SJohn Baldwin 	}
253c209e3e2SJohn Baldwin 	close(cpipe[1]);
254c209e3e2SJohn Baldwin 
255c209e3e2SJohn Baldwin 	/* Parent process. */
256c209e3e2SJohn Baldwin 
257c209e3e2SJohn Baldwin 	/* Attach to the child process. */
25898685dc8SJohn Baldwin 	attach_child(child);
259c209e3e2SJohn Baldwin 
260c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
261c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
262c209e3e2SJohn Baldwin 
263c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
264c209e3e2SJohn Baldwin 	close(cpipe[0]);
265c209e3e2SJohn Baldwin 
266c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
267c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
26896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
269c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
27096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
271c209e3e2SJohn Baldwin 
272c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
273c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
27496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
27596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
276c209e3e2SJohn Baldwin }
277c209e3e2SJohn Baldwin 
27857c74f5bSJohn Baldwin /*
27957c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
28057c74f5bSJohn Baldwin  * after the debugger has seen it.
28157c74f5bSJohn Baldwin  */
28257c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
28357c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
28457c74f5bSJohn Baldwin {
28557c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
28657c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
28757c74f5bSJohn Baldwin 	char c;
28857c74f5bSJohn Baldwin 
28996a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
29057c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
29157c74f5bSJohn Baldwin 
29257c74f5bSJohn Baldwin 	if (child == 0) {
29357c74f5bSJohn Baldwin 		/* Child process. */
29457c74f5bSJohn Baldwin 		close(cpipe[0]);
29557c74f5bSJohn Baldwin 
29657c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
2971fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
2981fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
29957c74f5bSJohn Baldwin 
300b98cb919SJohn Baldwin 		_exit(1);
30157c74f5bSJohn Baldwin 	}
30257c74f5bSJohn Baldwin 	close(cpipe[1]);
30357c74f5bSJohn Baldwin 
30496a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
30557c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
30657c74f5bSJohn Baldwin 
30757c74f5bSJohn Baldwin 	if (debugger == 0) {
30857c74f5bSJohn Baldwin 		/* Debugger process. */
30957c74f5bSJohn Baldwin 		close(dpipe[0]);
31057c74f5bSJohn Baldwin 
311dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
31257c74f5bSJohn Baldwin 
31357c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
31496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
315dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
31696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
31757c74f5bSJohn Baldwin 
318dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
31957c74f5bSJohn Baldwin 
32057c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
3211fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
3221fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
32357c74f5bSJohn Baldwin 
32457c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
32596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(read(dpipe[1], &c, sizeof(c)), 0);
32657c74f5bSJohn Baldwin 
32757c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
32896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
329dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
33096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
33157c74f5bSJohn Baldwin 
332b98cb919SJohn Baldwin 		_exit(0);
33357c74f5bSJohn Baldwin 	}
33457c74f5bSJohn Baldwin 	close(dpipe[1]);
33557c74f5bSJohn Baldwin 
33657c74f5bSJohn Baldwin 	/* Parent process. */
33757c74f5bSJohn Baldwin 
33857c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
3391fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
34057c74f5bSJohn Baldwin 
34157c74f5bSJohn Baldwin 	/* Release the child. */
3421fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
34396a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &c, sizeof(c)), 0);
34457c74f5bSJohn Baldwin 	close(cpipe[0]);
34557c74f5bSJohn Baldwin 
34698685dc8SJohn Baldwin 	wait_for_zombie(child);
34757c74f5bSJohn Baldwin 
34857c74f5bSJohn Baldwin 	/*
3492f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3502f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3512f021998SJohn Baldwin 	 * until the debugger sees the exit.
35257c74f5bSJohn Baldwin 	 */
35357c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
35496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
35557c74f5bSJohn Baldwin 
35657c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
35757c74f5bSJohn Baldwin 	close(dpipe[0]);
35857c74f5bSJohn Baldwin 
35957c74f5bSJohn Baldwin 	/* Wait for the debugger. */
36057c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
36196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
36257c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
36396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
36457c74f5bSJohn Baldwin 
36557c74f5bSJohn Baldwin 	/* The child process should now be ready. */
36657c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
36796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
36857c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
36996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
37057c74f5bSJohn Baldwin }
37157c74f5bSJohn Baldwin 
37257c74f5bSJohn Baldwin /*
37357c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
37457c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
37557c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
37657c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
37757c74f5bSJohn Baldwin  */
37857c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
37957c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
38057c74f5bSJohn Baldwin {
38157c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
38257c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
38357c74f5bSJohn Baldwin 	char c;
38457c74f5bSJohn Baldwin 
38596a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
38657c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
38757c74f5bSJohn Baldwin 
38857c74f5bSJohn Baldwin 	if (child == 0) {
38957c74f5bSJohn Baldwin 		/* Child process. */
39057c74f5bSJohn Baldwin 		close(cpipe[0]);
39157c74f5bSJohn Baldwin 
39257c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
3931fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
3941fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
39557c74f5bSJohn Baldwin 
396b98cb919SJohn Baldwin 		_exit(1);
39757c74f5bSJohn Baldwin 	}
39857c74f5bSJohn Baldwin 	close(cpipe[1]);
39957c74f5bSJohn Baldwin 
40096a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
40157c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
40257c74f5bSJohn Baldwin 
40357c74f5bSJohn Baldwin 	if (debugger == 0) {
40457c74f5bSJohn Baldwin 		/* Debugger parent. */
40557c74f5bSJohn Baldwin 
40657c74f5bSJohn Baldwin 		/*
40757c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
40857c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
40957c74f5bSJohn Baldwin 		 */
410dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
41157c74f5bSJohn Baldwin 		if (fpid != 0)
412b98cb919SJohn Baldwin 			_exit(2);
41357c74f5bSJohn Baldwin 
41457c74f5bSJohn Baldwin 		/* Debugger process. */
41557c74f5bSJohn Baldwin 		close(dpipe[0]);
41657c74f5bSJohn Baldwin 
417dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
41857c74f5bSJohn Baldwin 
41957c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
42096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
421dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
42296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42357c74f5bSJohn Baldwin 
424dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
42557c74f5bSJohn Baldwin 
42657c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
4271fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
4281fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
42957c74f5bSJohn Baldwin 
43057c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
4311fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(dpipe[1], &c, sizeof(c)),
4321fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
43357c74f5bSJohn Baldwin 
43457c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
43596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
436dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
43796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
43857c74f5bSJohn Baldwin 
439b98cb919SJohn Baldwin 		_exit(0);
44057c74f5bSJohn Baldwin 	}
441eddb85c6SJohn Baldwin 	close(dpipe[1]);
44257c74f5bSJohn Baldwin 
44357c74f5bSJohn Baldwin 	/* Parent process. */
44457c74f5bSJohn Baldwin 
44557c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
44657c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
44796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
44857c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
44996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
45057c74f5bSJohn Baldwin 
45157c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
45257c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
45396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
45457c74f5bSJohn Baldwin 
45557c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
4561fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
45757c74f5bSJohn Baldwin 
45857c74f5bSJohn Baldwin 	/* Release the child. */
4591fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
46096a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &c, sizeof(c)), 0);
46157c74f5bSJohn Baldwin 	close(cpipe[0]);
46257c74f5bSJohn Baldwin 
46398685dc8SJohn Baldwin 	wait_for_zombie(child);
46457c74f5bSJohn Baldwin 
46557c74f5bSJohn Baldwin 	/*
4662f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
4672f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
4682f021998SJohn Baldwin 	 * until the debugger sees the exit.
46957c74f5bSJohn Baldwin 	 */
47057c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
47196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
47257c74f5bSJohn Baldwin 
47357c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
4741fcbddecSAlex Richardson 	REQUIRE_EQ(write(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
47557c74f5bSJohn Baldwin 
47657c74f5bSJohn Baldwin 	/* Wait for the debugger. */
47796a9e50eSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), 0);
478eddb85c6SJohn Baldwin 	close(dpipe[0]);
47957c74f5bSJohn Baldwin 
48057c74f5bSJohn Baldwin 	/* The child process should now be ready. */
48157c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
48296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
48357c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
48496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
48557c74f5bSJohn Baldwin }
48657c74f5bSJohn Baldwin 
48798685dc8SJohn Baldwin /*
488128c9bc0SMark Johnston  * Make sure that we can collect the exit status of an orphaned process.
489128c9bc0SMark Johnston  */
490128c9bc0SMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
491128c9bc0SMark Johnston ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
492128c9bc0SMark Johnston {
493128c9bc0SMark Johnston 	ssize_t n;
494128c9bc0SMark Johnston 	int cpipe1[2], cpipe2[2], gcpipe[2], status;
495128c9bc0SMark Johnston 	pid_t child, gchild;
496128c9bc0SMark Johnston 
49796a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe1), 0);
49896a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe2), 0);
49996a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(gcpipe), 0);
500128c9bc0SMark Johnston 
50196a9e50eSAlex Richardson 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
502128c9bc0SMark Johnston 
503128c9bc0SMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
504128c9bc0SMark Johnston 	if (child == 0) {
505128c9bc0SMark Johnston 		CHILD_REQUIRE((gchild = fork()) != -1);
506128c9bc0SMark Johnston 		if (gchild == 0) {
507128c9bc0SMark Johnston 			status = 1;
508128c9bc0SMark Johnston 			do {
509128c9bc0SMark Johnston 				n = read(gcpipe[0], &status, sizeof(status));
510128c9bc0SMark Johnston 			} while (n == -1 && errno == EINTR);
511128c9bc0SMark Johnston 			_exit(status);
512128c9bc0SMark Johnston 		}
513128c9bc0SMark Johnston 
5141fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(cpipe1[1], &gchild, sizeof(gchild)),
5151fcbddecSAlex Richardson 		    (ssize_t)sizeof(gchild));
5161fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe2[0], &status, sizeof(status)),
5171fcbddecSAlex Richardson 		    (ssize_t)sizeof(status));
518128c9bc0SMark Johnston 		_exit(status);
519128c9bc0SMark Johnston 	}
520128c9bc0SMark Johnston 
5211fcbddecSAlex Richardson 	REQUIRE_EQ(read(cpipe1[0], &gchild, sizeof(gchild)),
5221fcbddecSAlex Richardson 	    (ssize_t)sizeof(gchild));
523128c9bc0SMark Johnston 
52496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, gchild, NULL, 0), 0);
525128c9bc0SMark Johnston 
526128c9bc0SMark Johnston 	status = 0;
5271fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe2[1], &status, sizeof(status)),
5281fcbddecSAlex Richardson 	    (ssize_t)sizeof(status));
52996a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(child, &status, 0), child);
53096a9e50eSAlex Richardson 	ATF_REQUIRE(WIFEXITED(status));
53196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
532128c9bc0SMark Johnston 
533128c9bc0SMark Johnston 	status = 0;
5341fcbddecSAlex Richardson 	REQUIRE_EQ(write(gcpipe[1], &status, sizeof(status)),
5351fcbddecSAlex Richardson 	    (ssize_t)sizeof(status));
53696a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(gchild, &status, 0), gchild);
537128c9bc0SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
53896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_DETACH, gchild, (caddr_t)1, 0), 0);
53996a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(gchild, &status, 0), gchild);
54096a9e50eSAlex Richardson 	ATF_REQUIRE(WIFEXITED(status));
54196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
542128c9bc0SMark Johnston 
54396a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe1[0]), 0);
54496a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe1[1]), 0);
54596a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe2[0]), 0);
54696a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe2[1]), 0);
54796a9e50eSAlex Richardson 	REQUIRE_EQ(close(gcpipe[0]), 0);
54896a9e50eSAlex Richardson 	REQUIRE_EQ(close(gcpipe[1]), 0);
549128c9bc0SMark Johnston }
550128c9bc0SMark Johnston 
551128c9bc0SMark Johnston /*
55298685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
55398685dc8SJohn Baldwin  * debugger is attached to it.
55498685dc8SJohn Baldwin  */
55598685dc8SJohn Baldwin static __dead2 void
556189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
55798685dc8SJohn Baldwin {
55898685dc8SJohn Baldwin 	pid_t fpid, wpid;
55998685dc8SJohn Baldwin 	int status;
56098685dc8SJohn Baldwin 
561189ac973SJohn Baldwin 	if (use_vfork)
562189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
563189ac973SJohn Baldwin 	else
56498685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
56598685dc8SJohn Baldwin 
56698685dc8SJohn Baldwin 	if (fpid == 0)
56798685dc8SJohn Baldwin 		/* Child */
568b98cb919SJohn Baldwin 		_exit(2);
56998685dc8SJohn Baldwin 
57098685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
57196a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(wpid, fpid);
57298685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
57396a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(WEXITSTATUS(status), 2);
57498685dc8SJohn Baldwin 
575b98cb919SJohn Baldwin 	_exit(1);
57698685dc8SJohn Baldwin }
57798685dc8SJohn Baldwin 
57898685dc8SJohn Baldwin /*
57998685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
58098685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
58198685dc8SJohn Baldwin  * child process.
58298685dc8SJohn Baldwin  */
58398685dc8SJohn Baldwin static pid_t
584189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
58598685dc8SJohn Baldwin {
58698685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
58798685dc8SJohn Baldwin 	bool fork_reported[2];
58898685dc8SJohn Baldwin 	pid_t child, wpid;
58998685dc8SJohn Baldwin 	int i, status;
59098685dc8SJohn Baldwin 
59198685dc8SJohn Baldwin 	fork_reported[0] = false;
59298685dc8SJohn Baldwin 	fork_reported[1] = false;
59398685dc8SJohn Baldwin 	child = -1;
59498685dc8SJohn Baldwin 
59598685dc8SJohn Baldwin 	/*
59698685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
59798685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
59898685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
59998685dc8SJohn Baldwin 	 */
60098685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
60198685dc8SJohn Baldwin 		wpid = wait(&status);
60298685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
60398685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
60498685dc8SJohn Baldwin 
60598685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
60698685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
60798685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
60898685dc8SJohn Baldwin 		    0);
60998685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
61098685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
61198685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
61298685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
61396a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
61498685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
61598685dc8SJohn Baldwin 			if (child == -1)
61698685dc8SJohn Baldwin 				child = wpid;
61798685dc8SJohn Baldwin 			else
61896a9e50eSAlex Richardson 				REQUIRE_EQ(child, wpid);
619189ac973SJohn Baldwin 			if (ppl != NULL)
620189ac973SJohn Baldwin 				ppl[1] = pl;
62198685dc8SJohn Baldwin 			fork_reported[1] = true;
62298685dc8SJohn Baldwin 		} else {
62396a9e50eSAlex Richardson 			REQUIRE_EQ(wpid, parent);
62496a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
62598685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
62698685dc8SJohn Baldwin 			if (child == -1)
62798685dc8SJohn Baldwin 				child = pl.pl_child_pid;
62898685dc8SJohn Baldwin 			else
62996a9e50eSAlex Richardson 				REQUIRE_EQ(child, pl.pl_child_pid);
630189ac973SJohn Baldwin 			if (ppl != NULL)
631189ac973SJohn Baldwin 				ppl[0] = pl;
63298685dc8SJohn Baldwin 			fork_reported[0] = true;
63398685dc8SJohn Baldwin 		}
63498685dc8SJohn Baldwin 	}
63598685dc8SJohn Baldwin 
63698685dc8SJohn Baldwin 	return (child);
63798685dc8SJohn Baldwin }
63898685dc8SJohn Baldwin 
63998685dc8SJohn Baldwin /*
64098685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
64198685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
64298685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
64398685dc8SJohn Baldwin  */
64498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
64598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
64698685dc8SJohn Baldwin {
647479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
64898685dc8SJohn Baldwin 	int status;
64998685dc8SJohn Baldwin 
65098685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
65198685dc8SJohn Baldwin 	if (fpid == 0) {
65298685dc8SJohn Baldwin 		trace_me();
653189ac973SJohn Baldwin 		follow_fork_parent(false);
65498685dc8SJohn Baldwin 	}
65598685dc8SJohn Baldwin 
65698685dc8SJohn Baldwin 	/* Parent process. */
65798685dc8SJohn Baldwin 	children[0] = fpid;
65898685dc8SJohn Baldwin 
65998685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
66098685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
66196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
66298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
66396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
66498685dc8SJohn Baldwin 
66598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
66698685dc8SJohn Baldwin 
66798685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
66898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
66998685dc8SJohn Baldwin 
670189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
67198685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
67298685dc8SJohn Baldwin 
67398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
67498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
67598685dc8SJohn Baldwin 
67698685dc8SJohn Baldwin 	/*
67798685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
67898685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
67998685dc8SJohn Baldwin 	 */
68098685dc8SJohn Baldwin 	wpid = wait(&status);
68196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
68298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
68396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
68498685dc8SJohn Baldwin 
68598685dc8SJohn Baldwin 	wpid = wait(&status);
68696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
68798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
68896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
68998685dc8SJohn Baldwin 
69098685dc8SJohn Baldwin 	wpid = wait(&status);
69196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
69296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
69398685dc8SJohn Baldwin }
69498685dc8SJohn Baldwin 
69598685dc8SJohn Baldwin /*
69698685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
69798685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
69898685dc8SJohn Baldwin  * child process is detached after it reports its fork.
69998685dc8SJohn Baldwin  */
70098685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
70198685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
70298685dc8SJohn Baldwin {
703479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
70498685dc8SJohn Baldwin 	int status;
70598685dc8SJohn Baldwin 
70698685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
70798685dc8SJohn Baldwin 	if (fpid == 0) {
70898685dc8SJohn Baldwin 		trace_me();
709189ac973SJohn Baldwin 		follow_fork_parent(false);
71098685dc8SJohn Baldwin 	}
71198685dc8SJohn Baldwin 
71298685dc8SJohn Baldwin 	/* Parent process. */
71398685dc8SJohn Baldwin 	children[0] = fpid;
71498685dc8SJohn Baldwin 
71598685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
71698685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
71796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
71898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
71996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
72098685dc8SJohn Baldwin 
72198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
72298685dc8SJohn Baldwin 
72398685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
72498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
72598685dc8SJohn Baldwin 
726189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
72798685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
72898685dc8SJohn Baldwin 
72998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
73098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
73198685dc8SJohn Baldwin 
73298685dc8SJohn Baldwin 	/*
73398685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
73498685dc8SJohn Baldwin 	 * child.
73598685dc8SJohn Baldwin 	 */
73698685dc8SJohn Baldwin 	wpid = wait(&status);
73796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
73898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
73996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
74098685dc8SJohn Baldwin 
74198685dc8SJohn Baldwin 	wpid = wait(&status);
74296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
74396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
74498685dc8SJohn Baldwin }
74598685dc8SJohn Baldwin 
74698685dc8SJohn Baldwin /*
74798685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
74898685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
74998685dc8SJohn Baldwin  * traced parent is detached after the fork.
75098685dc8SJohn Baldwin  */
75198685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
75298685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
75398685dc8SJohn Baldwin {
754479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
75598685dc8SJohn Baldwin 	int status;
75698685dc8SJohn Baldwin 
75798685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
75898685dc8SJohn Baldwin 	if (fpid == 0) {
75998685dc8SJohn Baldwin 		trace_me();
760189ac973SJohn Baldwin 		follow_fork_parent(false);
76198685dc8SJohn Baldwin 	}
76298685dc8SJohn Baldwin 
76398685dc8SJohn Baldwin 	/* Parent process. */
76498685dc8SJohn Baldwin 	children[0] = fpid;
76598685dc8SJohn Baldwin 
76698685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
76798685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
76896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
76998685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
77096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
77198685dc8SJohn Baldwin 
77298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
77398685dc8SJohn Baldwin 
77498685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
77598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
77698685dc8SJohn Baldwin 
777189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
77898685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
77998685dc8SJohn Baldwin 
78098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
78198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
78298685dc8SJohn Baldwin 
78398685dc8SJohn Baldwin 	/*
78498685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
78598685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
78698685dc8SJohn Baldwin 	 *
78798685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
78898685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
78998685dc8SJohn Baldwin 	 * after the grandchild.
79098685dc8SJohn Baldwin 	 */
79198685dc8SJohn Baldwin 	wpid = wait(&status);
79296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
79398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
79496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
79598685dc8SJohn Baldwin 
79698685dc8SJohn Baldwin 	wpid = wait(&status);
79796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
79898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
79996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
80098685dc8SJohn Baldwin 
80198685dc8SJohn Baldwin 	wpid = wait(&status);
80296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
80396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
80498685dc8SJohn Baldwin }
80598685dc8SJohn Baldwin 
80698685dc8SJohn Baldwin static void
80798685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
80898685dc8SJohn Baldwin {
80998685dc8SJohn Baldwin 	pid_t fpid;
81098685dc8SJohn Baldwin 
81198685dc8SJohn Baldwin 	close(cpipe[0]);
81298685dc8SJohn Baldwin 
81398685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
81498685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
81598685dc8SJohn Baldwin 	if (fpid != 0)
816b98cb919SJohn Baldwin 		_exit(3);
81798685dc8SJohn Baldwin 
81898685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
81998685dc8SJohn Baldwin 	fpid = getpid();
8201fcbddecSAlex Richardson 	CHILD_REQUIRE_EQ(write(cpipe[1], &fpid, sizeof(fpid)),
8211fcbddecSAlex Richardson 	    (ssize_t)sizeof(fpid));
82298685dc8SJohn Baldwin 
82398685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
82496a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(read(cpipe[1], &fpid, sizeof(fpid)), 0);
82598685dc8SJohn Baldwin }
82698685dc8SJohn Baldwin 
82798685dc8SJohn Baldwin /*
82898685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
82998685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
83098685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
83198685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
83298685dc8SJohn Baldwin  */
83398685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
83498685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
83598685dc8SJohn Baldwin {
836479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
83798685dc8SJohn Baldwin 	int cpipe[2], status;
83898685dc8SJohn Baldwin 
83996a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
84098685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
84198685dc8SJohn Baldwin 	if (fpid == 0) {
84298685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
843189ac973SJohn Baldwin 		follow_fork_parent(false);
84498685dc8SJohn Baldwin 	}
84598685dc8SJohn Baldwin 
84698685dc8SJohn Baldwin 	/* Parent process. */
84798685dc8SJohn Baldwin 	close(cpipe[1]);
84898685dc8SJohn Baldwin 
84998685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
85098685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
85196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
85298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
85396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
85498685dc8SJohn Baldwin 
85598685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
85696a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
8571fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
85898685dc8SJohn Baldwin 
85998685dc8SJohn Baldwin 	/* Attach to the fork parent. */
86098685dc8SJohn Baldwin 	attach_child(children[0]);
86198685dc8SJohn Baldwin 
86298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
86398685dc8SJohn Baldwin 
86498685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
86598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
86698685dc8SJohn Baldwin 
86798685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
86898685dc8SJohn Baldwin 	close(cpipe[0]);
86998685dc8SJohn Baldwin 
870189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
87198685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
87298685dc8SJohn Baldwin 
87398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
87498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
87598685dc8SJohn Baldwin 
87698685dc8SJohn Baldwin 	/*
87798685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
87898685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
87998685dc8SJohn Baldwin 	 */
88098685dc8SJohn Baldwin 	wpid = wait(&status);
88196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
88298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
88396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
88498685dc8SJohn Baldwin 
88598685dc8SJohn Baldwin 	wpid = wait(&status);
88696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
88798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
88896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
88998685dc8SJohn Baldwin 
89098685dc8SJohn Baldwin 	wpid = wait(&status);
89196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
89296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
89398685dc8SJohn Baldwin }
89498685dc8SJohn Baldwin 
89598685dc8SJohn Baldwin /*
89698685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
89798685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
89898685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
89998685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
90098685dc8SJohn Baldwin  */
90198685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
90298685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
90398685dc8SJohn Baldwin {
904479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
90598685dc8SJohn Baldwin 	int cpipe[2], status;
90698685dc8SJohn Baldwin 
90796a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
90898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
90998685dc8SJohn Baldwin 	if (fpid == 0) {
91098685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
911189ac973SJohn Baldwin 		follow_fork_parent(false);
91298685dc8SJohn Baldwin 	}
91398685dc8SJohn Baldwin 
91498685dc8SJohn Baldwin 	/* Parent process. */
91598685dc8SJohn Baldwin 	close(cpipe[1]);
91698685dc8SJohn Baldwin 
91798685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
91898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
91996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
92098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
92196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
92298685dc8SJohn Baldwin 
92398685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
92496a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
9251fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
92698685dc8SJohn Baldwin 
92798685dc8SJohn Baldwin 	/* Attach to the fork parent. */
92898685dc8SJohn Baldwin 	attach_child(children[0]);
92998685dc8SJohn Baldwin 
93098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
93198685dc8SJohn Baldwin 
93298685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
93398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
93498685dc8SJohn Baldwin 
93598685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
93698685dc8SJohn Baldwin 	close(cpipe[0]);
93798685dc8SJohn Baldwin 
938189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
93998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
94098685dc8SJohn Baldwin 
94198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
94298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
94398685dc8SJohn Baldwin 
94498685dc8SJohn Baldwin 	/*
94598685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
94698685dc8SJohn Baldwin 	 * parent.
94798685dc8SJohn Baldwin 	 */
94898685dc8SJohn Baldwin 	wpid = wait(&status);
94996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
95098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
95196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
95298685dc8SJohn Baldwin 
95398685dc8SJohn Baldwin 	wpid = wait(&status);
95496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
95596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
95698685dc8SJohn Baldwin }
95798685dc8SJohn Baldwin 
95898685dc8SJohn Baldwin /*
95998685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
96098685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
96198685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
96298685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
96398685dc8SJohn Baldwin  */
96498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
96598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
96698685dc8SJohn Baldwin {
967479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
96898685dc8SJohn Baldwin 	int cpipe[2], status;
96998685dc8SJohn Baldwin 
97096a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
97198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
97298685dc8SJohn Baldwin 	if (fpid == 0) {
97398685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
974189ac973SJohn Baldwin 		follow_fork_parent(false);
97598685dc8SJohn Baldwin 	}
97698685dc8SJohn Baldwin 
97798685dc8SJohn Baldwin 	/* Parent process. */
97898685dc8SJohn Baldwin 	close(cpipe[1]);
97998685dc8SJohn Baldwin 
98098685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
98198685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
98296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
98398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
98496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
98598685dc8SJohn Baldwin 
98698685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
98796a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
9881fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
98998685dc8SJohn Baldwin 
99098685dc8SJohn Baldwin 	/* Attach to the fork parent. */
99198685dc8SJohn Baldwin 	attach_child(children[0]);
99298685dc8SJohn Baldwin 
99398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
99498685dc8SJohn Baldwin 
99598685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
99698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
99798685dc8SJohn Baldwin 
99898685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
99998685dc8SJohn Baldwin 	close(cpipe[0]);
100098685dc8SJohn Baldwin 
1001189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
100298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
100398685dc8SJohn Baldwin 
100498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
100598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
100698685dc8SJohn Baldwin 
100798685dc8SJohn Baldwin 	/*
100898685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
100998685dc8SJohn Baldwin 	 * the child.
101098685dc8SJohn Baldwin 	 */
101198685dc8SJohn Baldwin 	wpid = wait(&status);
101296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
101398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
101496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
101598685dc8SJohn Baldwin 
101698685dc8SJohn Baldwin 	wpid = wait(&status);
101796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
101896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
101998685dc8SJohn Baldwin }
102098685dc8SJohn Baldwin 
1021368b2b1cSJohn Baldwin /*
1022368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
1023368b2b1cSJohn Baldwin  * parent but sees its original parent process.
1024368b2b1cSJohn Baldwin  */
1025368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
1026368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
1027368b2b1cSJohn Baldwin {
1028368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
1029368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
1030368b2b1cSJohn Baldwin 	char c;
1031368b2b1cSJohn Baldwin 
103296a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
1033368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
1034368b2b1cSJohn Baldwin 
1035368b2b1cSJohn Baldwin 	if (child == 0) {
1036368b2b1cSJohn Baldwin 		/* Child process. */
1037368b2b1cSJohn Baldwin 		close(cpipe[0]);
1038368b2b1cSJohn Baldwin 
1039368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
10401fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
10411fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
1042368b2b1cSJohn Baldwin 
1043368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
1044368b2b1cSJohn Baldwin 		ppid = getppid();
10451fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(cpipe[1], &ppid, sizeof(ppid)),
10461fcbddecSAlex Richardson 		    (ssize_t)sizeof(ppid));
1047368b2b1cSJohn Baldwin 
1048368b2b1cSJohn Baldwin 		_exit(1);
1049368b2b1cSJohn Baldwin 	}
1050368b2b1cSJohn Baldwin 	close(cpipe[1]);
1051368b2b1cSJohn Baldwin 
105296a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
1053368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
1054368b2b1cSJohn Baldwin 
1055368b2b1cSJohn Baldwin 	if (debugger == 0) {
1056368b2b1cSJohn Baldwin 		/* Debugger process. */
1057368b2b1cSJohn Baldwin 		close(dpipe[0]);
1058368b2b1cSJohn Baldwin 
1059368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
1060368b2b1cSJohn Baldwin 
1061368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
106296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
1063368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
106496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1065368b2b1cSJohn Baldwin 
1066368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
1067368b2b1cSJohn Baldwin 
1068368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
10691fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
10701fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
1071368b2b1cSJohn Baldwin 
1072368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
1073368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
107496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
1075368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
107696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
1077368b2b1cSJohn Baldwin 
1078368b2b1cSJohn Baldwin 		_exit(0);
1079368b2b1cSJohn Baldwin 	}
1080368b2b1cSJohn Baldwin 	close(dpipe[1]);
1081368b2b1cSJohn Baldwin 
1082368b2b1cSJohn Baldwin 	/* Parent process. */
1083368b2b1cSJohn Baldwin 
1084368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
10851fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
1086368b2b1cSJohn Baldwin 
1087368b2b1cSJohn Baldwin 	/* Release the child. */
10881fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
1089368b2b1cSJohn Baldwin 
1090368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
10911fcbddecSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &ppid, sizeof(ppid)), (ssize_t)sizeof(ppid));
1092368b2b1cSJohn Baldwin 	close(cpipe[0]);
1093368b2b1cSJohn Baldwin 
109496a9e50eSAlex Richardson 	REQUIRE_EQ(ppid, getpid());
1095368b2b1cSJohn Baldwin 
1096368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
1097368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
109896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
1099368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
110096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
1101368b2b1cSJohn Baldwin 
1102368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
1103368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
110496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
1105368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
110696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1107368b2b1cSJohn Baldwin }
1108368b2b1cSJohn Baldwin 
1109189ac973SJohn Baldwin /*
1110189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1111189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
1112189ac973SJohn Baldwin  */
1113189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
1114189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
1115189ac973SJohn Baldwin {
1116189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1117189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1118189ac973SJohn Baldwin 	int status;
1119189ac973SJohn Baldwin 
1120189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1121189ac973SJohn Baldwin 	if (fpid == 0) {
1122189ac973SJohn Baldwin 		trace_me();
1123189ac973SJohn Baldwin 		follow_fork_parent(false);
1124189ac973SJohn Baldwin 	}
1125189ac973SJohn Baldwin 
1126189ac973SJohn Baldwin 	/* Parent process. */
1127189ac973SJohn Baldwin 	children[0] = fpid;
1128189ac973SJohn Baldwin 
1129189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1130189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
113196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1132189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
113396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1134189ac973SJohn Baldwin 
1135189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1136189ac973SJohn Baldwin 
1137189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1138189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1139189ac973SJohn Baldwin 
1140189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1141189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1142189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1143189ac973SJohn Baldwin 
1144189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1145189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
11461fcbddecSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, (unsigned)SYS_fork);
114796a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, pl[1].pl_syscall_code);
114896a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_narg, pl[1].pl_syscall_narg);
1149189ac973SJohn Baldwin 
1150189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1151189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1152189ac973SJohn Baldwin 
1153189ac973SJohn Baldwin 	/*
1154189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1155189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1156189ac973SJohn Baldwin 	 */
1157189ac973SJohn Baldwin 	wpid = wait(&status);
115896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1159189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
116096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1161189ac973SJohn Baldwin 
1162189ac973SJohn Baldwin 	wpid = wait(&status);
116396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1164189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
116596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1166189ac973SJohn Baldwin 
1167189ac973SJohn Baldwin 	wpid = wait(&status);
116896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
116996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1170189ac973SJohn Baldwin }
1171189ac973SJohn Baldwin 
1172189ac973SJohn Baldwin /*
1173189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1174189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1175189ac973SJohn Baldwin  */
1176189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1177189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1178189ac973SJohn Baldwin {
1179189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1180189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1181189ac973SJohn Baldwin 	int status;
1182189ac973SJohn Baldwin 
1183189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1184189ac973SJohn Baldwin 	if (fpid == 0) {
1185189ac973SJohn Baldwin 		trace_me();
1186189ac973SJohn Baldwin 		follow_fork_parent(true);
1187189ac973SJohn Baldwin 	}
1188189ac973SJohn Baldwin 
1189189ac973SJohn Baldwin 	/* Parent process. */
1190189ac973SJohn Baldwin 	children[0] = fpid;
1191189ac973SJohn Baldwin 
1192189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1193189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
119496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1195189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
119696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1197189ac973SJohn Baldwin 
1198189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1199189ac973SJohn Baldwin 
1200189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1201189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1202189ac973SJohn Baldwin 
1203189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1204189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1205189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1206189ac973SJohn Baldwin 
1207189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1208189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
12091fcbddecSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, (unsigned)SYS_vfork);
121096a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, pl[1].pl_syscall_code);
121196a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_narg, pl[1].pl_syscall_narg);
1212189ac973SJohn Baldwin 
1213189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1214189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1215189ac973SJohn Baldwin 
1216189ac973SJohn Baldwin 	/*
1217189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1218189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1219189ac973SJohn Baldwin 	 */
1220189ac973SJohn Baldwin 	wpid = wait(&status);
122196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1222189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
122396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1224189ac973SJohn Baldwin 
1225189ac973SJohn Baldwin 	wpid = wait(&status);
122696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1227189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
122896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1229189ac973SJohn Baldwin 
1230189ac973SJohn Baldwin 	wpid = wait(&status);
123196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
123296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1233189ac973SJohn Baldwin }
1234189ac973SJohn Baldwin 
1235189ac973SJohn Baldwin static void *
1236189ac973SJohn Baldwin simple_thread(void *arg __unused)
1237189ac973SJohn Baldwin {
1238189ac973SJohn Baldwin 
1239189ac973SJohn Baldwin 	pthread_exit(NULL);
1240189ac973SJohn Baldwin }
1241189ac973SJohn Baldwin 
12425fcfab6eSJohn Baldwin static __dead2 void
12435fcfab6eSJohn Baldwin simple_thread_main(void)
12445fcfab6eSJohn Baldwin {
12455fcfab6eSJohn Baldwin 	pthread_t thread;
12465fcfab6eSJohn Baldwin 
124796a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_create(&thread, NULL, simple_thread, NULL), 0);
124896a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(thread, NULL), 0);
12495fcfab6eSJohn Baldwin 	exit(1);
12505fcfab6eSJohn Baldwin }
12515fcfab6eSJohn Baldwin 
1252189ac973SJohn Baldwin /*
1253189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1254189ac973SJohn Baldwin  * thread reports the correct value.
1255189ac973SJohn Baldwin  */
1256189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1257189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1258189ac973SJohn Baldwin {
1259189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1260189ac973SJohn Baldwin 	pid_t fpid, wpid;
1261e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1262189ac973SJohn Baldwin 	int status;
1263189ac973SJohn Baldwin 
1264189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1265189ac973SJohn Baldwin 	if (fpid == 0) {
1266189ac973SJohn Baldwin 		trace_me();
12675fcfab6eSJohn Baldwin 		simple_thread_main();
1268189ac973SJohn Baldwin 	}
1269189ac973SJohn Baldwin 
1270189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1271189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
127296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1273189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
127496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1275189ac973SJohn Baldwin 
1276189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1277189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1278e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1279189ac973SJohn Baldwin 
1280189ac973SJohn Baldwin 	/*
1281189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1282189ac973SJohn Baldwin 	 * system call exits.
1283189ac973SJohn Baldwin 	 */
1284189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1285189ac973SJohn Baldwin 
1286189ac973SJohn Baldwin 	/*
1287189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1288189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1289189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1290189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1291189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1292189ac973SJohn Baldwin 	 */
1293189ac973SJohn Baldwin 	for (;;) {
1294189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
129596a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
1296189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
129796a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1298189ac973SJohn Baldwin 
1299189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1300189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1301189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1302189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1303e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1304189ac973SJohn Baldwin 			/* New thread seen. */
1305189ac973SJohn Baldwin 			break;
1306189ac973SJohn Baldwin 
130796a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1308189ac973SJohn Baldwin 	}
1309189ac973SJohn Baldwin 
1310189ac973SJohn Baldwin 	/* Wait for the child to exit. */
131196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1312189ac973SJohn Baldwin 	for (;;) {
1313189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
131496a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
1315189ac973SJohn Baldwin 		if (WIFEXITED(status))
1316189ac973SJohn Baldwin 			break;
1317189ac973SJohn Baldwin 
1318189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
131996a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
132096a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1321189ac973SJohn Baldwin 	}
1322189ac973SJohn Baldwin 
132396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1324189ac973SJohn Baldwin 
1325189ac973SJohn Baldwin 	wpid = wait(&status);
132696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
132796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1328189ac973SJohn Baldwin }
1329189ac973SJohn Baldwin 
13305fcfab6eSJohn Baldwin /*
13315fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
13325fcfab6eSJohn Baldwin  */
13335fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
13345fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
13355fcfab6eSJohn Baldwin {
13365fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
13375fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
13385fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
13395fcfab6eSJohn Baldwin 	int status;
13405fcfab6eSJohn Baldwin 
13415fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13425fcfab6eSJohn Baldwin 	if (fpid == 0) {
13435fcfab6eSJohn Baldwin 		trace_me();
13445fcfab6eSJohn Baldwin 		simple_thread_main();
13455fcfab6eSJohn Baldwin 	}
13465fcfab6eSJohn Baldwin 
13475fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13485fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
134996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13505fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
135196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
13525fcfab6eSJohn Baldwin 
13535fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13545fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13555fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13565fcfab6eSJohn Baldwin 
135796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
13585fcfab6eSJohn Baldwin 
13595fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
136096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13615fcfab6eSJohn Baldwin 
13625fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13635fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
136496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13655fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
136696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
13675fcfab6eSJohn Baldwin 
13685fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
136996a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
13705fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13715fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13725fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13735fcfab6eSJohn Baldwin 
137496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13755fcfab6eSJohn Baldwin 
13765fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
13775fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
137896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13795fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
138096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
13815fcfab6eSJohn Baldwin 
13825fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
138396a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)),
13845fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
138596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[1]);
13865fcfab6eSJohn Baldwin 
138796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13885fcfab6eSJohn Baldwin 
13895fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13905fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13915fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
139296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
13935fcfab6eSJohn Baldwin 
13945fcfab6eSJohn Baldwin 	wpid = wait(&status);
139596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
139696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
13975fcfab6eSJohn Baldwin }
13985fcfab6eSJohn Baldwin 
13995fcfab6eSJohn Baldwin static void *
14005fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
14015fcfab6eSJohn Baldwin {
14025fcfab6eSJohn Baldwin 
14035fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
14045fcfab6eSJohn Baldwin 	exit(127);
14055fcfab6eSJohn Baldwin }
14065fcfab6eSJohn Baldwin 
14075fcfab6eSJohn Baldwin static __dead2 void
14085fcfab6eSJohn Baldwin exec_thread_main(void)
14095fcfab6eSJohn Baldwin {
14105fcfab6eSJohn Baldwin 	pthread_t thread;
14115fcfab6eSJohn Baldwin 
141296a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_create(&thread, NULL, exec_thread, NULL), 0);
14135fcfab6eSJohn Baldwin 	for (;;)
14145fcfab6eSJohn Baldwin 		sleep(60);
14155fcfab6eSJohn Baldwin 	exit(1);
14165fcfab6eSJohn Baldwin }
14175fcfab6eSJohn Baldwin 
14185fcfab6eSJohn Baldwin /*
14195fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
14205fcfab6eSJohn Baldwin  * process that calls execve(2).
14215fcfab6eSJohn Baldwin  */
14225fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
14235fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
14245fcfab6eSJohn Baldwin {
14255fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
14265fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
14275fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
14285fcfab6eSJohn Baldwin 	int status;
14295fcfab6eSJohn Baldwin 
14305fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14315fcfab6eSJohn Baldwin 	if (fpid == 0) {
14325fcfab6eSJohn Baldwin 		trace_me();
14335fcfab6eSJohn Baldwin 		exec_thread_main();
14345fcfab6eSJohn Baldwin 	}
14355fcfab6eSJohn Baldwin 
14365fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14375fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
143896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14395fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
144096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
14415fcfab6eSJohn Baldwin 
14425fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
14435fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
14445fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
14455fcfab6eSJohn Baldwin 
144696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
14475fcfab6eSJohn Baldwin 
14485fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
144996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14505fcfab6eSJohn Baldwin 
14515fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
14525fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
145396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14545fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
145596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14565fcfab6eSJohn Baldwin 
14575fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
145896a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
14595fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
14605fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
14615fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
14625fcfab6eSJohn Baldwin 
146396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14645fcfab6eSJohn Baldwin 
14655fcfab6eSJohn Baldwin 	/*
14665fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
14675fcfab6eSJohn Baldwin 	 * single threading from execve().
14685fcfab6eSJohn Baldwin 	 */
14695fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
147096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14715fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
147296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14735fcfab6eSJohn Baldwin 
14745fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
147596a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)),
14765fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
147796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[0]);
14785fcfab6eSJohn Baldwin 
147996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14805fcfab6eSJohn Baldwin 
14815fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
14825fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14835fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
148496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14855fcfab6eSJohn Baldwin 
14865fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
148796a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)),
14885fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
148996a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[1]);
14905fcfab6eSJohn Baldwin 
149196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14925fcfab6eSJohn Baldwin 
14935fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
14945fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14955fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
149696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
14975fcfab6eSJohn Baldwin 
14985fcfab6eSJohn Baldwin 	wpid = wait(&status);
149996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
150096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15015fcfab6eSJohn Baldwin }
15025fcfab6eSJohn Baldwin 
15033340c45bSJohn Baldwin static void
15043340c45bSJohn Baldwin handler(int sig __unused)
15053340c45bSJohn Baldwin {
15063340c45bSJohn Baldwin }
15073340c45bSJohn Baldwin 
15083340c45bSJohn Baldwin static void
15093340c45bSJohn Baldwin signal_main(void)
15103340c45bSJohn Baldwin {
15113340c45bSJohn Baldwin 
15123340c45bSJohn Baldwin 	signal(SIGINFO, handler);
15133340c45bSJohn Baldwin 	raise(SIGINFO);
15143340c45bSJohn Baldwin 	exit(0);
15153340c45bSJohn Baldwin }
15163340c45bSJohn Baldwin 
15173340c45bSJohn Baldwin /*
15183340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
15193340c45bSJohn Baldwin  */
15203340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
15213340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
15223340c45bSJohn Baldwin {
15233340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
15243340c45bSJohn Baldwin 	pid_t fpid, wpid;
15253340c45bSJohn Baldwin 	int status;
15263340c45bSJohn Baldwin 
15273340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15283340c45bSJohn Baldwin 	if (fpid == 0) {
15293340c45bSJohn Baldwin 		trace_me();
15303340c45bSJohn Baldwin 		signal_main();
15313340c45bSJohn Baldwin 	}
15323340c45bSJohn Baldwin 
15333340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15343340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
153596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
15363340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
153796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15383340c45bSJohn Baldwin 
153996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15403340c45bSJohn Baldwin 
15413340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
15423340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15433340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
154496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGINFO);
15453340c45bSJohn Baldwin 
15463340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
154796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
15483340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
154996a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, SI_LWP);
155096a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_pid, wpid);
15513340c45bSJohn Baldwin 
155296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15533340c45bSJohn Baldwin 
15543340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
15553340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15563340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
155796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
15583340c45bSJohn Baldwin 
15593340c45bSJohn Baldwin 	wpid = wait(&status);
156096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
156196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15623340c45bSJohn Baldwin }
15633340c45bSJohn Baldwin 
15648d570f64SJohn Baldwin /*
15658d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
15668d570f64SJohn Baldwin  */
15678d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
15688d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
15698d570f64SJohn Baldwin {
15708d570f64SJohn Baldwin 	pid_t fpid, wpid;
15718d570f64SJohn Baldwin 	int events, status;
15728d570f64SJohn Baldwin 
15738d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15748d570f64SJohn Baldwin 	if (fpid == 0) {
15758d570f64SJohn Baldwin 		trace_me();
15768d570f64SJohn Baldwin 		exec_thread(NULL);
15778d570f64SJohn Baldwin 	}
15788d570f64SJohn Baldwin 
15798d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15808d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
158196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
15828d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
158396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15848d570f64SJohn Baldwin 
15858d570f64SJohn Baldwin 	events = 0;
15868d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15878d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15888d570f64SJohn Baldwin 
158996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15908d570f64SJohn Baldwin 
15918d570f64SJohn Baldwin 	/* Should get one event at exit. */
15928d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15938d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
159496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
15958d570f64SJohn Baldwin 
15968d570f64SJohn Baldwin 	wpid = wait(&status);
159796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
159896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15998d570f64SJohn Baldwin }
16008d570f64SJohn Baldwin 
16018d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
16028d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
16038d570f64SJohn Baldwin {
16048d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
16058d570f64SJohn Baldwin 	pid_t fpid, wpid;
16068d570f64SJohn Baldwin 	int events, status;
16078d570f64SJohn Baldwin 
16088d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16098d570f64SJohn Baldwin 	if (fpid == 0) {
16108d570f64SJohn Baldwin 		trace_me();
16118d570f64SJohn Baldwin 		exec_thread(NULL);
16128d570f64SJohn Baldwin 	}
16138d570f64SJohn Baldwin 
16148d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16158d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
161696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
16178d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
161896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
16198d570f64SJohn Baldwin 
16208d570f64SJohn Baldwin 	events = PTRACE_EXEC;
16218d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
16228d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16238d570f64SJohn Baldwin 
162496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16258d570f64SJohn Baldwin 
16268d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
16278d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16288d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
162996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
16308d570f64SJohn Baldwin 
16318d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
163296a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)),
16338d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
16348d570f64SJohn Baldwin 
163596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16368d570f64SJohn Baldwin 
16378d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
16388d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16398d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
164096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16418d570f64SJohn Baldwin 
16428d570f64SJohn Baldwin 	wpid = wait(&status);
164396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
164496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
16458d570f64SJohn Baldwin }
16468d570f64SJohn Baldwin 
16478d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
16488d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
16498d570f64SJohn Baldwin {
16508d570f64SJohn Baldwin 	pid_t fpid, wpid;
16518d570f64SJohn Baldwin 	int events, status;
16528d570f64SJohn Baldwin 
16538d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16548d570f64SJohn Baldwin 	if (fpid == 0) {
16558d570f64SJohn Baldwin 		trace_me();
16568d570f64SJohn Baldwin 		exit(0);
16578d570f64SJohn Baldwin 	}
16588d570f64SJohn Baldwin 
16598d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16608d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
166196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
16628d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
166396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
16648d570f64SJohn Baldwin 
16658d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
16668d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
16678d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16688d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16698d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_FORK);
16708d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
16718d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16728d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16738d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_FORK));
16748d570f64SJohn Baldwin 
16758d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
16768d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
16778d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16788d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16798d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_LWP);
16808d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
16818d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16828d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16838d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_LWP));
16848d570f64SJohn Baldwin 
168596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16868d570f64SJohn Baldwin 
16878d570f64SJohn Baldwin 	/* Should get one event at exit. */
16888d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16898d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
169096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16918d570f64SJohn Baldwin 
16928d570f64SJohn Baldwin 	wpid = wait(&status);
169396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
169496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
16958d570f64SJohn Baldwin }
16968d570f64SJohn Baldwin 
1697fc4f075aSJohn Baldwin /*
1698fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1699fc4f075aSJohn Baldwin  */
1700fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
1701fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1702fc4f075aSJohn Baldwin {
1703fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1704fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1705fc4f075aSJohn Baldwin 	int events, status;
1706fc4f075aSJohn Baldwin 
1707fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1708fc4f075aSJohn Baldwin 	if (fpid == 0) {
1709fc4f075aSJohn Baldwin 		trace_me();
1710fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1711fc4f075aSJohn Baldwin 	}
1712fc4f075aSJohn Baldwin 
1713fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1714fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
171596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1716fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
171796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1718fc4f075aSJohn Baldwin 
1719fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1720fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1721fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1722fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1723fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1724fc4f075aSJohn Baldwin 
1725fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1726fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1727fc4f075aSJohn Baldwin 
1728fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1729fc4f075aSJohn Baldwin 	wpid = wait(&status);
173096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1731fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
173296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1733fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1734fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1735fc4f075aSJohn Baldwin 
1736fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1737fc4f075aSJohn Baldwin 
1738fc4f075aSJohn Baldwin 	wpid = wait(&status);
173996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1740fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
174196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1742fc4f075aSJohn Baldwin 
1743fc4f075aSJohn Baldwin 	wpid = wait(&status);
174496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
174596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1746fc4f075aSJohn Baldwin }
1747fc4f075aSJohn Baldwin 
1748fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
1749fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1750fc4f075aSJohn Baldwin {
1751fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1752fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1753fc4f075aSJohn Baldwin 	int events, status;
1754fc4f075aSJohn Baldwin 
1755fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1756fc4f075aSJohn Baldwin 	if (fpid == 0) {
1757fc4f075aSJohn Baldwin 		trace_me();
1758fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1759fc4f075aSJohn Baldwin 	}
1760fc4f075aSJohn Baldwin 
1761fc4f075aSJohn Baldwin 	/* Parent process. */
1762fc4f075aSJohn Baldwin 	children[0] = fpid;
1763fc4f075aSJohn Baldwin 
1764fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1765fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
176696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1767fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
176896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1769fc4f075aSJohn Baldwin 
1770fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1771fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1772fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1773fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1774fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1775fc4f075aSJohn Baldwin 
1776fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1777fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1778fc4f075aSJohn Baldwin 
1779fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1780fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1781fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1782fc4f075aSJohn Baldwin 
1783fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1784fc4f075aSJohn Baldwin 
1785fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1786fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1787fc4f075aSJohn Baldwin 
1788fc4f075aSJohn Baldwin 	/*
1789fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1790fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1791fc4f075aSJohn Baldwin 	 */
1792fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
179396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1794fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
179596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1796fc4f075aSJohn Baldwin 
1797fc4f075aSJohn Baldwin 	/*
1798fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1799fc4f075aSJohn Baldwin 	 * exits.
1800fc4f075aSJohn Baldwin 	 */
1801fc4f075aSJohn Baldwin 	wpid = wait(&status);
180296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1803fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
180496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1805fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1806fc4f075aSJohn Baldwin 	    -1);
1807fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1808fc4f075aSJohn Baldwin 
1809fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1810fc4f075aSJohn Baldwin 
1811fc4f075aSJohn Baldwin 	wpid = wait(&status);
181296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1813fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
181496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1815fc4f075aSJohn Baldwin 
1816fc4f075aSJohn Baldwin 	wpid = wait(&status);
181796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
181896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1819fc4f075aSJohn Baldwin }
1820fc4f075aSJohn Baldwin 
1821403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
1822e2ebfbbfSEric Badger /*
182382a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
182482a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
182582a4538fSEric Badger  */
182682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
182782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
182882a4538fSEric Badger {
182982a4538fSEric Badger 	pid_t fpid, wpid;
183082a4538fSEric Badger 	int status;
183182a4538fSEric Badger 
183282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
183382a4538fSEric Badger 	if (fpid == 0) {
183482a4538fSEric Badger 		trace_me();
18359e0d1159SEric Badger 		breakpoint();
183682a4538fSEric Badger 		exit(1);
183782a4538fSEric Badger 	}
183882a4538fSEric Badger 
183982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
184082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
184196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
184282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
184396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
184482a4538fSEric Badger 
184582a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
184696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
184782a4538fSEric Badger 
184882a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
184982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
185096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
185182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
185296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
185382a4538fSEric Badger 
185482a4538fSEric Badger 	/* Kill the child process. */
185596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
185682a4538fSEric Badger 
185782a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
185882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
185996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
186082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
186196a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
186282a4538fSEric Badger 
186382a4538fSEric Badger 	wpid = wait(&status);
186496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
186596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
186682a4538fSEric Badger }
1867403e331dSJohn Baldwin #endif /* HAVE_BREAKPOINT */
186882a4538fSEric Badger 
186982a4538fSEric Badger /*
187082a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
187182a4538fSEric Badger  * process exit when stopped inside of a system call.
187282a4538fSEric Badger  */
187382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
187482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
187582a4538fSEric Badger {
187682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
187782a4538fSEric Badger 	pid_t fpid, wpid;
187882a4538fSEric Badger 	int status;
187982a4538fSEric Badger 
188082a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
188182a4538fSEric Badger 	if (fpid == 0) {
188282a4538fSEric Badger 		trace_me();
188382a4538fSEric Badger 		getpid();
188482a4538fSEric Badger 		exit(1);
188582a4538fSEric Badger 	}
188682a4538fSEric Badger 
188782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
188882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
188996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
189082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
189196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
189282a4538fSEric Badger 
189382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
189496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
189582a4538fSEric Badger 
189682a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
189782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
189896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
189982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
190096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
190182a4538fSEric Badger 
190282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
190382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
190482a4538fSEric Badger 
190582a4538fSEric Badger 	/* Kill the child process. */
190696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
190782a4538fSEric Badger 
190882a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
190982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
191096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
191182a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
191296a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
191382a4538fSEric Badger 
191482a4538fSEric Badger 	wpid = wait(&status);
191596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
191696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
191782a4538fSEric Badger }
191882a4538fSEric Badger 
191982a4538fSEric Badger /*
192082a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
192182a4538fSEric Badger  * process exit when killing a multithreaded process.
192282a4538fSEric Badger  */
192382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
192482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
192582a4538fSEric Badger {
192682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
192782a4538fSEric Badger 	pid_t fpid, wpid;
192882a4538fSEric Badger 	lwpid_t main_lwp;
192982a4538fSEric Badger 	int status;
193082a4538fSEric Badger 
193182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
193282a4538fSEric Badger 	if (fpid == 0) {
193382a4538fSEric Badger 		trace_me();
193482a4538fSEric Badger 		simple_thread_main();
193582a4538fSEric Badger 	}
193682a4538fSEric Badger 
193782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
193882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
193996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
194082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
194196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
194282a4538fSEric Badger 
194382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
194482a4538fSEric Badger 	    sizeof(pl)) != -1);
194582a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
194682a4538fSEric Badger 
194796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
194882a4538fSEric Badger 
194982a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
195096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
195182a4538fSEric Badger 
195282a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
195382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
195496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
195582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
195696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
195782a4538fSEric Badger 
195882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
195996a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
196082a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
196182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
196282a4538fSEric Badger 
196382a4538fSEric Badger 	/* Kill the child process. */
196496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
196582a4538fSEric Badger 
196682a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
196782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
196896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
196982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
197096a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
197182a4538fSEric Badger 
197282a4538fSEric Badger 	wpid = wait(&status);
197396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
197496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
197582a4538fSEric Badger }
197682a4538fSEric Badger 
197782a4538fSEric Badger static void *
197882a4538fSEric Badger mask_usr1_thread(void *arg)
197982a4538fSEric Badger {
198082a4538fSEric Badger 	pthread_barrier_t *pbarrier;
198182a4538fSEric Badger 	sigset_t sigmask;
198282a4538fSEric Badger 
198382a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
198482a4538fSEric Badger 
198582a4538fSEric Badger 	sigemptyset(&sigmask);
198682a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
198796a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
198882a4538fSEric Badger 
198982a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
199082a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
199182a4538fSEric Badger 
199282a4538fSEric Badger 	for (;;)
199382a4538fSEric Badger 		sleep(60);
199482a4538fSEric Badger 
199582a4538fSEric Badger 	return (NULL);
199682a4538fSEric Badger }
199782a4538fSEric Badger 
199882a4538fSEric Badger /*
199982a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
200082a4538fSEric Badger  * and prevents spurious stops due to those other signals.
200182a4538fSEric Badger  */
20023cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal);
20033cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
20043cf56bb4SEnji Cooper {
20053cf56bb4SEnji Cooper 
20063cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
20073cf56bb4SEnji Cooper }
200882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
200982a4538fSEric Badger {
201082a4538fSEric Badger 	pid_t fpid, wpid;
201182a4538fSEric Badger 	int status;
201282a4538fSEric Badger 	cpuset_t setmask;
201382a4538fSEric Badger 	pthread_t t;
201482a4538fSEric Badger 	pthread_barrier_t barrier;
2015bc2be1d3SEric Badger 	struct sched_param sched_param;
201682a4538fSEric Badger 
201782a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
201882a4538fSEric Badger 	if (fpid == 0) {
2019bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
202082a4538fSEric Badger 		CPU_ZERO(&setmask);
202182a4538fSEric Badger 		CPU_SET(0, &setmask);
202282a4538fSEric Badger 		cpusetid_t setid;
202396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(cpuset(&setid), 0);
202482a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
202582a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
202682a4538fSEric Badger 
202796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
202882a4538fSEric Badger 
202982a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
203082a4538fSEric Badger 		    (void*)&barrier) == 0);
203182a4538fSEric Badger 
2032bc2be1d3SEric Badger 		/*
2033bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2034bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2035bc2be1d3SEric Badger 		 * thread runs first.
2036bc2be1d3SEric Badger 		 */
2037bc2be1d3SEric Badger 		sched_param.sched_priority =
2038bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2039bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2040bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2041bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2042bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2043bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2044bc2be1d3SEric Badger 		    &sched_param) == 0);
2045bc2be1d3SEric Badger 
204682a4538fSEric Badger 		sigset_t sigmask;
204782a4538fSEric Badger 		sigemptyset(&sigmask);
204882a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
204996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
205082a4538fSEric Badger 
205182a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
205282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
205382a4538fSEric Badger 
205482a4538fSEric Badger 		trace_me();
205582a4538fSEric Badger 
205682a4538fSEric Badger 		for (;;)
205782a4538fSEric Badger 			sleep(60);
205882a4538fSEric Badger 
205982a4538fSEric Badger 		exit(1);
206082a4538fSEric Badger 	}
206182a4538fSEric Badger 
206282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
206382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
206496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
206582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
206696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
206782a4538fSEric Badger 
206882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
206996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
207082a4538fSEric Badger 
207182a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
207296a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
207382a4538fSEric Badger 
207482a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
207582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
207696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
207782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
207896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
207982a4538fSEric Badger 
208082a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
208196a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
208282a4538fSEric Badger 
208382a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
208496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
208582a4538fSEric Badger 
208682a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
208782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
208896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
208982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
209096a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
209182a4538fSEric Badger 
209282a4538fSEric Badger 	wpid = wait(&status);
209396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
209496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
209582a4538fSEric Badger }
209682a4538fSEric Badger 
209782a4538fSEric Badger /*
209882a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
209982a4538fSEric Badger  * and prevents spurious stops caused by those events.
210082a4538fSEric Badger  */
21013cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop);
21023cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc)
21033cf56bb4SEnji Cooper {
21043cf56bb4SEnji Cooper 
21053cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
21063cf56bb4SEnji Cooper }
210782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
210882a4538fSEric Badger {
210982a4538fSEric Badger 	pid_t fpid, wpid;
2110bc2be1d3SEric Badger 	int status;
211182a4538fSEric Badger 	cpuset_t setmask;
211282a4538fSEric Badger 	pthread_t t;
211382a4538fSEric Badger 	pthread_barrier_t barrier;
211482a4538fSEric Badger 	lwpid_t main_lwp;
211582a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2116bc2be1d3SEric Badger 	struct sched_param sched_param;
211782a4538fSEric Badger 
211882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
211982a4538fSEric Badger 	if (fpid == 0) {
212082a4538fSEric Badger 		trace_me();
212182a4538fSEric Badger 
2122bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
212382a4538fSEric Badger 		CPU_ZERO(&setmask);
212482a4538fSEric Badger 		CPU_SET(0, &setmask);
212582a4538fSEric Badger 		cpusetid_t setid;
212696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(cpuset(&setid), 0);
212782a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
212882a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
212982a4538fSEric Badger 
213096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
213182a4538fSEric Badger 
213282a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
213382a4538fSEric Badger 		    (void*)&barrier) == 0);
213482a4538fSEric Badger 
2135bc2be1d3SEric Badger 		/*
2136bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2137bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2138bc2be1d3SEric Badger 		 * thread runs first.
2139bc2be1d3SEric Badger 		 */
2140bc2be1d3SEric Badger 		sched_param.sched_priority =
2141bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2142bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2143bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2144bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2145bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2146bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2147bc2be1d3SEric Badger 		    &sched_param) == 0);
2148bc2be1d3SEric Badger 
214982a4538fSEric Badger 		sigset_t sigmask;
215082a4538fSEric Badger 		sigemptyset(&sigmask);
215182a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
215296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
215382a4538fSEric Badger 
215482a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
215582a4538fSEric Badger 		pthread_barrier_wait(&barrier);
215682a4538fSEric Badger 
215782a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
215882a4538fSEric Badger 		raise(SIGSTOP);
215982a4538fSEric Badger 
216082a4538fSEric Badger 		getpid();
216182a4538fSEric Badger 		exit(1);
216282a4538fSEric Badger 	}
216382a4538fSEric Badger 
216482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
216582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
216696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
216782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
216896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
216982a4538fSEric Badger 
217082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
217182a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
217282a4538fSEric Badger 
217382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
217496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
217582a4538fSEric Badger 
217682a4538fSEric Badger 	/*
217782a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
217882a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
217982a4538fSEric Badger 	 */
218082a4538fSEric Badger 	for (;;) {
218182a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
218296a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
218382a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
218482a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
218582a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
218682a4538fSEric Badger 			    sizeof(pl)) != -1);
218782a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
218882a4538fSEric Badger 		} else {
218996a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
219082a4538fSEric Badger 			break;
219182a4538fSEric Badger 		}
219296a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
219382a4538fSEric Badger 	}
219482a4538fSEric Badger 
2195bc2be1d3SEric Badger 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
219696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
219782a4538fSEric Badger 
219882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
219996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
220082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
220196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
220282a4538fSEric Badger 
220382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
220482a4538fSEric Badger 	    sizeof(pl)) != -1);
220596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, main_lwp);
220682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
2207bc2be1d3SEric Badger 	/* Prevent the main thread from hitting its syscall exit for now. */
220896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SUSPEND, main_lwp, 0, 0), 0);
220982a4538fSEric Badger 
2210bc2be1d3SEric Badger 	/*
2211bc2be1d3SEric Badger 	 * Proceed, allowing second thread to hit syscall exit for
2212bc2be1d3SEric Badger 	 * pthread_barrier_wait().
2213bc2be1d3SEric Badger 	 */
221496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
2215bc2be1d3SEric Badger 
2216bc2be1d3SEric Badger 	wpid = waitpid(fpid, &status, 0);
221796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2218bc2be1d3SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
221996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
2220bc2be1d3SEric Badger 
2221bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
2222bc2be1d3SEric Badger 	    sizeof(pl)) != -1);
2223bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
2224bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
222582a4538fSEric Badger 
222682a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
222796a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
222882a4538fSEric Badger 
222996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
223082a4538fSEric Badger 
2231bc2be1d3SEric Badger 	/* The next wait() should report the SIGUSR2. */
223282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
223396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
223482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
223596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
223682a4538fSEric Badger 
223782a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
223896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_RESUME, main_lwp, 0, 0), 0);
223982a4538fSEric Badger 
224082a4538fSEric Badger 	/*
224182a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
2242bc2be1d3SEric Badger 	 * has been resumed. The second thread has taken a SIGUSR2 which will
2243bc2be1d3SEric Badger 	 * be replaced with a SIGKILL below. The main thread will get to run
2244bc2be1d3SEric Badger 	 * first. It should notice the kill request (even though the signal
2245bc2be1d3SEric Badger 	 * replacement occurred in the other thread) and exit accordingly.  It
2246bc2be1d3SEric Badger 	 * should not stop for the system call exit event.
224782a4538fSEric Badger 	 */
224882a4538fSEric Badger 
224982a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
225096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
225182a4538fSEric Badger 
225282a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
225382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
225496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
225582a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
225696a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
225782a4538fSEric Badger 
225882a4538fSEric Badger 	wpid = wait(&status);
225996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
226096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
226182a4538fSEric Badger }
226282a4538fSEric Badger 
226382a4538fSEric Badger static void
226482a4538fSEric Badger sigusr1_handler(int sig)
226582a4538fSEric Badger {
226682a4538fSEric Badger 
226796a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
226882a4538fSEric Badger 	_exit(2);
226982a4538fSEric Badger }
227082a4538fSEric Badger 
227182a4538fSEric Badger /*
227282a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
227382a4538fSEric Badger  * a PT_KILL will kill the process.
227482a4538fSEric Badger  */
227582a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
227682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
227782a4538fSEric Badger {
227882a4538fSEric Badger 	pid_t fpid, wpid;
227982a4538fSEric Badger 	int status;
228082a4538fSEric Badger 	int max_pending_per_proc;
228182a4538fSEric Badger 	size_t len;
228282a4538fSEric Badger 	int i;
228382a4538fSEric Badger 
228482a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
228582a4538fSEric Badger 
228682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
228782a4538fSEric Badger 	if (fpid == 0) {
228882a4538fSEric Badger 		trace_me();
228982a4538fSEric Badger 		exit(1);
229082a4538fSEric Badger 	}
229182a4538fSEric Badger 
229282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
229382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
229496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
229582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
229696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
229782a4538fSEric Badger 
229882a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
229982a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
230082a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
230182a4538fSEric Badger 
230282a4538fSEric Badger 	/* Fill the signal queue. */
230382a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
230496a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
230582a4538fSEric Badger 
230682a4538fSEric Badger 	/* Kill the child process. */
230796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
230882a4538fSEric Badger 
230982a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
231082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
231196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
231282a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
231396a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
231482a4538fSEric Badger 
231582a4538fSEric Badger 	wpid = wait(&status);
231696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
231796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
231882a4538fSEric Badger }
231982a4538fSEric Badger 
232082a4538fSEric Badger /*
232182a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
232282a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
232382a4538fSEric Badger  * call is complete.
232482a4538fSEric Badger  */
232582a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
232682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
232782a4538fSEric Badger {
232882a4538fSEric Badger 	struct ptrace_lwpinfo pl;
232982a4538fSEric Badger 	pid_t fpid, wpid;
233082a4538fSEric Badger 	int status;
233182a4538fSEric Badger 
233282a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
233382a4538fSEric Badger 
233482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
233582a4538fSEric Badger 	if (fpid == 0) {
233682a4538fSEric Badger 		trace_me();
233782a4538fSEric Badger 		getpid();
233882a4538fSEric Badger 		exit(1);
233982a4538fSEric Badger 	}
234082a4538fSEric Badger 
234182a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
234282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
234396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
234482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
234596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
234682a4538fSEric Badger 
234782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
234896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
234982a4538fSEric Badger 
235082a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
235182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
235296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
235382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
235496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
235582a4538fSEric Badger 
235682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
235782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
235882a4538fSEric Badger 
235982a4538fSEric Badger 	/* Continue the child process with a signal. */
236096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
236182a4538fSEric Badger 
236282a4538fSEric Badger 	for (;;) {
236382a4538fSEric Badger 		/*
236482a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
236582a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
236682a4538fSEric Badger 		 * past any syscall stops.
236782a4538fSEric Badger 		 */
236882a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
236996a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
237082a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
237182a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
237282a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
237396a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
237482a4538fSEric Badger 		} else {
237582a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
237696a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
237782a4538fSEric Badger 			break;
237882a4538fSEric Badger 		}
237982a4538fSEric Badger 	}
238082a4538fSEric Badger 
238182a4538fSEric Badger 	wpid = wait(&status);
238296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
238396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
238482a4538fSEric Badger }
238582a4538fSEric Badger 
238682a4538fSEric Badger static void
238782a4538fSEric Badger sigusr1_counting_handler(int sig)
238882a4538fSEric Badger {
238982a4538fSEric Badger 	static int counter = 0;
239082a4538fSEric Badger 
239196a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
239282a4538fSEric Badger 	counter++;
239382a4538fSEric Badger 	if (counter == 2)
239482a4538fSEric Badger 		_exit(2);
239582a4538fSEric Badger }
239682a4538fSEric Badger 
239782a4538fSEric Badger /*
239882a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
239982a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
240082a4538fSEric Badger  * the system call is complete.
240182a4538fSEric Badger  */
240282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
240382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
240482a4538fSEric Badger {
240582a4538fSEric Badger 	struct ptrace_lwpinfo pl;
240682a4538fSEric Badger 	pid_t fpid, wpid;
240782a4538fSEric Badger 	int status;
240882a4538fSEric Badger 
240982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
241082a4538fSEric Badger 
241182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
241282a4538fSEric Badger 	if (fpid == 0) {
241382a4538fSEric Badger 		trace_me();
241482a4538fSEric Badger 		getpid();
241582a4538fSEric Badger 		exit(1);
241682a4538fSEric Badger 	}
241782a4538fSEric Badger 
241882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
241982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
242096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
242182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
242296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
242382a4538fSEric Badger 
242482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
242596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
242682a4538fSEric Badger 
242782a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
242882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
242996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
243082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
243196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
243282a4538fSEric Badger 
243382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
243482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
243582a4538fSEric Badger 
243682a4538fSEric Badger 	/* Continue the child process with a signal. */
243796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
243882a4538fSEric Badger 
243982a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
244082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
244196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
244282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
244396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
244482a4538fSEric Badger 
244582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
244682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
244782a4538fSEric Badger 
244882a4538fSEric Badger 	/* Continue the child process with a signal. */
244996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
245082a4538fSEric Badger 
245182a4538fSEric Badger 	for (;;) {
245282a4538fSEric Badger 		/*
245382a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
245482a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
245582a4538fSEric Badger 		 * past any syscall stops.
245682a4538fSEric Badger 		 */
245782a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
245896a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
245982a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
246082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
246182a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
246296a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
246382a4538fSEric Badger 		} else {
246482a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
246596a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
246682a4538fSEric Badger 			break;
246782a4538fSEric Badger 		}
246882a4538fSEric Badger 	}
246982a4538fSEric Badger 
247082a4538fSEric Badger 	wpid = wait(&status);
247196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
247296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
247382a4538fSEric Badger }
247482a4538fSEric Badger 
247582a4538fSEric Badger /*
247682a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
247782a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
247882a4538fSEric Badger  */
247982a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
248082a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
248182a4538fSEric Badger {
248282a4538fSEric Badger 	pid_t fpid, wpid;
248382a4538fSEric Badger 	int status;
248482a4538fSEric Badger 	int max_pending_per_proc;
248582a4538fSEric Badger 	size_t len;
248682a4538fSEric Badger 	int i;
248782a4538fSEric Badger 
248882a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
248982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
249082a4538fSEric Badger 
249182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
249282a4538fSEric Badger 	if (fpid == 0) {
249382a4538fSEric Badger 		trace_me();
249482a4538fSEric Badger 		exit(1);
249582a4538fSEric Badger 	}
249682a4538fSEric Badger 
249782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
249882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
249996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
250082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
250196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
250282a4538fSEric Badger 
250382a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
250482a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
250582a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
250682a4538fSEric Badger 
250782a4538fSEric Badger 	/* Fill the signal queue. */
250882a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
250996a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
251082a4538fSEric Badger 
251182a4538fSEric Badger 	/* Continue with signal. */
251296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
251382a4538fSEric Badger 
251482a4538fSEric Badger 	for (;;) {
251582a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
251696a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
251782a4538fSEric Badger 		if (WIFSTOPPED(status)) {
251896a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
251996a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
252082a4538fSEric Badger 		} else {
252182a4538fSEric Badger 			/*
252282a4538fSEric Badger 			 * The last wait() should report normal _exit from the
252382a4538fSEric Badger 			 * SIGUSR1 handler.
252482a4538fSEric Badger 			 */
252582a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
252696a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
252782a4538fSEric Badger 			break;
252882a4538fSEric Badger 		}
252982a4538fSEric Badger 	}
253082a4538fSEric Badger 
253182a4538fSEric Badger 	wpid = wait(&status);
253296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
253396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
253482a4538fSEric Badger }
253582a4538fSEric Badger 
2536753e2922SBryan Drewery static sem_t sigusr1_sem;
2537753e2922SBryan Drewery static int got_usr1;
2538753e2922SBryan Drewery 
2539753e2922SBryan Drewery static void
2540753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused)
2541753e2922SBryan Drewery {
2542753e2922SBryan Drewery 
2543753e2922SBryan Drewery 	got_usr1++;
254496a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sem_post(&sigusr1_sem), 0);
2545753e2922SBryan Drewery }
2546753e2922SBryan Drewery 
2547753e2922SBryan Drewery /*
2548753e2922SBryan Drewery  * Verify that even if the signal queue is full for a child process,
2549753e2922SBryan Drewery  * and the signal is masked, a PT_CONTINUE with a signal will not
2550753e2922SBryan Drewery  * result in loss of that signal.
2551753e2922SBryan Drewery  */
2552753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
2553753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
2554753e2922SBryan Drewery {
2555753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2556753e2922SBryan Drewery 	pid_t fpid, wpid;
2557753e2922SBryan Drewery 	int status, err;
2558753e2922SBryan Drewery 	int max_pending_per_proc;
2559753e2922SBryan Drewery 	size_t len;
2560753e2922SBryan Drewery 	int i;
2561753e2922SBryan Drewery 	sigset_t sigmask;
2562753e2922SBryan Drewery 
2563753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
256496a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
2565753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2566753e2922SBryan Drewery 
2567753e2922SBryan Drewery 	got_usr1 = 0;
2568753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2569753e2922SBryan Drewery 	if (fpid == 0) {
257096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
257196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
257296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
2573753e2922SBryan Drewery 
2574753e2922SBryan Drewery 		trace_me();
257596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
2576753e2922SBryan Drewery 
2577753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
257896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
2579753e2922SBryan Drewery 		/* Wait to receive the SIGUSR1. */
2580753e2922SBryan Drewery 		do {
2581753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2582753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2583753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
258496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
2585753e2922SBryan Drewery 		exit(1);
2586753e2922SBryan Drewery 	}
2587753e2922SBryan Drewery 
2588753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2589753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
259096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2591753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
259296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
2593753e2922SBryan Drewery 
2594753e2922SBryan Drewery 	len = sizeof(max_pending_per_proc);
2595753e2922SBryan Drewery 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
2596753e2922SBryan Drewery 	    &max_pending_per_proc, &len, NULL, 0) == 0);
2597753e2922SBryan Drewery 
2598753e2922SBryan Drewery 	/* Fill the signal queue. */
2599753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i)
260096a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
2601753e2922SBryan Drewery 
2602753e2922SBryan Drewery 	/* Continue with signal. */
260396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
2604753e2922SBryan Drewery 
2605753e2922SBryan Drewery 	/* Collect and ignore all of the SIGUSR2. */
2606753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i) {
2607753e2922SBryan Drewery 		wpid = waitpid(fpid, &status, 0);
260896a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
2609753e2922SBryan Drewery 		ATF_REQUIRE(WIFSTOPPED(status));
261096a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
261196a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2612753e2922SBryan Drewery 	}
2613753e2922SBryan Drewery 
2614753e2922SBryan Drewery 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
2615753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
261696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2617753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
261896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
2619753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
262096a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
2621753e2922SBryan Drewery 
2622753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
262396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2624753e2922SBryan Drewery 
2625753e2922SBryan Drewery 	/* The last wait() should report exit after receiving SIGUSR1. */
2626753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
262796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2628753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
262996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
2630753e2922SBryan Drewery 
2631753e2922SBryan Drewery 	wpid = wait(&status);
263296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
263396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
2634753e2922SBryan Drewery }
2635753e2922SBryan Drewery 
263682a4538fSEric Badger /*
263782a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
263882a4538fSEric Badger  * replaced with another signal.
263982a4538fSEric Badger  */
264082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
264182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
264282a4538fSEric Badger {
264382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
264482a4538fSEric Badger 	pid_t fpid, wpid;
264582a4538fSEric Badger 	int status;
264682a4538fSEric Badger 
264782a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
264882a4538fSEric Badger 	if (fpid == 0) {
264982a4538fSEric Badger 		trace_me();
265082a4538fSEric Badger 		sleep(20);
265182a4538fSEric Badger 		exit(1);
265282a4538fSEric Badger 	}
265382a4538fSEric Badger 
265482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
265582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
265696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
265782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
265896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
265982a4538fSEric Badger 
266096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
266182a4538fSEric Badger 
266282a4538fSEric Badger 	/* Send a signal without ptrace. */
266396a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGINT), 0);
266482a4538fSEric Badger 
266582a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
266682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
266796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
266882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
266996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGINT);
267082a4538fSEric Badger 
267182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
267282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
267396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGINT);
267482a4538fSEric Badger 
267582a4538fSEric Badger 	/* Continue the child process with a different signal. */
267696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM), 0);
267782a4538fSEric Badger 
267882a4538fSEric Badger 	/*
267982a4538fSEric Badger 	 * The last wait() should report having died due to the new
268082a4538fSEric Badger 	 * signal, SIGTERM.
268182a4538fSEric Badger 	 */
268282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
268396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
268482a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
268596a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGTERM);
268682a4538fSEric Badger 
268782a4538fSEric Badger 	wpid = wait(&status);
268896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
268996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
269082a4538fSEric Badger }
269182a4538fSEric Badger 
269282a4538fSEric Badger /*
269382a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
269482a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
269582a4538fSEric Badger  * invented for e.g, system call stops.
269682a4538fSEric Badger  */
269782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
269882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
269982a4538fSEric Badger {
270082a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2701fc1e29dcSBryan Drewery 	struct rlimit rl;
270282a4538fSEric Badger 	pid_t fpid, wpid;
270382a4538fSEric Badger 	int status;
270482a4538fSEric Badger 
270582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
270682a4538fSEric Badger 	if (fpid == 0) {
270782a4538fSEric Badger 		trace_me();
2708fc1e29dcSBryan Drewery 		/* SIGTRAP expected to cause exit on syscall entry. */
2709fc1e29dcSBryan Drewery 		rl.rlim_cur = rl.rlim_max = 0;
271096a9e50eSAlex Richardson 		REQUIRE_EQ(setrlimit(RLIMIT_CORE, &rl), 0);
271182a4538fSEric Badger 		getpid();
271282a4538fSEric Badger 		exit(1);
271382a4538fSEric Badger 	}
271482a4538fSEric Badger 
271582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
271682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
271796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
271882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
271996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
272082a4538fSEric Badger 
272182a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
272296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
272382a4538fSEric Badger 
272482a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
272582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
272696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
272782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
272896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
272982a4538fSEric Badger 
273082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
273182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
273282a4538fSEric Badger 
273382a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
273496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP), 0);
273582a4538fSEric Badger 
273682a4538fSEric Badger 	for (;;) {
273782a4538fSEric Badger 		/*
273882a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
273982a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
274082a4538fSEric Badger 		 */
274182a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
274296a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
274382a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
274482a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
274582a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
274696a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
274782a4538fSEric Badger 		} else {
274882a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
274996a9e50eSAlex Richardson 			REQUIRE_EQ(WTERMSIG(status), SIGTRAP);
275082a4538fSEric Badger 			break;
275182a4538fSEric Badger 		}
275282a4538fSEric Badger 	}
275382a4538fSEric Badger 
275482a4538fSEric Badger 	wpid = wait(&status);
275596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
275696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
275782a4538fSEric Badger }
275882a4538fSEric Badger 
275982a4538fSEric Badger /*
276082a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
276182a4538fSEric Badger  */
276282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
276382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
276482a4538fSEric Badger {
276582a4538fSEric Badger 	struct ptrace_lwpinfo pl;
276682a4538fSEric Badger 	pid_t fpid, wpid;
276782a4538fSEric Badger 	int status;
276882a4538fSEric Badger 
276982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
277082a4538fSEric Badger 
277182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
277282a4538fSEric Badger 	if (fpid == 0) {
277382a4538fSEric Badger 		trace_me();
277482a4538fSEric Badger 		getpid();
277582a4538fSEric Badger 		exit(1);
277682a4538fSEric Badger 	}
277782a4538fSEric Badger 
277882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
277982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
278096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
278182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
278296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
278382a4538fSEric Badger 
278482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
278596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
278682a4538fSEric Badger 
278782a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
278882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
278996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
279082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
279196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
279282a4538fSEric Badger 
279382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
279482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
279582a4538fSEric Badger 
279682a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
279796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
279882a4538fSEric Badger 
279982a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
280082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
280196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
280282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
280396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
280482a4538fSEric Badger 
280582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
280682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
280782a4538fSEric Badger 
280882a4538fSEric Badger 	/* Send an ABRT without ptrace. */
280996a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGABRT), 0);
281082a4538fSEric Badger 
281182a4538fSEric Badger 	/* Continue normally. */
281296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
281382a4538fSEric Badger 
281482a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
281582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
281696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
281782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
281896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
281982a4538fSEric Badger 
282082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
282182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
282296a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
282382a4538fSEric Badger 
282482a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
282596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
282682a4538fSEric Badger 
282782a4538fSEric Badger 	for (;;) {
282882a4538fSEric Badger 		/*
282982a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
283082a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
283182a4538fSEric Badger 		 * past any syscall stops.
283282a4538fSEric Badger 		 */
283382a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
283496a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
283582a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
283682a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
283782a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
283896a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
283982a4538fSEric Badger 		} else {
284082a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
284196a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
284282a4538fSEric Badger 			break;
284382a4538fSEric Badger 		}
284482a4538fSEric Badger 	}
284582a4538fSEric Badger 
284682a4538fSEric Badger 	wpid = wait(&status);
284796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
284896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
284982a4538fSEric Badger }
285082a4538fSEric Badger 
285182a4538fSEric Badger /*
285282a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
285382a4538fSEric Badger  */
285482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
285582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
285682a4538fSEric Badger {
285782a4538fSEric Badger 	pid_t fpid, wpid;
285882a4538fSEric Badger 	int status, kq, nevents;
285982a4538fSEric Badger 	struct kevent kev;
286082a4538fSEric Badger 
286182a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
286282a4538fSEric Badger 
286382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
286482a4538fSEric Badger 	if (fpid == 0) {
286582a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
286682a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
286796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(kevent(kq, &kev, 1, NULL, 0, NULL), 0);
286882a4538fSEric Badger 
286982a4538fSEric Badger 		trace_me();
287082a4538fSEric Badger 
287182a4538fSEric Badger 		for (;;) {
287282a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
287382a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
287482a4538fSEric Badger 				continue;
287582a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
287696a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(kev.filter, EVFILT_SIGNAL);
28771fcbddecSAlex Richardson 			CHILD_REQUIRE_EQ(kev.ident, (uintptr_t)SIGUSR1);
287882a4538fSEric Badger 			break;
287982a4538fSEric Badger 		}
288082a4538fSEric Badger 
288182a4538fSEric Badger 		exit(1);
288282a4538fSEric Badger 	}
288382a4538fSEric Badger 
288482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
288582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
288696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
288782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
288896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
288982a4538fSEric Badger 
289082a4538fSEric Badger 	/* Continue with the SIGUSR1. */
289196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
289282a4538fSEric Badger 
289382a4538fSEric Badger 	/*
289482a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
289582a4538fSEric Badger 	 */
289682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
289796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
289882a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
289996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
290082a4538fSEric Badger 
290182a4538fSEric Badger 	wpid = wait(&status);
290296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
290396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
290482a4538fSEric Badger }
290582a4538fSEric Badger 
290682a4538fSEric Badger static void *
290782a4538fSEric Badger signal_thread(void *arg)
290882a4538fSEric Badger {
290982a4538fSEric Badger 	int err;
291082a4538fSEric Badger 	sigset_t sigmask;
291182a4538fSEric Badger 
291282a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
291382a4538fSEric Badger 
291482a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
291582a4538fSEric Badger 	do {
291682a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
291782a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
291882a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
291982a4538fSEric Badger 
292082a4538fSEric Badger 	/* Free our companion thread from the barrier. */
292182a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
292282a4538fSEric Badger 
292382a4538fSEric Badger 	/*
292482a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
292582a4538fSEric Badger 	 * other thread.
292682a4538fSEric Badger 	 */
292796a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
292896a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
292996a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
293082a4538fSEric Badger 
293182a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
293282a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
293382a4538fSEric Badger 
293482a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
293582a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
293682a4538fSEric Badger 
293782a4538fSEric Badger 	return (NULL);
293882a4538fSEric Badger }
293982a4538fSEric Badger 
294082a4538fSEric Badger /*
2941753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2942753e2922SBryan Drewery  * signal from kill() once unmasked.
2943753e2922SBryan Drewery  */
2944753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
2945753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
2946753e2922SBryan Drewery {
2947753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2948753e2922SBryan Drewery 	pid_t fpid, wpid;
2949753e2922SBryan Drewery 	int status, err;
2950753e2922SBryan Drewery 	sigset_t sigmask;
2951753e2922SBryan Drewery 
295296a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
2953753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2954753e2922SBryan Drewery 	got_usr1 = 0;
2955753e2922SBryan Drewery 
2956753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2957753e2922SBryan Drewery 	if (fpid == 0) {
295896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
295996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
296096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
2961753e2922SBryan Drewery 
2962753e2922SBryan Drewery 		trace_me();
296396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
2964753e2922SBryan Drewery 
2965753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
296696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
2967753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2968753e2922SBryan Drewery 		do {
2969753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2970753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2971753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
297296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
2973753e2922SBryan Drewery 		exit(1);
2974753e2922SBryan Drewery 	}
2975753e2922SBryan Drewery 
2976753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2977753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
297896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2979753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
298096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
2981753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
298296a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGSTOP);
2983753e2922SBryan Drewery 
2984753e2922SBryan Drewery 	/* Send blocked SIGUSR1 which should cause a stop. */
298596a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
2986753e2922SBryan Drewery 
2987753e2922SBryan Drewery 	/* Continue the child ignoring the SIGSTOP. */
298896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2989753e2922SBryan Drewery 
2990753e2922SBryan Drewery 	/* The next wait() should report the kill(SIGUSR1) was received. */
2991753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
299296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2993753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
299496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
2995753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
299696a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
2997753e2922SBryan Drewery 
2998753e2922SBryan Drewery 	/* Continue the child, allowing in the SIGUSR1. */
299996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
3000753e2922SBryan Drewery 
3001753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3002753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
300396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3004753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
300596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3006753e2922SBryan Drewery 
3007753e2922SBryan Drewery 	wpid = wait(&status);
300896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
300996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3010753e2922SBryan Drewery }
3011753e2922SBryan Drewery 
3012753e2922SBryan Drewery /*
3013753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
3014753e2922SBryan Drewery  * signal from PT_CONTINUE once unmasked.
3015753e2922SBryan Drewery  */
3016753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
3017753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
3018753e2922SBryan Drewery {
3019753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
3020753e2922SBryan Drewery 	pid_t fpid, wpid;
3021753e2922SBryan Drewery 	int status, err;
3022753e2922SBryan Drewery 	sigset_t sigmask;
3023753e2922SBryan Drewery 
302496a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
3025753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
3026753e2922SBryan Drewery 	got_usr1 = 0;
3027753e2922SBryan Drewery 
3028753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
3029753e2922SBryan Drewery 	if (fpid == 0) {
303096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
303196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
303296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
3033753e2922SBryan Drewery 
3034753e2922SBryan Drewery 		trace_me();
303596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
3036753e2922SBryan Drewery 
3037753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
303896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
3039753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
3040753e2922SBryan Drewery 		do {
3041753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
3042753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
3043753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
3044753e2922SBryan Drewery 
304596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
3046753e2922SBryan Drewery 		exit(1);
3047753e2922SBryan Drewery 	}
3048753e2922SBryan Drewery 
3049753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
3050753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
305196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3052753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
305396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3054753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
305596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGSTOP);
3056753e2922SBryan Drewery 
3057753e2922SBryan Drewery 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
305896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
3059753e2922SBryan Drewery 
3060753e2922SBryan Drewery 	/* The next wait() should report the SIGUSR1 was received. */
3061753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
306296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3063753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
306496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
3065753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
306696a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
3067753e2922SBryan Drewery 
3068753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
306996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3070753e2922SBryan Drewery 
3071753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3072753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
307396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3074753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
307596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3076753e2922SBryan Drewery 
3077753e2922SBryan Drewery 	wpid = wait(&status);
307896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
307996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3080753e2922SBryan Drewery }
3081753e2922SBryan Drewery 
3082753e2922SBryan Drewery /*
308382a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
308482a4538fSEric Badger  * a different signal that the new signal is routed to a thread
308599144520SEitan Adler  * that can accept it, and that the thread is awakened by the signal
308682a4538fSEric Badger  * in a timely manner.
308782a4538fSEric Badger  */
308882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
308982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
309082a4538fSEric Badger {
309182a4538fSEric Badger 	pid_t fpid, wpid;
309282a4538fSEric Badger 	int status, err;
309382a4538fSEric Badger 	pthread_t t;
309482a4538fSEric Badger 	sigset_t sigmask;
309582a4538fSEric Badger 	pthread_barrier_t barrier;
309682a4538fSEric Badger 
309796a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
309896a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
309982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
310082a4538fSEric Badger 
310182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
310282a4538fSEric Badger 	if (fpid == 0) {
310396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_create(&t, NULL, signal_thread,
310496a9e50eSAlex Richardson 		    (void *)&barrier), 0);
310582a4538fSEric Badger 
310682a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
310796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
310896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
310996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
311082a4538fSEric Badger 
311182a4538fSEric Badger 		trace_me();
311282a4538fSEric Badger 
311382a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
311482a4538fSEric Badger 		pthread_barrier_wait(&barrier);
311582a4538fSEric Badger 
311682a4538fSEric Badger 		/*
311782a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
311882a4538fSEric Badger 		 * thread.
311982a4538fSEric Badger 		 */
312096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL),
312196a9e50eSAlex Richardson 		    0);
312282a4538fSEric Badger 
312382a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
312482a4538fSEric Badger 		pthread_barrier_wait(&barrier);
312582a4538fSEric Badger 
312682a4538fSEric Badger 		/*
312782a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
312882a4538fSEric Badger 		 * now.
312982a4538fSEric Badger 		 */
313082a4538fSEric Badger 		raise(SIGSTOP);
313182a4538fSEric Badger 
313282a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
313382a4538fSEric Badger 		do {
313482a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
313582a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
313682a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
313782a4538fSEric Badger 
313882a4538fSEric Badger 		/* Free the other thread from the barrier. */
313982a4538fSEric Badger 		pthread_barrier_wait(&barrier);
314082a4538fSEric Badger 
314196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_join(t, NULL), 0);
314282a4538fSEric Badger 
314382a4538fSEric Badger 		exit(1);
314482a4538fSEric Badger 	}
314582a4538fSEric Badger 
314682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
314782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
314896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
314982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
315096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
315182a4538fSEric Badger 
315282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
315396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
315482a4538fSEric Badger 
315582a4538fSEric Badger 	/*
315682a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
315782a4538fSEric Badger 	 * in this case).
315882a4538fSEric Badger 	 */
315996a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
316082a4538fSEric Badger 
316182a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
316282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
316396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
316482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
316596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
316682a4538fSEric Badger 
316782a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
316896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
316982a4538fSEric Badger 
317082a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
317182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
317296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
317382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
317496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
317582a4538fSEric Badger 
317682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
317796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
317882a4538fSEric Badger 
317996a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
318082a4538fSEric Badger 
318182a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
318282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
318396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
318482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
318596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
318682a4538fSEric Badger 
318782a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
318896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
318982a4538fSEric Badger 
319082a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
319182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
319296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
319382a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
319496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
319582a4538fSEric Badger 
319682a4538fSEric Badger 	wpid = wait(&status);
319796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
319896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
319982a4538fSEric Badger }
320082a4538fSEric Badger 
3201*548a2ec4SAndrew Turner /*
3202*548a2ec4SAndrew Turner  * Verify that PT_GETREGSET returns registers and PT_SETREGSET updates them.
3203*548a2ec4SAndrew Turner  */
3204*548a2ec4SAndrew Turner ATF_TC_WITHOUT_HEAD(ptrace__PT_REGSET);
3205*548a2ec4SAndrew Turner ATF_TC_BODY(ptrace__PT_REGSET, tc)
3206*548a2ec4SAndrew Turner {
3207*548a2ec4SAndrew Turner 	struct prstatus prstatus;
3208*548a2ec4SAndrew Turner 	struct iovec vec;
3209*548a2ec4SAndrew Turner 	pid_t child, wpid;
3210*548a2ec4SAndrew Turner 	int status;
3211*548a2ec4SAndrew Turner 
3212*548a2ec4SAndrew Turner 	ATF_REQUIRE((child = fork()) != -1);
3213*548a2ec4SAndrew Turner 	if (child == 0) {
3214*548a2ec4SAndrew Turner 		trace_me();
3215*548a2ec4SAndrew Turner 		exit(1);
3216*548a2ec4SAndrew Turner 	}
3217*548a2ec4SAndrew Turner 
3218*548a2ec4SAndrew Turner 	/* The first wait() should report the stop from SIGSTOP. */
3219*548a2ec4SAndrew Turner 	wpid = waitpid(child, &status, 0);
3220*548a2ec4SAndrew Turner 	REQUIRE_EQ(wpid, child);
3221*548a2ec4SAndrew Turner 	ATF_REQUIRE(WIFSTOPPED(status));
3222*548a2ec4SAndrew Turner 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3223*548a2ec4SAndrew Turner 
3224*548a2ec4SAndrew Turner 	/* Check the size is returned when vec.iov_base is NULL */
3225*548a2ec4SAndrew Turner 	vec.iov_base = NULL;
3226*548a2ec4SAndrew Turner 	vec.iov_len = 0;
3227*548a2ec4SAndrew Turner 	ATF_REQUIRE(ptrace(PT_GETREGSET, wpid, (caddr_t)&vec, NT_PRSTATUS) !=
3228*548a2ec4SAndrew Turner 	    -1);
3229*548a2ec4SAndrew Turner 	ATF_REQUIRE(vec.iov_len == sizeof(prstatus));
3230*548a2ec4SAndrew Turner 	ATF_REQUIRE(vec.iov_base == NULL);
3231*548a2ec4SAndrew Turner 
3232*548a2ec4SAndrew Turner 	/* Read the registers. */
3233*548a2ec4SAndrew Turner 	memset(&prstatus, 0, sizeof(prstatus));
3234*548a2ec4SAndrew Turner 	vec.iov_base = &prstatus;
3235*548a2ec4SAndrew Turner 	ATF_REQUIRE(ptrace(PT_GETREGSET, wpid, (caddr_t)&vec, NT_PRSTATUS) !=
3236*548a2ec4SAndrew Turner 	    -1);
3237*548a2ec4SAndrew Turner 	ATF_REQUIRE(vec.iov_len == sizeof(prstatus));
3238*548a2ec4SAndrew Turner 	ATF_REQUIRE(vec.iov_base == &prstatus);
3239*548a2ec4SAndrew Turner 	ATF_REQUIRE(prstatus.pr_statussz == sizeof(prstatus));
3240*548a2ec4SAndrew Turner 
3241*548a2ec4SAndrew Turner 	/* Write the registers back. */
3242*548a2ec4SAndrew Turner 	ATF_REQUIRE(ptrace(PT_SETREGSET, wpid, (caddr_t)&vec, NT_PRSTATUS) !=
3243*548a2ec4SAndrew Turner 	    -1);
3244*548a2ec4SAndrew Turner 
3245*548a2ec4SAndrew Turner 	REQUIRE_EQ(ptrace(PT_CONTINUE, child, (caddr_t)1, 0), 0);
3246*548a2ec4SAndrew Turner 
3247*548a2ec4SAndrew Turner 	/* The second wait() should report the exit status. */
3248*548a2ec4SAndrew Turner 	wpid = waitpid(child, &status, 0);
3249*548a2ec4SAndrew Turner 	REQUIRE_EQ(wpid, child);
3250*548a2ec4SAndrew Turner 	ATF_REQUIRE(WIFEXITED(status));
3251*548a2ec4SAndrew Turner 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3252*548a2ec4SAndrew Turner 
3253*548a2ec4SAndrew Turner 	/* The child should no longer exist. */
3254*548a2ec4SAndrew Turner 	wpid = waitpid(child, &status, 0);
3255*548a2ec4SAndrew Turner 	REQUIRE_EQ(wpid, -1);
3256*548a2ec4SAndrew Turner 	REQUIRE_EQ(errno, ECHILD);
3257*548a2ec4SAndrew Turner }
3258*548a2ec4SAndrew Turner 
3259b38bd91fSEric Badger static void *
3260b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
3261b38bd91fSEric Badger {
3262b38bd91fSEric Badger 
3263b38bd91fSEric Badger 	raise(SIGSTOP);
3264b38bd91fSEric Badger 	return NULL;
3265b38bd91fSEric Badger }
3266b38bd91fSEric Badger 
3267b38bd91fSEric Badger static void *
3268b38bd91fSEric Badger sleep_thread(void *arg __unused)
3269b38bd91fSEric Badger {
3270b38bd91fSEric Badger 
3271b38bd91fSEric Badger 	sleep(60);
3272b38bd91fSEric Badger 	return NULL;
3273b38bd91fSEric Badger }
3274b38bd91fSEric Badger 
3275b38bd91fSEric Badger static void
3276b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
3277b38bd91fSEric Badger {
3278b38bd91fSEric Badger 	pid_t fpid, wpid;
3279b38bd91fSEric Badger 	int status, i;
3280b38bd91fSEric Badger 	cpuset_t setmask;
3281b38bd91fSEric Badger 	cpusetid_t setid;
3282b38bd91fSEric Badger 	pthread_t t;
3283b38bd91fSEric Badger 
3284b38bd91fSEric Badger 	/*
3285b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
3286b38bd91fSEric Badger 	 * that both child and grandchild have died.
3287b38bd91fSEric Badger 	 */
328896a9e50eSAlex Richardson 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
3289b38bd91fSEric Badger 
3290b38bd91fSEric Badger 	fpid = fork();
3291b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
3292b38bd91fSEric Badger 	if (fpid == 0) {
3293b38bd91fSEric Badger 		fpid = fork();
3294b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
3295b38bd91fSEric Badger 		if (fpid == 0) {
3296b38bd91fSEric Badger 			trace_me();
3297b38bd91fSEric Badger 
3298b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
3299b38bd91fSEric Badger 			CPU_ZERO(&setmask);
3300b38bd91fSEric Badger 			CPU_SET(0, &setmask);
330196a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(cpuset(&setid), 0);
3302b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
3303b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
3304b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
3305b38bd91fSEric Badger 
3306b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
3307b38bd91fSEric Badger 				/*
3308b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
3309b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
3310b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
3311b38bd91fSEric Badger 				 * threads compete.
3312b38bd91fSEric Badger 				 */
3313b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3314b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
3315b38bd91fSEric Badger 				raise(SIGSTOP);
3316b38bd91fSEric Badger 			} else {
3317b38bd91fSEric Badger 				/*
3318b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
3319b38bd91fSEric Badger 				 * this thread. After creating the new thread,
3320b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
3321b38bd91fSEric Badger 				 * raise the SIGSTOP.
3322b38bd91fSEric Badger 				 */
3323b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3324b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
3325b38bd91fSEric Badger 				sleep(60);
3326b38bd91fSEric Badger 			}
3327b38bd91fSEric Badger 
3328b38bd91fSEric Badger 			exit(0);
3329b38bd91fSEric Badger 		}
3330b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
3331b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
333296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, fpid);
3333b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
333496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3335b38bd91fSEric Badger 
333696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3337b38bd91fSEric Badger 
3338b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
3339b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
334096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, fpid);
3341b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
334296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3343b38bd91fSEric Badger 
3344b38bd91fSEric Badger 		/*
3345b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
3346b38bd91fSEric Badger 		 * should be killed.
3347b38bd91fSEric Badger 		 */
3348b38bd91fSEric Badger 		exit(0);
3349b38bd91fSEric Badger 	}
3350b38bd91fSEric Badger 
3351b38bd91fSEric Badger 	/*
3352b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
3353b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
3354b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
3355b38bd91fSEric Badger 	 * left dangling when its parent died.
3356b38bd91fSEric Badger 	 */
3357b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
3358b38bd91fSEric Badger 		wpid = wait(&status);
335996a9e50eSAlex Richardson 		if (wpid == fpid) {
336096a9e50eSAlex Richardson 			ATF_REQUIRE(WIFEXITED(status));
336196a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 0);
336296a9e50eSAlex Richardson 		} else {
336396a9e50eSAlex Richardson 			ATF_REQUIRE(WIFSIGNALED(status));
336496a9e50eSAlex Richardson 			REQUIRE_EQ(WTERMSIG(status), SIGKILL);
336596a9e50eSAlex Richardson 		}
3366b38bd91fSEric Badger 	}
3367b38bd91fSEric Badger }
3368b38bd91fSEric Badger 
3369b38bd91fSEric Badger /*
3370b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
3371b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
3372b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
3373b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
3374b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
3375b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
3376b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
3377b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
3378b38bd91fSEric Badger  * past, so make no assumption.
3379b38bd91fSEric Badger  */
33803cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
33813cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
33823cf56bb4SEnji Cooper {
33833cf56bb4SEnji Cooper 
33843cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33853cf56bb4SEnji Cooper }
3386b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
3387b38bd91fSEric Badger {
3388b38bd91fSEric Badger 
3389b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
3390b38bd91fSEric Badger }
33913cf56bb4SEnji Cooper 
33923cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
33933cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
33943cf56bb4SEnji Cooper {
33953cf56bb4SEnji Cooper 
33963cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33973cf56bb4SEnji Cooper }
3398b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
3399b38bd91fSEric Badger {
3400b38bd91fSEric Badger 
3401b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
3402b38bd91fSEric Badger }
3403b38bd91fSEric Badger 
3404b4d33259SEric Badger /*
3405b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
3406b4d33259SEric Badger  * is not modified.
3407b4d33259SEric Badger  */
3408b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
3409b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
3410b4d33259SEric Badger {
3411b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
3412b4d33259SEric Badger 	pid_t fpid, wpid;
3413b4d33259SEric Badger 	int status, event_mask, new_event_mask;
3414b4d33259SEric Badger 
3415b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
3416b4d33259SEric Badger 	if (fpid == 0) {
3417b4d33259SEric Badger 		trace_me();
3418b4d33259SEric Badger 		raise(SIGSTOP);
3419b4d33259SEric Badger 		exit(0);
3420b4d33259SEric Badger 	}
3421b4d33259SEric Badger 
3422b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
3423b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
342496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3425b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
342696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3427b4d33259SEric Badger 
3428b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
3429b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
3430b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
3431b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
3432b4d33259SEric Badger 
3433b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
343496a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGKILL), 0);
3435b4d33259SEric Badger 
3436b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
343796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3438b4d33259SEric Badger 
3439b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
3440b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
344196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3442b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
344396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGKILL);
3444b4d33259SEric Badger 
3445b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3446b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
344796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGKILL);
3448b4d33259SEric Badger 
3449b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
345096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3451b4d33259SEric Badger 
3452b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
3453b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
345496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3455b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
345696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3457b4d33259SEric Badger 
3458b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
3459b4d33259SEric Badger 	new_event_mask = 0;
3460b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
3461b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
346296a9e50eSAlex Richardson 	REQUIRE_EQ(event_mask, new_event_mask);
3463b4d33259SEric Badger 
3464b4d33259SEric Badger 	/* Continue the child to let it exit. */
346596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3466b4d33259SEric Badger 
3467b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
3468b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3469b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
347096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
3471b4d33259SEric Badger 
3472b4d33259SEric Badger 	wpid = wait(&status);
347396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
347496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3475b4d33259SEric Badger }
3476b4d33259SEric Badger 
3477d74da94cSMark Johnston static void *
3478d74da94cSMark Johnston flock_thread(void *arg)
3479d74da94cSMark Johnston {
3480d74da94cSMark Johnston 	int fd;
3481d74da94cSMark Johnston 
3482d74da94cSMark Johnston 	fd = *(int *)arg;
3483d74da94cSMark Johnston 	(void)flock(fd, LOCK_EX);
3484d74da94cSMark Johnston 	(void)flock(fd, LOCK_UN);
3485d74da94cSMark Johnston 	return (NULL);
3486d74da94cSMark Johnston }
3487d74da94cSMark Johnston 
3488d74da94cSMark Johnston /*
3489d74da94cSMark Johnston  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
3490d74da94cSMark Johnston  * We rely on the fact that the lockf implementation sets SBDRY before blocking
3491d74da94cSMark Johnston  * on a lock. This is a regression test for r318191.
3492d74da94cSMark Johnston  */
3493d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
3494d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
3495d74da94cSMark Johnston {
3496d74da94cSMark Johnston 	pthread_barrier_t barrier;
3497d74da94cSMark Johnston 	pthread_barrierattr_t battr;
3498d74da94cSMark Johnston 	char tmpfile[64];
3499d74da94cSMark Johnston 	pid_t child, wpid;
3500d74da94cSMark Johnston 	int error, fd, i, status;
3501d74da94cSMark Johnston 
350296a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrierattr_init(&battr), 0);
3503d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
3504d74da94cSMark Johnston 	    PTHREAD_PROCESS_SHARED) == 0);
350596a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrier_init(&barrier, &battr, 2), 0);
3506d74da94cSMark Johnston 
3507d74da94cSMark Johnston 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
3508d74da94cSMark Johnston 	fd = mkstemp(tmpfile);
3509d74da94cSMark Johnston 	ATF_REQUIRE(fd >= 0);
3510d74da94cSMark Johnston 
3511d74da94cSMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
3512d74da94cSMark Johnston 	if (child == 0) {
3513d74da94cSMark Johnston 		pthread_t t[2];
351496437391SBryan Drewery 		int cfd;
3515d74da94cSMark Johnston 
3516d74da94cSMark Johnston 		error = pthread_barrier_wait(&barrier);
3517d74da94cSMark Johnston 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
3518d74da94cSMark Johnston 			_exit(1);
3519d74da94cSMark Johnston 
3520d74da94cSMark Johnston 		cfd = open(tmpfile, O_RDONLY);
3521d74da94cSMark Johnston 		if (cfd < 0)
3522d74da94cSMark Johnston 			_exit(1);
3523d74da94cSMark Johnston 
3524d74da94cSMark Johnston 		/*
3525d74da94cSMark Johnston 		 * We want at least two threads blocked on the file lock since
3526d74da94cSMark Johnston 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
3527d74da94cSMark Johnston 		 * sleep.
3528d74da94cSMark Johnston 		 */
3529d74da94cSMark Johnston 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
3530d74da94cSMark Johnston 			_exit(1);
3531d74da94cSMark Johnston 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
3532d74da94cSMark Johnston 			_exit(1);
3533d74da94cSMark Johnston 		if (pthread_join(t[0], NULL) != 0)
3534d74da94cSMark Johnston 			_exit(1);
3535d74da94cSMark Johnston 		if (pthread_join(t[1], NULL) != 0)
3536d74da94cSMark Johnston 			_exit(1);
3537d74da94cSMark Johnston 		_exit(0);
3538d74da94cSMark Johnston 	}
3539d74da94cSMark Johnston 
354096a9e50eSAlex Richardson 	REQUIRE_EQ(flock(fd, LOCK_EX), 0);
3541d74da94cSMark Johnston 
3542d74da94cSMark Johnston 	error = pthread_barrier_wait(&barrier);
3543d74da94cSMark Johnston 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
3544d74da94cSMark Johnston 
3545d74da94cSMark Johnston 	/*
3546d74da94cSMark Johnston 	 * Give the child some time to block. Is there a better way to do this?
3547d74da94cSMark Johnston 	 */
3548d74da94cSMark Johnston 	sleep(1);
3549d74da94cSMark Johnston 
3550d74da94cSMark Johnston 	/*
3551d74da94cSMark Johnston 	 * Attach and give the child 3 seconds to stop.
3552d74da94cSMark Johnston 	 */
355396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, child, NULL, 0), 0);
3554d74da94cSMark Johnston 	for (i = 0; i < 3; i++) {
3555d74da94cSMark Johnston 		wpid = waitpid(child, &status, WNOHANG);
3556d74da94cSMark Johnston 		if (wpid == child && WIFSTOPPED(status) &&
3557d74da94cSMark Johnston 		    WSTOPSIG(status) == SIGSTOP)
3558d74da94cSMark Johnston 			break;
3559d74da94cSMark Johnston 		sleep(1);
3560d74da94cSMark Johnston 	}
3561d74da94cSMark Johnston 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
3562d74da94cSMark Johnston 
356396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_DETACH, child, NULL, 0), 0);
3564d74da94cSMark Johnston 
356596a9e50eSAlex Richardson 	REQUIRE_EQ(flock(fd, LOCK_UN), 0);
356696a9e50eSAlex Richardson 	REQUIRE_EQ(unlink(tmpfile), 0);
356796a9e50eSAlex Richardson 	REQUIRE_EQ(close(fd), 0);
3568d74da94cSMark Johnston }
3569d74da94cSMark Johnston 
357054cfb29eSJohn Baldwin static void
357154cfb29eSJohn Baldwin sigusr1_step_handler(int sig)
357254cfb29eSJohn Baldwin {
357354cfb29eSJohn Baldwin 
357496a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
357554cfb29eSJohn Baldwin 	raise(SIGABRT);
357654cfb29eSJohn Baldwin }
357754cfb29eSJohn Baldwin 
357854cfb29eSJohn Baldwin /*
357954cfb29eSJohn Baldwin  * Verify that PT_STEP with a signal invokes the signal before
358054cfb29eSJohn Baldwin  * stepping the next instruction (and that the next instruction is
358154cfb29eSJohn Baldwin  * stepped correctly).
358254cfb29eSJohn Baldwin  */
358354cfb29eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal);
358454cfb29eSJohn Baldwin ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
358554cfb29eSJohn Baldwin {
358654cfb29eSJohn Baldwin 	struct ptrace_lwpinfo pl;
358754cfb29eSJohn Baldwin 	pid_t fpid, wpid;
358854cfb29eSJohn Baldwin 	int status;
358954cfb29eSJohn Baldwin 
359054cfb29eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
359154cfb29eSJohn Baldwin 	if (fpid == 0) {
359254cfb29eSJohn Baldwin 		trace_me();
359354cfb29eSJohn Baldwin 		signal(SIGUSR1, sigusr1_step_handler);
359454cfb29eSJohn Baldwin 		raise(SIGABRT);
359554cfb29eSJohn Baldwin 		exit(1);
359654cfb29eSJohn Baldwin 	}
359754cfb29eSJohn Baldwin 
359854cfb29eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
359954cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
360096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
360154cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
360296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
360354cfb29eSJohn Baldwin 
360496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
360554cfb29eSJohn Baldwin 
360654cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
360754cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
360896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
360954cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
361096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
361154cfb29eSJohn Baldwin 
361254cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
361354cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
361496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
361554cfb29eSJohn Baldwin 
361654cfb29eSJohn Baldwin 	/* Step the child process inserting SIGUSR1. */
361796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1), 0);
361854cfb29eSJohn Baldwin 
361954cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the signal handler. */
362054cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
362196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
362254cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
362396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
362454cfb29eSJohn Baldwin 
362554cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
362654cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
362796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
362854cfb29eSJohn Baldwin 
362954cfb29eSJohn Baldwin 	/* Continue the child process discarding the signal. */
363096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
363154cfb29eSJohn Baldwin 
363254cfb29eSJohn Baldwin 	/* The next stop should report a trace trap from PT_STEP. */
363354cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
363496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
363554cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
363696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
363754cfb29eSJohn Baldwin 
363854cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
363954cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
364096a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
364196a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_TRACE);
364254cfb29eSJohn Baldwin 
364354cfb29eSJohn Baldwin 	/* Continue the child to let it exit. */
364496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
364554cfb29eSJohn Baldwin 
364654cfb29eSJohn Baldwin 	/* The last event should be for the child process's exit. */
364754cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
364854cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
364996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
365054cfb29eSJohn Baldwin 
365154cfb29eSJohn Baldwin 	wpid = wait(&status);
365296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
365396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
365454cfb29eSJohn Baldwin }
365554cfb29eSJohn Baldwin 
3656643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3657643ce7deSJohn Baldwin /*
3658643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported
3659643ce7deSJohn Baldwin  * for a breakpoint trap.
3660643ce7deSJohn Baldwin  */
3661643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo);
3662643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__breakpoint_siginfo, tc)
3663643ce7deSJohn Baldwin {
3664643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3665643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3666643ce7deSJohn Baldwin 	int status;
3667643ce7deSJohn Baldwin 
3668643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3669643ce7deSJohn Baldwin 	if (fpid == 0) {
3670643ce7deSJohn Baldwin 		trace_me();
3671643ce7deSJohn Baldwin 		breakpoint();
3672643ce7deSJohn Baldwin 		exit(1);
3673643ce7deSJohn Baldwin 	}
3674643ce7deSJohn Baldwin 
3675643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3676643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
367796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3678643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
367996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3680643ce7deSJohn Baldwin 
3681643ce7deSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
368296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3683643ce7deSJohn Baldwin 
3684643ce7deSJohn Baldwin 	/* The second wait() should report hitting the breakpoint. */
3685643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
368696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3687643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
368896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3689643ce7deSJohn Baldwin 
3690643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3691643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
369296a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
369396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3694643ce7deSJohn Baldwin 
3695643ce7deSJohn Baldwin 	/* Kill the child process. */
369696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
3697643ce7deSJohn Baldwin 
3698643ce7deSJohn Baldwin 	/* The last wait() should report the SIGKILL. */
3699643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
370096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3701643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSIGNALED(status));
370296a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
3703643ce7deSJohn Baldwin 
3704643ce7deSJohn Baldwin 	wpid = wait(&status);
370596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
370696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3707643ce7deSJohn Baldwin }
3708643ce7deSJohn Baldwin #endif /* HAVE_BREAKPOINT */
3709643ce7deSJohn Baldwin 
3710643ce7deSJohn Baldwin /*
3711643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_TRACE code is reported
3712643ce7deSJohn Baldwin  * for a single-step trap from PT_STEP.
3713643ce7deSJohn Baldwin  */
3714643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo);
3715643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__step_siginfo, tc)
3716643ce7deSJohn Baldwin {
3717643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3718643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3719643ce7deSJohn Baldwin 	int status;
3720643ce7deSJohn Baldwin 
3721643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3722643ce7deSJohn Baldwin 	if (fpid == 0) {
3723643ce7deSJohn Baldwin 		trace_me();
3724643ce7deSJohn Baldwin 		exit(1);
3725643ce7deSJohn Baldwin 	}
3726643ce7deSJohn Baldwin 
3727643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3728643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
372996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3730643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
373196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3732643ce7deSJohn Baldwin 
3733643ce7deSJohn Baldwin 	/* Step the child ignoring the SIGSTOP. */
373496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, 0), 0);
3735643ce7deSJohn Baldwin 
3736643ce7deSJohn Baldwin 	/* The second wait() should report a single-step trap. */
3737643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
373896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3739643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
374096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3741643ce7deSJohn Baldwin 
3742643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3743643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
374496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
374596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_TRACE);
3746643ce7deSJohn Baldwin 
3747643ce7deSJohn Baldwin 	/* Continue the child process. */
374896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3749643ce7deSJohn Baldwin 
3750643ce7deSJohn Baldwin 	/* The last event should be for the child process's exit. */
3751643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3752643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
375396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3754643ce7deSJohn Baldwin 
3755643ce7deSJohn Baldwin 	wpid = wait(&status);
375696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
375796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3758643ce7deSJohn Baldwin }
3759643ce7deSJohn Baldwin 
3760403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3761e012fe34SJohn Baldwin static void *
3762e0a40f30SJohn Baldwin continue_thread(void *arg __unused)
3763e012fe34SJohn Baldwin {
3764e012fe34SJohn Baldwin 	breakpoint();
3765e012fe34SJohn Baldwin 	return (NULL);
3766e012fe34SJohn Baldwin }
3767e012fe34SJohn Baldwin 
3768e012fe34SJohn Baldwin static __dead2 void
3769e012fe34SJohn Baldwin continue_thread_main(void)
3770e012fe34SJohn Baldwin {
3771e012fe34SJohn Baldwin 	pthread_t threads[2];
3772e012fe34SJohn Baldwin 
3773e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
3774e012fe34SJohn Baldwin 	    NULL) == 0);
3775e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
3776e012fe34SJohn Baldwin 	    NULL) == 0);
377796a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(threads[0], NULL), 0);
377896a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(threads[1], NULL), 0);
3779e012fe34SJohn Baldwin 	exit(1);
3780e012fe34SJohn Baldwin }
3781e012fe34SJohn Baldwin 
3782e012fe34SJohn Baldwin /*
3783e012fe34SJohn Baldwin  * Ensure that PT_CONTINUE clears the status of the thread that
3784e012fe34SJohn Baldwin  * triggered the stop even if a different thread's LWP was passed to
3785e012fe34SJohn Baldwin  * PT_CONTINUE.
3786e012fe34SJohn Baldwin  */
3787e012fe34SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
3788e012fe34SJohn Baldwin ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
3789e012fe34SJohn Baldwin {
3790e012fe34SJohn Baldwin 	struct ptrace_lwpinfo pl;
3791e012fe34SJohn Baldwin 	pid_t fpid, wpid;
3792e012fe34SJohn Baldwin 	lwpid_t lwps[2];
3793e012fe34SJohn Baldwin 	bool hit_break[2];
3794403e331dSJohn Baldwin 	struct reg reg;
3795e012fe34SJohn Baldwin 	int i, j, status;
3796e012fe34SJohn Baldwin 
3797e012fe34SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3798e012fe34SJohn Baldwin 	if (fpid == 0) {
3799e012fe34SJohn Baldwin 		trace_me();
3800e012fe34SJohn Baldwin 		continue_thread_main();
3801e012fe34SJohn Baldwin 	}
3802e012fe34SJohn Baldwin 
3803e012fe34SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3804e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
380596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3806e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
380796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3808e012fe34SJohn Baldwin 
3809e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3810e012fe34SJohn Baldwin 	    sizeof(pl)) != -1);
3811e012fe34SJohn Baldwin 
381296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
3813e012fe34SJohn Baldwin 
3814e012fe34SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
381596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3816e012fe34SJohn Baldwin 
3817e012fe34SJohn Baldwin 	/* One of the new threads should report it's birth. */
3818e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
381996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3820e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
382196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3822e012fe34SJohn Baldwin 
3823e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
382496a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
3825e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3826e012fe34SJohn Baldwin 	lwps[0] = pl.pl_lwpid;
3827e012fe34SJohn Baldwin 
3828e012fe34SJohn Baldwin 	/*
3829e012fe34SJohn Baldwin 	 * Suspend this thread to ensure both threads are alive before
3830e012fe34SJohn Baldwin 	 * hitting the breakpoint.
3831e012fe34SJohn Baldwin 	 */
3832e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
3833e012fe34SJohn Baldwin 
383496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3835e012fe34SJohn Baldwin 
3836e012fe34SJohn Baldwin 	/* Second thread should report it's birth. */
3837e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
383896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3839e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
384096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3841e012fe34SJohn Baldwin 
3842e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
384396a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
3844e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3845e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
3846e012fe34SJohn Baldwin 	lwps[1] = pl.pl_lwpid;
3847e012fe34SJohn Baldwin 
3848e012fe34SJohn Baldwin 	/* Resume both threads waiting for breakpoint events. */
3849e012fe34SJohn Baldwin 	hit_break[0] = hit_break[1] = false;
3850e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
385196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3852e012fe34SJohn Baldwin 
3853e012fe34SJohn Baldwin 	/* One thread should report a breakpoint. */
3854e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
385596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3856e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
385796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3858e012fe34SJohn Baldwin 
3859e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3860e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
386196a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
386296a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3863e012fe34SJohn Baldwin 	if (pl.pl_lwpid == lwps[0])
3864e012fe34SJohn Baldwin 		i = 0;
3865e012fe34SJohn Baldwin 	else
3866e012fe34SJohn Baldwin 		i = 1;
3867e012fe34SJohn Baldwin 	hit_break[i] = true;
3868403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3869403e331dSJohn Baldwin 	SKIP_BREAK(&reg);
3870403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3871e012fe34SJohn Baldwin 
3872e012fe34SJohn Baldwin 	/*
3873e012fe34SJohn Baldwin 	 * Resume both threads but pass the other thread's LWPID to
3874e012fe34SJohn Baldwin 	 * PT_CONTINUE.
3875e012fe34SJohn Baldwin 	 */
387696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0), 0);
3877e012fe34SJohn Baldwin 
3878e012fe34SJohn Baldwin 	/*
3879e012fe34SJohn Baldwin 	 * Will now get two thread exit events and one more breakpoint
3880e012fe34SJohn Baldwin 	 * event.
3881e012fe34SJohn Baldwin 	 */
3882e012fe34SJohn Baldwin 	for (j = 0; j < 3; j++) {
3883e012fe34SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
388496a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
3885e012fe34SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
388696a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3887e012fe34SJohn Baldwin 
3888e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3889e012fe34SJohn Baldwin 		    sizeof(pl)) != -1);
3890e012fe34SJohn Baldwin 
3891e012fe34SJohn Baldwin 		if (pl.pl_lwpid == lwps[0])
3892e012fe34SJohn Baldwin 			i = 0;
3893e012fe34SJohn Baldwin 		else
3894e012fe34SJohn Baldwin 			i = 1;
3895e012fe34SJohn Baldwin 
3896e012fe34SJohn Baldwin 		ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
3897e012fe34SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_EXITED) {
3898e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(hit_break[i],
3899e012fe34SJohn Baldwin 			    "exited thread did not report breakpoint");
3900e012fe34SJohn Baldwin 			lwps[i] = 0;
3901e012fe34SJohn Baldwin 		} else {
3902e012fe34SJohn Baldwin 			ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
390396a9e50eSAlex Richardson 			REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
390496a9e50eSAlex Richardson 			REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3905e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(!hit_break[i],
3906e012fe34SJohn Baldwin 			    "double breakpoint event");
3907e012fe34SJohn Baldwin 			hit_break[i] = true;
3908403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
3909403e331dSJohn Baldwin 			    0) != -1);
3910403e331dSJohn Baldwin 			SKIP_BREAK(&reg);
3911403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
3912403e331dSJohn Baldwin 			    0) != -1);
3913e012fe34SJohn Baldwin 		}
3914e012fe34SJohn Baldwin 
391596a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3916e012fe34SJohn Baldwin 	}
3917e012fe34SJohn Baldwin 
3918e012fe34SJohn Baldwin 	/* Both threads should have exited. */
391996a9e50eSAlex Richardson 	REQUIRE_EQ(lwps[0], 0);
392096a9e50eSAlex Richardson 	REQUIRE_EQ(lwps[1], 0);
3921e012fe34SJohn Baldwin 
3922e012fe34SJohn Baldwin 	/* The last event should be for the child process's exit. */
3923e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3924e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
392596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3926e012fe34SJohn Baldwin 
3927e012fe34SJohn Baldwin 	wpid = wait(&status);
392896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
392996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3930e012fe34SJohn Baldwin }
3931e012fe34SJohn Baldwin #endif
3932e012fe34SJohn Baldwin 
3933c5786670SJohn Baldwin /*
3934c5786670SJohn Baldwin  * Verify that PT_LWPINFO doesn't return stale siginfo.
3935c5786670SJohn Baldwin  */
3936c5786670SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_LWPINFO_stale_siginfo);
3937c5786670SJohn Baldwin ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo, tc)
3938c5786670SJohn Baldwin {
3939c5786670SJohn Baldwin 	struct ptrace_lwpinfo pl;
3940c5786670SJohn Baldwin 	pid_t fpid, wpid;
3941c5786670SJohn Baldwin 	int events, status;
3942c5786670SJohn Baldwin 
3943c5786670SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3944c5786670SJohn Baldwin 	if (fpid == 0) {
3945c5786670SJohn Baldwin 		trace_me();
3946c5786670SJohn Baldwin 		raise(SIGABRT);
3947c5786670SJohn Baldwin 		exit(1);
3948c5786670SJohn Baldwin 	}
3949c5786670SJohn Baldwin 
3950c5786670SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3951c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
395296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3953c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
395496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3955c5786670SJohn Baldwin 
395696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3957c5786670SJohn Baldwin 
3958c5786670SJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
3959c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
396096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3961c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
396296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
3963c5786670SJohn Baldwin 
3964c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3965c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
396696a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
3967c5786670SJohn Baldwin 
3968c5786670SJohn Baldwin 	/*
3969c5786670SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
3970c5786670SJohn Baldwin 	 * syscall traps.
3971c5786670SJohn Baldwin 	 */
397296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
3973c5786670SJohn Baldwin 
3974c5786670SJohn Baldwin 	/*
3975c5786670SJohn Baldwin 	 * The next stop should report a system call entry from
3976c5786670SJohn Baldwin 	 * exit().  PL_FLAGS_SI should not be set.
3977c5786670SJohn Baldwin 	 */
3978c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
397996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3980c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
398196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3982c5786670SJohn Baldwin 
3983c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3984c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
398596a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & PL_FLAG_SI), 0);
3986c5786670SJohn Baldwin 
3987c5786670SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
3988c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
3989c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3990c5786670SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
3991c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
3992c5786670SJohn Baldwin 	    sizeof(events)) == 0);
399396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3994c5786670SJohn Baldwin 
3995c5786670SJohn Baldwin 	/* The last event should be for the child process's exit. */
3996c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3997c5786670SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
399896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3999c5786670SJohn Baldwin 
4000c5786670SJohn Baldwin 	wpid = wait(&status);
400196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
400296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4003c5786670SJohn Baldwin }
4004c5786670SJohn Baldwin 
4005c8ea8731SJohn Baldwin /*
400632451fb9SJohn Baldwin  * A simple test of PT_GET_SC_ARGS and PT_GET_SC_RET.
4007c8ea8731SJohn Baldwin  */
4008c8ea8731SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__syscall_args);
4009c8ea8731SJohn Baldwin ATF_TC_BODY(ptrace__syscall_args, tc)
4010c8ea8731SJohn Baldwin {
4011c8ea8731SJohn Baldwin 	struct ptrace_lwpinfo pl;
401232451fb9SJohn Baldwin 	struct ptrace_sc_ret psr;
4013c8ea8731SJohn Baldwin 	pid_t fpid, wpid;
4014c8ea8731SJohn Baldwin 	register_t args[2];
4015c8ea8731SJohn Baldwin 	int events, status;
4016c8ea8731SJohn Baldwin 
4017c8ea8731SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
4018c8ea8731SJohn Baldwin 	if (fpid == 0) {
4019c8ea8731SJohn Baldwin 		trace_me();
4020c8ea8731SJohn Baldwin 		kill(getpid(), 0);
402117cc2009SAlex Richardson 		/* Close a fd that should not exist. */
402217cc2009SAlex Richardson 		close(12345);
4023c8ea8731SJohn Baldwin 		exit(1);
4024c8ea8731SJohn Baldwin 	}
4025c8ea8731SJohn Baldwin 
4026c8ea8731SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
4027c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
402896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
4029c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
403096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
4031c8ea8731SJohn Baldwin 
4032c8ea8731SJohn Baldwin 	/*
4033c8ea8731SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
403432451fb9SJohn Baldwin 	 * syscall traps.
4035c8ea8731SJohn Baldwin 	 */
403696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
4037c8ea8731SJohn Baldwin 
4038c8ea8731SJohn Baldwin 	/*
4039c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from getpid().
4040c8ea8731SJohn Baldwin 	 */
4041c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
404296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
4043c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
404496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
4045c8ea8731SJohn Baldwin 
4046c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
4047c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
40481fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_getpid);
4049c8ea8731SJohn Baldwin 
405096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
4051c8ea8731SJohn Baldwin 
4052c8ea8731SJohn Baldwin 	/*
405332451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from getpid().
405432451fb9SJohn Baldwin 	 */
405532451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
405696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
405732451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
405896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
405932451fb9SJohn Baldwin 
406032451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
406132451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
40621fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_getpid);
406332451fb9SJohn Baldwin 
406432451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
406532451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
406696a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, 0);
406796a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_retval[0], wpid);
406832451fb9SJohn Baldwin 
406996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
407032451fb9SJohn Baldwin 
407132451fb9SJohn Baldwin 	/*
4072c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from kill().
4073c8ea8731SJohn Baldwin 	 */
4074c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
407596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
4076c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
407796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
4078c8ea8731SJohn Baldwin 
4079c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
4080c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
40811fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_kill);
40821fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_narg, 2u);
4083c8ea8731SJohn Baldwin 
4084c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
4085c8ea8731SJohn Baldwin 	    sizeof(args)) != -1);
408696a9e50eSAlex Richardson 	REQUIRE_EQ(args[0], wpid);
408796a9e50eSAlex Richardson 	REQUIRE_EQ(args[1], 0);
4088c8ea8731SJohn Baldwin 
408996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
409032451fb9SJohn Baldwin 
409132451fb9SJohn Baldwin 	/*
409232451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from kill().
409332451fb9SJohn Baldwin 	 */
409432451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
409596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
409632451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
409796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
409832451fb9SJohn Baldwin 
409932451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
410032451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
41011fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_kill);
410232451fb9SJohn Baldwin 
410332451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
410432451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
410596a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, 0);
410632451fb9SJohn Baldwin 
410796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
410832451fb9SJohn Baldwin 
410932451fb9SJohn Baldwin 	/*
411032451fb9SJohn Baldwin 	 * The next stop should be the syscall entry from close().
411132451fb9SJohn Baldwin 	 */
411232451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
411396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
411432451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
411596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
411632451fb9SJohn Baldwin 
411732451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
411832451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
41191fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_close);
41201fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_narg, 1u);
412132451fb9SJohn Baldwin 
412232451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
412332451fb9SJohn Baldwin 	    sizeof(args)) != -1);
412417cc2009SAlex Richardson 	REQUIRE_EQ(args[0], 12345);
412532451fb9SJohn Baldwin 
412696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
412732451fb9SJohn Baldwin 
412832451fb9SJohn Baldwin 	/*
412932451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from close().
413032451fb9SJohn Baldwin 	 */
413132451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
413296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
413332451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
413496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
413532451fb9SJohn Baldwin 
413632451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
413732451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
41381fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_close);
413932451fb9SJohn Baldwin 
414032451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
414132451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
414296a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, EBADF);
414332451fb9SJohn Baldwin 
4144c8ea8731SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
4145c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
4146c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
4147c8ea8731SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
4148c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
4149c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
415096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
4151c8ea8731SJohn Baldwin 
4152c8ea8731SJohn Baldwin 	/* The last event should be for the child process's exit. */
4153c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4154c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
415596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
4156c8ea8731SJohn Baldwin 
4157c8ea8731SJohn Baldwin 	wpid = wait(&status);
415896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
415996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4160c8ea8731SJohn Baldwin }
4161c8ea8731SJohn Baldwin 
4162fd631bcdSMariusz Zaborski /*
4163fd631bcdSMariusz Zaborski  * Verify that when the process is traced that it isn't reparent
4164fd631bcdSMariusz Zaborski  * to the init process when we close all process descriptors.
4165fd631bcdSMariusz Zaborski  */
4166fd631bcdSMariusz Zaborski ATF_TC(ptrace__proc_reparent);
4167fd631bcdSMariusz Zaborski ATF_TC_HEAD(ptrace__proc_reparent, tc)
4168fd631bcdSMariusz Zaborski {
4169fd631bcdSMariusz Zaborski 
4170fd631bcdSMariusz Zaborski 	atf_tc_set_md_var(tc, "timeout", "2");
4171fd631bcdSMariusz Zaborski }
4172fd631bcdSMariusz Zaborski ATF_TC_BODY(ptrace__proc_reparent, tc)
4173fd631bcdSMariusz Zaborski {
4174fd631bcdSMariusz Zaborski 	pid_t traced, debuger, wpid;
4175fd631bcdSMariusz Zaborski 	int pd, status;
4176fd631bcdSMariusz Zaborski 
4177fd631bcdSMariusz Zaborski 	traced = pdfork(&pd, 0);
4178fd631bcdSMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
4179fd631bcdSMariusz Zaborski 	if (traced == 0) {
4180fd631bcdSMariusz Zaborski 		raise(SIGSTOP);
4181fd631bcdSMariusz Zaborski 		exit(0);
4182fd631bcdSMariusz Zaborski 	}
4183fd631bcdSMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
4184fd631bcdSMariusz Zaborski 
4185fd631bcdSMariusz Zaborski 	debuger = fork();
4186fd631bcdSMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
4187fd631bcdSMariusz Zaborski 	if (debuger == 0) {
4188fd631bcdSMariusz Zaborski 		/* The traced process is reparented to debuger. */
418996a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_ATTACH, traced, 0, 0), 0);
4190fd631bcdSMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
419196a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
4192fd631bcdSMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
419396a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
419496a9e50eSAlex Richardson 		REQUIRE_EQ(close(pd), 0);
419596a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_DETACH, traced, (caddr_t)1, 0), 0);
4196fd631bcdSMariusz Zaborski 
4197fd631bcdSMariusz Zaborski 		/* We closed pd so we should not have any child. */
4198fd631bcdSMariusz Zaborski 		wpid = wait(&status);
419996a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, -1);
420096a9e50eSAlex Richardson 		REQUIRE_EQ(errno, ECHILD);
4201fd631bcdSMariusz Zaborski 
4202fd631bcdSMariusz Zaborski 		exit(0);
4203fd631bcdSMariusz Zaborski 	}
4204fd631bcdSMariusz Zaborski 
420596a9e50eSAlex Richardson 	REQUIRE_EQ(close(pd), 0);
4206fd631bcdSMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
420796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debuger);
420896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
4209fd631bcdSMariusz Zaborski 
4210fd631bcdSMariusz Zaborski 	/* Check if we still have any child. */
4211fd631bcdSMariusz Zaborski 	wpid = wait(&status);
421296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
421396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4214fd631bcdSMariusz Zaborski }
4215fd631bcdSMariusz Zaborski 
42168e493611SMariusz Zaborski /*
42178e493611SMariusz Zaborski  * Ensure that traced processes created with pdfork(2) are visible to
42188e493611SMariusz Zaborski  * waitid(P_ALL).
42198e493611SMariusz Zaborski  */
42208e493611SMariusz Zaborski ATF_TC_WITHOUT_HEAD(ptrace__procdesc_wait_child);
42218e493611SMariusz Zaborski ATF_TC_BODY(ptrace__procdesc_wait_child, tc)
42228e493611SMariusz Zaborski {
42238e493611SMariusz Zaborski 	pid_t child, wpid;
42248e493611SMariusz Zaborski 	int pd, status;
42258e493611SMariusz Zaborski 
42268e493611SMariusz Zaborski 	child = pdfork(&pd, 0);
42278e493611SMariusz Zaborski 	ATF_REQUIRE(child >= 0);
42288e493611SMariusz Zaborski 
42298e493611SMariusz Zaborski 	if (child == 0) {
42308e493611SMariusz Zaborski 		trace_me();
42318e493611SMariusz Zaborski 		(void)raise(SIGSTOP);
42328e493611SMariusz Zaborski 		exit(0);
42338e493611SMariusz Zaborski 	}
42348e493611SMariusz Zaborski 
42358e493611SMariusz Zaborski 	wpid = waitpid(child, &status, 0);
423696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
42378e493611SMariusz Zaborski 	ATF_REQUIRE(WIFSTOPPED(status));
423896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42398e493611SMariusz Zaborski 
42408e493611SMariusz Zaborski 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
42418e493611SMariusz Zaborski 
42428e493611SMariusz Zaborski 	wpid = wait(&status);
424396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
42448e493611SMariusz Zaborski 	ATF_REQUIRE(WIFSTOPPED(status));
424596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42468e493611SMariusz Zaborski 
42478e493611SMariusz Zaborski 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
42488e493611SMariusz Zaborski 
42498e493611SMariusz Zaborski 	/*
42508e493611SMariusz Zaborski 	 * If process was created by pdfork, the return code have to
42518e493611SMariusz Zaborski 	 * be collected through process descriptor.
42528e493611SMariusz Zaborski 	 */
42538e493611SMariusz Zaborski 	wpid = wait(&status);
425496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
425596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
42568e493611SMariusz Zaborski 
42578e493611SMariusz Zaborski 	ATF_REQUIRE(close(pd) != -1);
42588e493611SMariusz Zaborski }
42598e493611SMariusz Zaborski 
42608e493611SMariusz Zaborski /*
42618e493611SMariusz Zaborski  * Ensure that traced processes created with pdfork(2) are not visible
42628e493611SMariusz Zaborski  * after returning to parent - waitid(P_ALL).
42638e493611SMariusz Zaborski  */
42648e493611SMariusz Zaborski ATF_TC_WITHOUT_HEAD(ptrace__procdesc_reparent_wait_child);
42658e493611SMariusz Zaborski ATF_TC_BODY(ptrace__procdesc_reparent_wait_child, tc)
42668e493611SMariusz Zaborski {
42678e493611SMariusz Zaborski 	pid_t traced, debuger, wpid;
42688e493611SMariusz Zaborski 	int pd, status;
42698e493611SMariusz Zaborski 
42708e493611SMariusz Zaborski 	traced = pdfork(&pd, 0);
42718e493611SMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
42728e493611SMariusz Zaborski 	if (traced == 0) {
42738e493611SMariusz Zaborski 		raise(SIGSTOP);
42748e493611SMariusz Zaborski 		exit(0);
42758e493611SMariusz Zaborski 	}
42768e493611SMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
42778e493611SMariusz Zaborski 
427810321314SAlex Richardson 	/* Wait until the child process has stopped before fork()ing again. */
427910321314SAlex Richardson 	REQUIRE_EQ(traced, waitpid(traced, &status, WSTOPPED));
42808e493611SMariusz Zaborski 	debuger = fork();
42818e493611SMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
42828e493611SMariusz Zaborski 	if (debuger == 0) {
42838e493611SMariusz Zaborski 		/* The traced process is reparented to debuger. */
428496a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_ATTACH, traced, 0, 0), 0);
42858e493611SMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
428696a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
42878e493611SMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
428896a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42898e493611SMariusz Zaborski 
42908e493611SMariusz Zaborski 		/* Allow process to die. */
429196a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, traced, (caddr_t)1, 0), 0);
42928e493611SMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
429396a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
42948e493611SMariusz Zaborski 		ATF_REQUIRE(WIFEXITED(status));
429596a9e50eSAlex Richardson 		REQUIRE_EQ(WEXITSTATUS(status), 0);
42968e493611SMariusz Zaborski 
42978e493611SMariusz Zaborski 		/* Reparent back to the orginal process. */
429896a9e50eSAlex Richardson 		REQUIRE_EQ(close(pd), 0);
42998e493611SMariusz Zaborski 		exit(0);
43008e493611SMariusz Zaborski 	}
43018e493611SMariusz Zaborski 
43028e493611SMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
430396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debuger);
430496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
43058e493611SMariusz Zaborski 
43068e493611SMariusz Zaborski 	/*
43078e493611SMariusz Zaborski 	 * We have a child but it has a process descriptori
43088e493611SMariusz Zaborski 	 * so we should not be able to collect it process.
43098e493611SMariusz Zaborski 	 */
43108e493611SMariusz Zaborski 	wpid = wait(&status);
431196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
431296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
43138e493611SMariusz Zaborski 
431496a9e50eSAlex Richardson 	REQUIRE_EQ(close(pd), 0);
43158e493611SMariusz Zaborski }
43168e493611SMariusz Zaborski 
4317c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
4318c209e3e2SJohn Baldwin {
4319c209e3e2SJohn Baldwin 
4320c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
4321c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
432257c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
432357c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
4324128c9bc0SMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
432598685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
432698685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
432798685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
432898685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
432998685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
433098685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
433198685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
433298685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
4333368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
4334189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
4335189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
4336189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
43375fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
43385fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
43393340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
43408d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
43418d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
43428d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
4343fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
4344fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
4345403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
434682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
4347e2ebfbbfSEric Badger #endif
434882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
434982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
435082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
435182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
435282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
435382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
435482a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
435582a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
435682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
4357753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
435882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
435982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
436082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
436182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
4362753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
4363753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
436482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
4365*548a2ec4SAndrew Turner 	ATF_TP_ADD_TC(tp, ptrace__PT_REGSET);
4366b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
4367b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
4368b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
4369d74da94cSMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
437054cfb29eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
4371643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
4372643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo);
4373643ce7deSJohn Baldwin #endif
4374643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__step_siginfo);
4375403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
4376e012fe34SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
4377e012fe34SJohn Baldwin #endif
4378c5786670SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
4379c8ea8731SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__syscall_args);
4380fd631bcdSMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__proc_reparent);
43818e493611SMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__procdesc_wait_child);
43828e493611SMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__procdesc_reparent_wait_child);
4383c209e3e2SJohn Baldwin 
4384c209e3e2SJohn Baldwin 	return (atf_no_error());
4385c209e3e2SJohn Baldwin }
4386