xref: /freebsd/tests/sys/kern/ptrace_test.c (revision a9c91abd3bd42d90a40bf89ba8682746700455ac)
1c209e3e2SJohn Baldwin /*-
2c209e3e2SJohn Baldwin  * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
3c209e3e2SJohn Baldwin  * All rights reserved.
4c209e3e2SJohn Baldwin  *
5c209e3e2SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
6c209e3e2SJohn Baldwin  * modification, are permitted provided that the following conditions
7c209e3e2SJohn Baldwin  * are met:
8c209e3e2SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
9c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
10c209e3e2SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
11c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
12c209e3e2SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
13c209e3e2SJohn Baldwin  *
14c209e3e2SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15c209e3e2SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16c209e3e2SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c209e3e2SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18c209e3e2SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c209e3e2SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c209e3e2SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c209e3e2SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c209e3e2SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c209e3e2SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24c209e3e2SJohn Baldwin  * SUCH DAMAGE.
25c209e3e2SJohn Baldwin  */
26c209e3e2SJohn Baldwin 
27c209e3e2SJohn Baldwin #include <sys/cdefs.h>
28c209e3e2SJohn Baldwin __FBSDID("$FreeBSD$");
29c209e3e2SJohn Baldwin 
30c209e3e2SJohn Baldwin #include <sys/types.h>
3182a4538fSEric Badger #include <sys/cpuset.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>
36c209e3e2SJohn Baldwin #include <sys/ptrace.h>
37bc2be1d3SEric Badger #include <sys/queue.h>
38bc2be1d3SEric Badger #include <sys/runq.h>
39189ac973SJohn Baldwin #include <sys/syscall.h>
4057c74f5bSJohn Baldwin #include <sys/sysctl.h>
4157c74f5bSJohn Baldwin #include <sys/user.h>
42c209e3e2SJohn Baldwin #include <sys/wait.h>
43c209e3e2SJohn Baldwin #include <errno.h>
449e0d1159SEric Badger #include <machine/cpufunc.h>
45189ac973SJohn Baldwin #include <pthread.h>
46bc2be1d3SEric Badger #include <sched.h>
4782a4538fSEric Badger #include <semaphore.h>
48c209e3e2SJohn Baldwin #include <signal.h>
49dfa8ba12SJohn Baldwin #include <stdio.h>
50c209e3e2SJohn Baldwin #include <stdlib.h>
51c209e3e2SJohn Baldwin #include <unistd.h>
52c209e3e2SJohn Baldwin #include <atf-c.h>
53c209e3e2SJohn Baldwin 
54c209e3e2SJohn Baldwin /*
55403e331dSJohn Baldwin  * Architectures with a user-visible breakpoint().
56403e331dSJohn Baldwin  */
57*a9c91abdSJohn Baldwin #if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) ||	\
58*a9c91abdSJohn Baldwin     defined(__i386__) || defined(__mips__) || defined(__riscv) ||	\
59*a9c91abdSJohn Baldwin     defined(__sparc64__)
60403e331dSJohn Baldwin #define	HAVE_BREAKPOINT
61403e331dSJohn Baldwin #endif
62403e331dSJohn Baldwin 
63403e331dSJohn Baldwin /*
64403e331dSJohn Baldwin  * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap.
65403e331dSJohn Baldwin  */
66403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
67*a9c91abdSJohn Baldwin #if defined(__aarch64__)
68*a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->elr += 4)
69*a9c91abdSJohn Baldwin #elif defined(__amd64__) || defined(__i386__)
70403e331dSJohn Baldwin #define	SKIP_BREAK(reg)
71*a9c91abdSJohn Baldwin #elif defined(__arm__)
72*a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_pc += 4)
73bd061c39SJohn Baldwin #elif defined(__mips__)
74bd061c39SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_regs[PC] += 4)
75ca75fa17SJohn Baldwin #elif defined(__riscv)
76ca75fa17SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->sepc += 4)
77403e331dSJohn Baldwin #elif defined(__sparc64__)
78403e331dSJohn Baldwin #define	SKIP_BREAK(reg)	do {						\
79403e331dSJohn Baldwin 	(reg)->r_tpc = (reg)->r_tnpc + 4;				\
80403e331dSJohn Baldwin 	(reg)->r_tnpc += 8;						\
81403e331dSJohn Baldwin } while (0)
82403e331dSJohn Baldwin #endif
83403e331dSJohn Baldwin #endif
84403e331dSJohn Baldwin 
85403e331dSJohn Baldwin /*
86dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
87dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
88dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
89dfa8ba12SJohn Baldwin  */
90dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {						\
91dfa8ba12SJohn Baldwin 		if (!(exp))						\
92dfa8ba12SJohn Baldwin 			child_fail_require(__FILE__, __LINE__,		\
93dfa8ba12SJohn Baldwin 			    #exp " not met");				\
94dfa8ba12SJohn Baldwin 	} while (0)
95dfa8ba12SJohn Baldwin 
9698685dc8SJohn Baldwin static __dead2 void
97dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str)
98dfa8ba12SJohn Baldwin {
99dfa8ba12SJohn Baldwin 	char buf[128];
100dfa8ba12SJohn Baldwin 
101dfa8ba12SJohn Baldwin 	snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str);
102dfa8ba12SJohn Baldwin 	write(2, buf, strlen(buf));
103dfa8ba12SJohn Baldwin 	_exit(32);
104dfa8ba12SJohn Baldwin }
105dfa8ba12SJohn Baldwin 
10698685dc8SJohn Baldwin static void
10798685dc8SJohn Baldwin trace_me(void)
10898685dc8SJohn Baldwin {
10998685dc8SJohn Baldwin 
11098685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
11198685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11298685dc8SJohn Baldwin 
11398685dc8SJohn Baldwin 	/* Trigger a stop. */
11498685dc8SJohn Baldwin 	raise(SIGSTOP);
11598685dc8SJohn Baldwin }
11698685dc8SJohn Baldwin 
11798685dc8SJohn Baldwin static void
11898685dc8SJohn Baldwin attach_child(pid_t pid)
11998685dc8SJohn Baldwin {
12098685dc8SJohn Baldwin 	pid_t wpid;
12198685dc8SJohn Baldwin 	int status;
12298685dc8SJohn Baldwin 
12398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
12498685dc8SJohn Baldwin 
12598685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
12698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == pid);
12798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12898685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
12998685dc8SJohn Baldwin }
13098685dc8SJohn Baldwin 
13198685dc8SJohn Baldwin static void
13298685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
13398685dc8SJohn Baldwin {
13498685dc8SJohn Baldwin 
13598685dc8SJohn Baldwin 	/*
13698685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
13798685dc8SJohn Baldwin 	 * there is not a better way.
1383a014c56SJohn Baldwin 	 *
1393a014c56SJohn Baldwin 	 * Prior to r325719, the kern.proc.pid.<pid> sysctl failed
1403a014c56SJohn Baldwin 	 * with ESRCH.  After that change, a valid struct kinfo_proc
1413a014c56SJohn Baldwin 	 * is returned for zombies with ki_stat set to SZOMB.
14298685dc8SJohn Baldwin 	 */
14398685dc8SJohn Baldwin 	for (;;) {
14498685dc8SJohn Baldwin 		struct kinfo_proc kp;
14598685dc8SJohn Baldwin 		size_t len;
14698685dc8SJohn Baldwin 		int mib[4];
14798685dc8SJohn Baldwin 
14898685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
14998685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
15098685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
15198685dc8SJohn Baldwin 		mib[3] = pid;
15298685dc8SJohn Baldwin 		len = sizeof(kp);
15398685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
15498685dc8SJohn Baldwin 			ATF_REQUIRE(errno == ESRCH);
15598685dc8SJohn Baldwin 			break;
15698685dc8SJohn Baldwin 		}
1573a014c56SJohn Baldwin 		if (kp.ki_stat == SZOMB)
1583a014c56SJohn Baldwin 			break;
15998685dc8SJohn Baldwin 		usleep(5000);
16098685dc8SJohn Baldwin 	}
16198685dc8SJohn Baldwin }
16298685dc8SJohn Baldwin 
163dfa8ba12SJohn Baldwin /*
164c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
165c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
166c209e3e2SJohn Baldwin  */
167c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
168c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
169c209e3e2SJohn Baldwin {
170c209e3e2SJohn Baldwin 	pid_t child, wpid;
171c209e3e2SJohn Baldwin 	int status;
172c209e3e2SJohn Baldwin 
173c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
174c209e3e2SJohn Baldwin 	if (child == 0) {
175c209e3e2SJohn Baldwin 		/* Child process. */
17698685dc8SJohn Baldwin 		trace_me();
177c209e3e2SJohn Baldwin 
178b98cb919SJohn Baldwin 		_exit(1);
179c209e3e2SJohn Baldwin 	}
180c209e3e2SJohn Baldwin 
181c209e3e2SJohn Baldwin 	/* Parent process. */
182c209e3e2SJohn Baldwin 
183c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
184c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
185c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
186c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
187c209e3e2SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
188c209e3e2SJohn Baldwin 
189c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
190c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
191c209e3e2SJohn Baldwin 
192c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
193c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
194c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
195c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
196c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
197c209e3e2SJohn Baldwin 
198c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
199c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
200c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
201c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
202c209e3e2SJohn Baldwin }
203c209e3e2SJohn Baldwin 
204c209e3e2SJohn Baldwin /*
205c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
206c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
207c209e3e2SJohn Baldwin  */
208c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
209c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
210c209e3e2SJohn Baldwin {
211c209e3e2SJohn Baldwin 	pid_t child, wpid;
212c209e3e2SJohn Baldwin 	int cpipe[2], status;
213c209e3e2SJohn Baldwin 	char c;
214c209e3e2SJohn Baldwin 
215c209e3e2SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
216c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
217c209e3e2SJohn Baldwin 	if (child == 0) {
218c209e3e2SJohn Baldwin 		/* Child process. */
219c209e3e2SJohn Baldwin 		close(cpipe[0]);
220c209e3e2SJohn Baldwin 
221c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
222dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0);
223c209e3e2SJohn Baldwin 
224b98cb919SJohn Baldwin 		_exit(1);
225c209e3e2SJohn Baldwin 	}
226c209e3e2SJohn Baldwin 	close(cpipe[1]);
227c209e3e2SJohn Baldwin 
228c209e3e2SJohn Baldwin 	/* Parent process. */
229c209e3e2SJohn Baldwin 
230c209e3e2SJohn Baldwin 	/* Attach to the child process. */
23198685dc8SJohn Baldwin 	attach_child(child);
232c209e3e2SJohn Baldwin 
233c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
234c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
235c209e3e2SJohn Baldwin 
236c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
237c209e3e2SJohn Baldwin 	close(cpipe[0]);
238c209e3e2SJohn Baldwin 
239c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
240c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
241c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
242c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
243c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
244c209e3e2SJohn Baldwin 
245c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
246c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
247c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
248c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
249c209e3e2SJohn Baldwin }
250c209e3e2SJohn Baldwin 
25157c74f5bSJohn Baldwin /*
25257c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
25357c74f5bSJohn Baldwin  * after the debugger has seen it.
25457c74f5bSJohn Baldwin  */
25557c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
25657c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
25757c74f5bSJohn Baldwin {
25857c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
25957c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
26057c74f5bSJohn Baldwin 	char c;
26157c74f5bSJohn Baldwin 
26257c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
26357c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
26457c74f5bSJohn Baldwin 
26557c74f5bSJohn Baldwin 	if (child == 0) {
26657c74f5bSJohn Baldwin 		/* Child process. */
26757c74f5bSJohn Baldwin 		close(cpipe[0]);
26857c74f5bSJohn Baldwin 
26957c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
270dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
27157c74f5bSJohn Baldwin 
272b98cb919SJohn Baldwin 		_exit(1);
27357c74f5bSJohn Baldwin 	}
27457c74f5bSJohn Baldwin 	close(cpipe[1]);
27557c74f5bSJohn Baldwin 
27657c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
27757c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
27857c74f5bSJohn Baldwin 
27957c74f5bSJohn Baldwin 	if (debugger == 0) {
28057c74f5bSJohn Baldwin 		/* Debugger process. */
28157c74f5bSJohn Baldwin 		close(dpipe[0]);
28257c74f5bSJohn Baldwin 
283dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
28457c74f5bSJohn Baldwin 
28557c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
286dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
287dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
288dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
28957c74f5bSJohn Baldwin 
290dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
29157c74f5bSJohn Baldwin 
29257c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
293dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
29457c74f5bSJohn Baldwin 
29557c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
296dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0);
29757c74f5bSJohn Baldwin 
29857c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
299dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
300dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
301dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
30257c74f5bSJohn Baldwin 
303b98cb919SJohn Baldwin 		_exit(0);
30457c74f5bSJohn Baldwin 	}
30557c74f5bSJohn Baldwin 	close(dpipe[1]);
30657c74f5bSJohn Baldwin 
30757c74f5bSJohn Baldwin 	/* Parent process. */
30857c74f5bSJohn Baldwin 
30957c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
31057c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
31157c74f5bSJohn Baldwin 
31257c74f5bSJohn Baldwin 	/* Release the child. */
31357c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
31457c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
31557c74f5bSJohn Baldwin 	close(cpipe[0]);
31657c74f5bSJohn Baldwin 
31798685dc8SJohn Baldwin 	wait_for_zombie(child);
31857c74f5bSJohn Baldwin 
31957c74f5bSJohn Baldwin 	/*
3202f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3212f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3222f021998SJohn Baldwin 	 * until the debugger sees the exit.
32357c74f5bSJohn Baldwin 	 */
32457c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
32557c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
32657c74f5bSJohn Baldwin 
32757c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
32857c74f5bSJohn Baldwin 	close(dpipe[0]);
32957c74f5bSJohn Baldwin 
33057c74f5bSJohn Baldwin 	/* Wait for the debugger. */
33157c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
33257c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
33357c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
33457c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
33557c74f5bSJohn Baldwin 
33657c74f5bSJohn Baldwin 	/* The child process should now be ready. */
33757c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
33857c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
33957c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
34057c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
34157c74f5bSJohn Baldwin }
34257c74f5bSJohn Baldwin 
34357c74f5bSJohn Baldwin /*
34457c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
34557c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
34657c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
34757c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
34857c74f5bSJohn Baldwin  */
34957c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
35057c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
35157c74f5bSJohn Baldwin {
35257c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
35357c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
35457c74f5bSJohn Baldwin 	char c;
35557c74f5bSJohn Baldwin 
35657c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
35757c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
35857c74f5bSJohn Baldwin 
35957c74f5bSJohn Baldwin 	if (child == 0) {
36057c74f5bSJohn Baldwin 		/* Child process. */
36157c74f5bSJohn Baldwin 		close(cpipe[0]);
36257c74f5bSJohn Baldwin 
36357c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
364dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
36557c74f5bSJohn Baldwin 
366b98cb919SJohn Baldwin 		_exit(1);
36757c74f5bSJohn Baldwin 	}
36857c74f5bSJohn Baldwin 	close(cpipe[1]);
36957c74f5bSJohn Baldwin 
37057c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
37157c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
37257c74f5bSJohn Baldwin 
37357c74f5bSJohn Baldwin 	if (debugger == 0) {
37457c74f5bSJohn Baldwin 		/* Debugger parent. */
37557c74f5bSJohn Baldwin 
37657c74f5bSJohn Baldwin 		/*
37757c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
37857c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
37957c74f5bSJohn Baldwin 		 */
380dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
38157c74f5bSJohn Baldwin 		if (fpid != 0)
382b98cb919SJohn Baldwin 			_exit(2);
38357c74f5bSJohn Baldwin 
38457c74f5bSJohn Baldwin 		/* Debugger process. */
38557c74f5bSJohn Baldwin 		close(dpipe[0]);
38657c74f5bSJohn Baldwin 
387dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
38857c74f5bSJohn Baldwin 
38957c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
390dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
391dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
392dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
39357c74f5bSJohn Baldwin 
394dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
39557c74f5bSJohn Baldwin 
39657c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
397dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
39857c74f5bSJohn Baldwin 
39957c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
400dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c));
40157c74f5bSJohn Baldwin 
40257c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
403dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
404dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
405dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
40657c74f5bSJohn Baldwin 
407b98cb919SJohn Baldwin 		_exit(0);
40857c74f5bSJohn Baldwin 	}
409eddb85c6SJohn Baldwin 	close(dpipe[1]);
41057c74f5bSJohn Baldwin 
41157c74f5bSJohn Baldwin 	/* Parent process. */
41257c74f5bSJohn Baldwin 
41357c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
41457c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
41557c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
41657c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
41757c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
41857c74f5bSJohn Baldwin 
41957c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
42057c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
42157c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
42257c74f5bSJohn Baldwin 
42357c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
42457c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
42557c74f5bSJohn Baldwin 
42657c74f5bSJohn Baldwin 	/* Release the child. */
42757c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
42857c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
42957c74f5bSJohn Baldwin 	close(cpipe[0]);
43057c74f5bSJohn Baldwin 
43198685dc8SJohn Baldwin 	wait_for_zombie(child);
43257c74f5bSJohn Baldwin 
43357c74f5bSJohn Baldwin 	/*
4342f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
4352f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
4362f021998SJohn Baldwin 	 * until the debugger sees the exit.
43757c74f5bSJohn Baldwin 	 */
43857c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
43957c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
44057c74f5bSJohn Baldwin 
44157c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
442eddb85c6SJohn Baldwin 	ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c));
44357c74f5bSJohn Baldwin 
44457c74f5bSJohn Baldwin 	/* Wait for the debugger. */
445eddb85c6SJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0);
446eddb85c6SJohn Baldwin 	close(dpipe[0]);
44757c74f5bSJohn Baldwin 
44857c74f5bSJohn Baldwin 	/* The child process should now be ready. */
44957c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
45057c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
45157c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
45257c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
45357c74f5bSJohn Baldwin }
45457c74f5bSJohn Baldwin 
45598685dc8SJohn Baldwin /*
45698685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
45798685dc8SJohn Baldwin  * debugger is attached to it.
45898685dc8SJohn Baldwin  */
45998685dc8SJohn Baldwin static __dead2 void
460189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
46198685dc8SJohn Baldwin {
46298685dc8SJohn Baldwin 	pid_t fpid, wpid;
46398685dc8SJohn Baldwin 	int status;
46498685dc8SJohn Baldwin 
465189ac973SJohn Baldwin 	if (use_vfork)
466189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
467189ac973SJohn Baldwin 	else
46898685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
46998685dc8SJohn Baldwin 
47098685dc8SJohn Baldwin 	if (fpid == 0)
47198685dc8SJohn Baldwin 		/* Child */
472b98cb919SJohn Baldwin 		_exit(2);
47398685dc8SJohn Baldwin 
47498685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
47598685dc8SJohn Baldwin 	CHILD_REQUIRE(wpid == fpid);
47698685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
47798685dc8SJohn Baldwin 	CHILD_REQUIRE(WEXITSTATUS(status) == 2);
47898685dc8SJohn Baldwin 
479b98cb919SJohn Baldwin 	_exit(1);
48098685dc8SJohn Baldwin }
48198685dc8SJohn Baldwin 
48298685dc8SJohn Baldwin /*
48398685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
48498685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
48598685dc8SJohn Baldwin  * child process.
48698685dc8SJohn Baldwin  */
48798685dc8SJohn Baldwin static pid_t
488189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
48998685dc8SJohn Baldwin {
49098685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
49198685dc8SJohn Baldwin 	bool fork_reported[2];
49298685dc8SJohn Baldwin 	pid_t child, wpid;
49398685dc8SJohn Baldwin 	int i, status;
49498685dc8SJohn Baldwin 
49598685dc8SJohn Baldwin 	fork_reported[0] = false;
49698685dc8SJohn Baldwin 	fork_reported[1] = false;
49798685dc8SJohn Baldwin 	child = -1;
49898685dc8SJohn Baldwin 
49998685dc8SJohn Baldwin 	/*
50098685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
50198685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
50298685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
50398685dc8SJohn Baldwin 	 */
50498685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
50598685dc8SJohn Baldwin 		wpid = wait(&status);
50698685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
50798685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
50898685dc8SJohn Baldwin 
50998685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
51098685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
51198685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
51298685dc8SJohn Baldwin 		    0);
51398685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
51498685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
51598685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
51698685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
51798685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
51898685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
51998685dc8SJohn Baldwin 			if (child == -1)
52098685dc8SJohn Baldwin 				child = wpid;
52198685dc8SJohn Baldwin 			else
52298685dc8SJohn Baldwin 				ATF_REQUIRE(child == wpid);
523189ac973SJohn Baldwin 			if (ppl != NULL)
524189ac973SJohn Baldwin 				ppl[1] = pl;
52598685dc8SJohn Baldwin 			fork_reported[1] = true;
52698685dc8SJohn Baldwin 		} else {
52798685dc8SJohn Baldwin 			ATF_REQUIRE(wpid == parent);
52898685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
52998685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
53098685dc8SJohn Baldwin 			if (child == -1)
53198685dc8SJohn Baldwin 				child = pl.pl_child_pid;
53298685dc8SJohn Baldwin 			else
53398685dc8SJohn Baldwin 				ATF_REQUIRE(child == pl.pl_child_pid);
534189ac973SJohn Baldwin 			if (ppl != NULL)
535189ac973SJohn Baldwin 				ppl[0] = pl;
53698685dc8SJohn Baldwin 			fork_reported[0] = true;
53798685dc8SJohn Baldwin 		}
53898685dc8SJohn Baldwin 	}
53998685dc8SJohn Baldwin 
54098685dc8SJohn Baldwin 	return (child);
54198685dc8SJohn Baldwin }
54298685dc8SJohn Baldwin 
54398685dc8SJohn Baldwin /*
54498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
54598685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
54698685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
54798685dc8SJohn Baldwin  */
54898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
54998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
55098685dc8SJohn Baldwin {
551479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
55298685dc8SJohn Baldwin 	int status;
55398685dc8SJohn Baldwin 
55498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
55598685dc8SJohn Baldwin 	if (fpid == 0) {
55698685dc8SJohn Baldwin 		trace_me();
557189ac973SJohn Baldwin 		follow_fork_parent(false);
55898685dc8SJohn Baldwin 	}
55998685dc8SJohn Baldwin 
56098685dc8SJohn Baldwin 	/* Parent process. */
56198685dc8SJohn Baldwin 	children[0] = fpid;
56298685dc8SJohn Baldwin 
56398685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
56498685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
56598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
56698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
56798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
56898685dc8SJohn Baldwin 
56998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
57098685dc8SJohn Baldwin 
57198685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
57298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
57398685dc8SJohn Baldwin 
574189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
57598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
57698685dc8SJohn Baldwin 
57798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
57898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
57998685dc8SJohn Baldwin 
58098685dc8SJohn Baldwin 	/*
58198685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
58298685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
58398685dc8SJohn Baldwin 	 */
58498685dc8SJohn Baldwin 	wpid = wait(&status);
58598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
58698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
58798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
58898685dc8SJohn Baldwin 
58998685dc8SJohn Baldwin 	wpid = wait(&status);
59098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
59198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
59298685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
59398685dc8SJohn Baldwin 
59498685dc8SJohn Baldwin 	wpid = wait(&status);
59598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
59698685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
59798685dc8SJohn Baldwin }
59898685dc8SJohn Baldwin 
59998685dc8SJohn Baldwin /*
60098685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
60198685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
60298685dc8SJohn Baldwin  * child process is detached after it reports its fork.
60398685dc8SJohn Baldwin  */
60498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
60598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
60698685dc8SJohn Baldwin {
607479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
60898685dc8SJohn Baldwin 	int status;
60998685dc8SJohn Baldwin 
61098685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
61198685dc8SJohn Baldwin 	if (fpid == 0) {
61298685dc8SJohn Baldwin 		trace_me();
613189ac973SJohn Baldwin 		follow_fork_parent(false);
61498685dc8SJohn Baldwin 	}
61598685dc8SJohn Baldwin 
61698685dc8SJohn Baldwin 	/* Parent process. */
61798685dc8SJohn Baldwin 	children[0] = fpid;
61898685dc8SJohn Baldwin 
61998685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
62098685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
62198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
62298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
62398685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
62498685dc8SJohn Baldwin 
62598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
62698685dc8SJohn Baldwin 
62798685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
62898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
62998685dc8SJohn Baldwin 
630189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
63198685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
63298685dc8SJohn Baldwin 
63398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
63498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
63598685dc8SJohn Baldwin 
63698685dc8SJohn Baldwin 	/*
63798685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
63898685dc8SJohn Baldwin 	 * child.
63998685dc8SJohn Baldwin 	 */
64098685dc8SJohn Baldwin 	wpid = wait(&status);
64198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
64298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
64398685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
64498685dc8SJohn Baldwin 
64598685dc8SJohn Baldwin 	wpid = wait(&status);
64698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
64798685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
64898685dc8SJohn Baldwin }
64998685dc8SJohn Baldwin 
65098685dc8SJohn Baldwin /*
65198685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
65298685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
65398685dc8SJohn Baldwin  * traced parent is detached after the fork.
65498685dc8SJohn Baldwin  */
65598685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
65698685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
65798685dc8SJohn Baldwin {
658479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
65998685dc8SJohn Baldwin 	int status;
66098685dc8SJohn Baldwin 
66198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
66298685dc8SJohn Baldwin 	if (fpid == 0) {
66398685dc8SJohn Baldwin 		trace_me();
664189ac973SJohn Baldwin 		follow_fork_parent(false);
66598685dc8SJohn Baldwin 	}
66698685dc8SJohn Baldwin 
66798685dc8SJohn Baldwin 	/* Parent process. */
66898685dc8SJohn Baldwin 	children[0] = fpid;
66998685dc8SJohn Baldwin 
67098685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
67198685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
67298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
67398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
67498685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
67598685dc8SJohn Baldwin 
67698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
67798685dc8SJohn Baldwin 
67898685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
67998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
68098685dc8SJohn Baldwin 
681189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
68298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
68398685dc8SJohn Baldwin 
68498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
68598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
68698685dc8SJohn Baldwin 
68798685dc8SJohn Baldwin 	/*
68898685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
68998685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
69098685dc8SJohn Baldwin 	 *
69198685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
69298685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
69398685dc8SJohn Baldwin 	 * after the grandchild.
69498685dc8SJohn Baldwin 	 */
69598685dc8SJohn Baldwin 	wpid = wait(&status);
69698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
69798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
69898685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
69998685dc8SJohn Baldwin 
70098685dc8SJohn Baldwin 	wpid = wait(&status);
70198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
70298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
70398685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
70498685dc8SJohn Baldwin 
70598685dc8SJohn Baldwin 	wpid = wait(&status);
70698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
70798685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
70898685dc8SJohn Baldwin }
70998685dc8SJohn Baldwin 
71098685dc8SJohn Baldwin static void
71198685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
71298685dc8SJohn Baldwin {
71398685dc8SJohn Baldwin 	pid_t fpid;
71498685dc8SJohn Baldwin 
71598685dc8SJohn Baldwin 	close(cpipe[0]);
71698685dc8SJohn Baldwin 
71798685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
71898685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
71998685dc8SJohn Baldwin 	if (fpid != 0)
720b98cb919SJohn Baldwin 		_exit(3);
72198685dc8SJohn Baldwin 
72298685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
72398685dc8SJohn Baldwin 	fpid = getpid();
72498685dc8SJohn Baldwin 	CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
72598685dc8SJohn Baldwin 
72698685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
72798685dc8SJohn Baldwin 	CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
72898685dc8SJohn Baldwin }
72998685dc8SJohn Baldwin 
73098685dc8SJohn Baldwin /*
73198685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
73298685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
73398685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
73498685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
73598685dc8SJohn Baldwin  */
73698685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
73798685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
73898685dc8SJohn Baldwin {
739479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
74098685dc8SJohn Baldwin 	int cpipe[2], status;
74198685dc8SJohn Baldwin 
74298685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
74398685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
74498685dc8SJohn Baldwin 	if (fpid == 0) {
74598685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
746189ac973SJohn Baldwin 		follow_fork_parent(false);
74798685dc8SJohn Baldwin 	}
74898685dc8SJohn Baldwin 
74998685dc8SJohn Baldwin 	/* Parent process. */
75098685dc8SJohn Baldwin 	close(cpipe[1]);
75198685dc8SJohn Baldwin 
75298685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
75398685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
75498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
75598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
75698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
75798685dc8SJohn Baldwin 
75898685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
75998685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
76098685dc8SJohn Baldwin 	    sizeof(children[0]));
76198685dc8SJohn Baldwin 
76298685dc8SJohn Baldwin 	/* Attach to the fork parent. */
76398685dc8SJohn Baldwin 	attach_child(children[0]);
76498685dc8SJohn Baldwin 
76598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
76698685dc8SJohn Baldwin 
76798685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
76898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
76998685dc8SJohn Baldwin 
77098685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
77198685dc8SJohn Baldwin 	close(cpipe[0]);
77298685dc8SJohn Baldwin 
773189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
77498685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
77598685dc8SJohn Baldwin 
77698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
77798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
77898685dc8SJohn Baldwin 
77998685dc8SJohn Baldwin 	/*
78098685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
78198685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
78298685dc8SJohn Baldwin 	 */
78398685dc8SJohn Baldwin 	wpid = wait(&status);
78498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
78598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
78698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
78798685dc8SJohn Baldwin 
78898685dc8SJohn Baldwin 	wpid = wait(&status);
78998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
79098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
79198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
79298685dc8SJohn Baldwin 
79398685dc8SJohn Baldwin 	wpid = wait(&status);
79498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
79598685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
79698685dc8SJohn Baldwin }
79798685dc8SJohn Baldwin 
79898685dc8SJohn Baldwin /*
79998685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
80098685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
80198685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
80298685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
80398685dc8SJohn Baldwin  */
80498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
80598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
80698685dc8SJohn Baldwin {
807479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
80898685dc8SJohn Baldwin 	int cpipe[2], status;
80998685dc8SJohn Baldwin 
81098685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
81198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
81298685dc8SJohn Baldwin 	if (fpid == 0) {
81398685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
814189ac973SJohn Baldwin 		follow_fork_parent(false);
81598685dc8SJohn Baldwin 	}
81698685dc8SJohn Baldwin 
81798685dc8SJohn Baldwin 	/* Parent process. */
81898685dc8SJohn Baldwin 	close(cpipe[1]);
81998685dc8SJohn Baldwin 
82098685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
82198685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
82298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
82398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
82498685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
82598685dc8SJohn Baldwin 
82698685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
82798685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
82898685dc8SJohn Baldwin 	    sizeof(children[0]));
82998685dc8SJohn Baldwin 
83098685dc8SJohn Baldwin 	/* Attach to the fork parent. */
83198685dc8SJohn Baldwin 	attach_child(children[0]);
83298685dc8SJohn Baldwin 
83398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
83498685dc8SJohn Baldwin 
83598685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
83698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
83798685dc8SJohn Baldwin 
83898685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
83998685dc8SJohn Baldwin 	close(cpipe[0]);
84098685dc8SJohn Baldwin 
841189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
84298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
84398685dc8SJohn Baldwin 
84498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
84598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
84698685dc8SJohn Baldwin 
84798685dc8SJohn Baldwin 	/*
84898685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
84998685dc8SJohn Baldwin 	 * parent.
85098685dc8SJohn Baldwin 	 */
85198685dc8SJohn Baldwin 	wpid = wait(&status);
85298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
85398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
85498685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
85598685dc8SJohn Baldwin 
85698685dc8SJohn Baldwin 	wpid = wait(&status);
85798685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
85898685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
85998685dc8SJohn Baldwin }
86098685dc8SJohn Baldwin 
86198685dc8SJohn Baldwin /*
86298685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
86398685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
86498685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
86598685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
86698685dc8SJohn Baldwin  */
86798685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
86898685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
86998685dc8SJohn Baldwin {
870479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
87198685dc8SJohn Baldwin 	int cpipe[2], status;
87298685dc8SJohn Baldwin 
87398685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
87498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
87598685dc8SJohn Baldwin 	if (fpid == 0) {
87698685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
877189ac973SJohn Baldwin 		follow_fork_parent(false);
87898685dc8SJohn Baldwin 	}
87998685dc8SJohn Baldwin 
88098685dc8SJohn Baldwin 	/* Parent process. */
88198685dc8SJohn Baldwin 	close(cpipe[1]);
88298685dc8SJohn Baldwin 
88398685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
88498685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
88598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
88698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
88798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
88898685dc8SJohn Baldwin 
88998685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
89098685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
89198685dc8SJohn Baldwin 	    sizeof(children[0]));
89298685dc8SJohn Baldwin 
89398685dc8SJohn Baldwin 	/* Attach to the fork parent. */
89498685dc8SJohn Baldwin 	attach_child(children[0]);
89598685dc8SJohn Baldwin 
89698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
89798685dc8SJohn Baldwin 
89898685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
89998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
90098685dc8SJohn Baldwin 
90198685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
90298685dc8SJohn Baldwin 	close(cpipe[0]);
90398685dc8SJohn Baldwin 
904189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
90598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
90698685dc8SJohn Baldwin 
90798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
90898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
90998685dc8SJohn Baldwin 
91098685dc8SJohn Baldwin 	/*
91198685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
91298685dc8SJohn Baldwin 	 * the child.
91398685dc8SJohn Baldwin 	 */
91498685dc8SJohn Baldwin 	wpid = wait(&status);
91598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
91698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
91798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
91898685dc8SJohn Baldwin 
91998685dc8SJohn Baldwin 	wpid = wait(&status);
92098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
92198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
92298685dc8SJohn Baldwin }
92398685dc8SJohn Baldwin 
924368b2b1cSJohn Baldwin /*
925368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
926368b2b1cSJohn Baldwin  * parent but sees its original parent process.
927368b2b1cSJohn Baldwin  */
928368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
929368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
930368b2b1cSJohn Baldwin {
931368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
932368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
933368b2b1cSJohn Baldwin 	char c;
934368b2b1cSJohn Baldwin 
935368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
936368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
937368b2b1cSJohn Baldwin 
938368b2b1cSJohn Baldwin 	if (child == 0) {
939368b2b1cSJohn Baldwin 		/* Child process. */
940368b2b1cSJohn Baldwin 		close(cpipe[0]);
941368b2b1cSJohn Baldwin 
942368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
943368b2b1cSJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
944368b2b1cSJohn Baldwin 
945368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
946368b2b1cSJohn Baldwin 		ppid = getppid();
947368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) ==
948368b2b1cSJohn Baldwin 		    sizeof(ppid));
949368b2b1cSJohn Baldwin 
950368b2b1cSJohn Baldwin 		_exit(1);
951368b2b1cSJohn Baldwin 	}
952368b2b1cSJohn Baldwin 	close(cpipe[1]);
953368b2b1cSJohn Baldwin 
954368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
955368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
956368b2b1cSJohn Baldwin 
957368b2b1cSJohn Baldwin 	if (debugger == 0) {
958368b2b1cSJohn Baldwin 		/* Debugger process. */
959368b2b1cSJohn Baldwin 		close(dpipe[0]);
960368b2b1cSJohn Baldwin 
961368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
962368b2b1cSJohn Baldwin 
963368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
964368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
965368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
966368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
967368b2b1cSJohn Baldwin 
968368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
969368b2b1cSJohn Baldwin 
970368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
971368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
972368b2b1cSJohn Baldwin 
973368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
974368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
975368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
976368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
977368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
978368b2b1cSJohn Baldwin 
979368b2b1cSJohn Baldwin 		_exit(0);
980368b2b1cSJohn Baldwin 	}
981368b2b1cSJohn Baldwin 	close(dpipe[1]);
982368b2b1cSJohn Baldwin 
983368b2b1cSJohn Baldwin 	/* Parent process. */
984368b2b1cSJohn Baldwin 
985368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
986368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
987368b2b1cSJohn Baldwin 
988368b2b1cSJohn Baldwin 	/* Release the child. */
989368b2b1cSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
990368b2b1cSJohn Baldwin 
991368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
992368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid));
993368b2b1cSJohn Baldwin 	close(cpipe[0]);
994368b2b1cSJohn Baldwin 
995368b2b1cSJohn Baldwin 	ATF_REQUIRE(ppid == getpid());
996368b2b1cSJohn Baldwin 
997368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
998368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
999368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
1000368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1001368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
1002368b2b1cSJohn Baldwin 
1003368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
1004368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
1005368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == child);
1006368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1007368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1008368b2b1cSJohn Baldwin }
1009368b2b1cSJohn Baldwin 
1010189ac973SJohn Baldwin /*
1011189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1012189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
1013189ac973SJohn Baldwin  */
1014189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
1015189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
1016189ac973SJohn Baldwin {
1017189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1018189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1019189ac973SJohn Baldwin 	int status;
1020189ac973SJohn Baldwin 
1021189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1022189ac973SJohn Baldwin 	if (fpid == 0) {
1023189ac973SJohn Baldwin 		trace_me();
1024189ac973SJohn Baldwin 		follow_fork_parent(false);
1025189ac973SJohn Baldwin 	}
1026189ac973SJohn Baldwin 
1027189ac973SJohn Baldwin 	/* Parent process. */
1028189ac973SJohn Baldwin 	children[0] = fpid;
1029189ac973SJohn Baldwin 
1030189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1031189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1032189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1033189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1034189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1035189ac973SJohn Baldwin 
1036189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1037189ac973SJohn Baldwin 
1038189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1039189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1040189ac973SJohn Baldwin 
1041189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1042189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1043189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1044189ac973SJohn Baldwin 
1045189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1046189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1047189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork);
1048189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1049189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1050189ac973SJohn Baldwin 
1051189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1052189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1053189ac973SJohn Baldwin 
1054189ac973SJohn Baldwin 	/*
1055189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1056189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1057189ac973SJohn Baldwin 	 */
1058189ac973SJohn Baldwin 	wpid = wait(&status);
1059189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1060189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1061189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1062189ac973SJohn Baldwin 
1063189ac973SJohn Baldwin 	wpid = wait(&status);
1064189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1065189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1066189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1067189ac973SJohn Baldwin 
1068189ac973SJohn Baldwin 	wpid = wait(&status);
1069189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1070189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1071189ac973SJohn Baldwin }
1072189ac973SJohn Baldwin 
1073189ac973SJohn Baldwin /*
1074189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1075189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1076189ac973SJohn Baldwin  */
1077189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1078189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1079189ac973SJohn Baldwin {
1080189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1081189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1082189ac973SJohn Baldwin 	int status;
1083189ac973SJohn Baldwin 
1084189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1085189ac973SJohn Baldwin 	if (fpid == 0) {
1086189ac973SJohn Baldwin 		trace_me();
1087189ac973SJohn Baldwin 		follow_fork_parent(true);
1088189ac973SJohn Baldwin 	}
1089189ac973SJohn Baldwin 
1090189ac973SJohn Baldwin 	/* Parent process. */
1091189ac973SJohn Baldwin 	children[0] = fpid;
1092189ac973SJohn Baldwin 
1093189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1094189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1095189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1096189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1097189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1098189ac973SJohn Baldwin 
1099189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1100189ac973SJohn Baldwin 
1101189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1102189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1103189ac973SJohn Baldwin 
1104189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1105189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1106189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1107189ac973SJohn Baldwin 
1108189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1109189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1110189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork);
1111189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1112189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1113189ac973SJohn Baldwin 
1114189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1115189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1116189ac973SJohn Baldwin 
1117189ac973SJohn Baldwin 	/*
1118189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1119189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1120189ac973SJohn Baldwin 	 */
1121189ac973SJohn Baldwin 	wpid = wait(&status);
1122189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1123189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1124189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1125189ac973SJohn Baldwin 
1126189ac973SJohn Baldwin 	wpid = wait(&status);
1127189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1128189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1129189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1130189ac973SJohn Baldwin 
1131189ac973SJohn Baldwin 	wpid = wait(&status);
1132189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1133189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1134189ac973SJohn Baldwin }
1135189ac973SJohn Baldwin 
1136189ac973SJohn Baldwin static void *
1137189ac973SJohn Baldwin simple_thread(void *arg __unused)
1138189ac973SJohn Baldwin {
1139189ac973SJohn Baldwin 
1140189ac973SJohn Baldwin 	pthread_exit(NULL);
1141189ac973SJohn Baldwin }
1142189ac973SJohn Baldwin 
11435fcfab6eSJohn Baldwin static __dead2 void
11445fcfab6eSJohn Baldwin simple_thread_main(void)
11455fcfab6eSJohn Baldwin {
11465fcfab6eSJohn Baldwin 	pthread_t thread;
11475fcfab6eSJohn Baldwin 
11485fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, NULL) == 0);
11495fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_join(thread, NULL) == 0);
11505fcfab6eSJohn Baldwin 	exit(1);
11515fcfab6eSJohn Baldwin }
11525fcfab6eSJohn Baldwin 
1153189ac973SJohn Baldwin /*
1154189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1155189ac973SJohn Baldwin  * thread reports the correct value.
1156189ac973SJohn Baldwin  */
1157189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1158189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1159189ac973SJohn Baldwin {
1160189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1161189ac973SJohn Baldwin 	pid_t fpid, wpid;
1162e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1163189ac973SJohn Baldwin 	int status;
1164189ac973SJohn Baldwin 
1165189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1166189ac973SJohn Baldwin 	if (fpid == 0) {
1167189ac973SJohn Baldwin 		trace_me();
11685fcfab6eSJohn Baldwin 		simple_thread_main();
1169189ac973SJohn Baldwin 	}
1170189ac973SJohn Baldwin 
1171189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1172189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1173189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1174189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1175189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1176189ac973SJohn Baldwin 
1177189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1178189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1179e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1180189ac973SJohn Baldwin 
1181189ac973SJohn Baldwin 	/*
1182189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1183189ac973SJohn Baldwin 	 * system call exits.
1184189ac973SJohn Baldwin 	 */
1185189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1186189ac973SJohn Baldwin 
1187189ac973SJohn Baldwin 	/*
1188189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1189189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1190189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1191189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1192189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1193189ac973SJohn Baldwin 	 */
1194189ac973SJohn Baldwin 	for (;;) {
1195189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1196189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1197189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1198189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1199189ac973SJohn Baldwin 
1200189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1201189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1202189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1203189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1204e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1205189ac973SJohn Baldwin 			/* New thread seen. */
1206189ac973SJohn Baldwin 			break;
1207189ac973SJohn Baldwin 
1208189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1209189ac973SJohn Baldwin 	}
1210189ac973SJohn Baldwin 
1211189ac973SJohn Baldwin 	/* Wait for the child to exit. */
1212189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1213189ac973SJohn Baldwin 	for (;;) {
1214189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1215189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1216189ac973SJohn Baldwin 		if (WIFEXITED(status))
1217189ac973SJohn Baldwin 			break;
1218189ac973SJohn Baldwin 
1219189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1220189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1221189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1222189ac973SJohn Baldwin 	}
1223189ac973SJohn Baldwin 
1224189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1225189ac973SJohn Baldwin 
1226189ac973SJohn Baldwin 	wpid = wait(&status);
1227189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1228189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1229189ac973SJohn Baldwin }
1230189ac973SJohn Baldwin 
12315fcfab6eSJohn Baldwin /*
12325fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
12335fcfab6eSJohn Baldwin  */
12345fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
12355fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
12365fcfab6eSJohn Baldwin {
12375fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
12385fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
12395fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
12405fcfab6eSJohn Baldwin 	int status;
12415fcfab6eSJohn Baldwin 
12425fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
12435fcfab6eSJohn Baldwin 	if (fpid == 0) {
12445fcfab6eSJohn Baldwin 		trace_me();
12455fcfab6eSJohn Baldwin 		simple_thread_main();
12465fcfab6eSJohn Baldwin 	}
12475fcfab6eSJohn Baldwin 
12485fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
12495fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12505fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12515fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12525fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
12535fcfab6eSJohn Baldwin 
12545fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
12555fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
12565fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
12575fcfab6eSJohn Baldwin 
12585fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
12595fcfab6eSJohn Baldwin 
12605fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
12615fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12625fcfab6eSJohn Baldwin 
12635fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
12645fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12655fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12665fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12675fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
12685fcfab6eSJohn Baldwin 
12695fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
12705fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
12715fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
12725fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
12735fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
12745fcfab6eSJohn Baldwin 
12755fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12765fcfab6eSJohn Baldwin 
12775fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
12785fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12795fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12805fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12815fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
12825fcfab6eSJohn Baldwin 
12835fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
12845fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
12855fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
12865fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
12875fcfab6eSJohn Baldwin 
12885fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12895fcfab6eSJohn Baldwin 
12905fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
12915fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12925fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
12935fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
12945fcfab6eSJohn Baldwin 
12955fcfab6eSJohn Baldwin 	wpid = wait(&status);
12965fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
12975fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
12985fcfab6eSJohn Baldwin }
12995fcfab6eSJohn Baldwin 
13005fcfab6eSJohn Baldwin static void *
13015fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
13025fcfab6eSJohn Baldwin {
13035fcfab6eSJohn Baldwin 
13045fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
13055fcfab6eSJohn Baldwin 	exit(127);
13065fcfab6eSJohn Baldwin }
13075fcfab6eSJohn Baldwin 
13085fcfab6eSJohn Baldwin static __dead2 void
13095fcfab6eSJohn Baldwin exec_thread_main(void)
13105fcfab6eSJohn Baldwin {
13115fcfab6eSJohn Baldwin 	pthread_t thread;
13125fcfab6eSJohn Baldwin 
13135fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, exec_thread, NULL) == 0);
13145fcfab6eSJohn Baldwin 	for (;;)
13155fcfab6eSJohn Baldwin 		sleep(60);
13165fcfab6eSJohn Baldwin 	exit(1);
13175fcfab6eSJohn Baldwin }
13185fcfab6eSJohn Baldwin 
13195fcfab6eSJohn Baldwin /*
13205fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
13215fcfab6eSJohn Baldwin  * process that calls execve(2).
13225fcfab6eSJohn Baldwin  */
13235fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
13245fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
13255fcfab6eSJohn Baldwin {
13265fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
13275fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
13285fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
13295fcfab6eSJohn Baldwin 	int status;
13305fcfab6eSJohn Baldwin 
13315fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13325fcfab6eSJohn Baldwin 	if (fpid == 0) {
13335fcfab6eSJohn Baldwin 		trace_me();
13345fcfab6eSJohn Baldwin 		exec_thread_main();
13355fcfab6eSJohn Baldwin 	}
13365fcfab6eSJohn Baldwin 
13375fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13385fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13395fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13405fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13415fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
13425fcfab6eSJohn Baldwin 
13435fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13445fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13455fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13465fcfab6eSJohn Baldwin 
13475fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
13485fcfab6eSJohn Baldwin 
13495fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
13505fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13515fcfab6eSJohn Baldwin 
13525fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13535fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13545fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13555fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13565fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13575fcfab6eSJohn Baldwin 
13585fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13595fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
13605fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13615fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13625fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13635fcfab6eSJohn Baldwin 
13645fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13655fcfab6eSJohn Baldwin 
13665fcfab6eSJohn Baldwin 	/*
13675fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
13685fcfab6eSJohn Baldwin 	 * single threading from execve().
13695fcfab6eSJohn Baldwin 	 */
13705fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13715fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13725fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13735fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13745fcfab6eSJohn Baldwin 
13755fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13765fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
13775fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
13785fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[0]);
13795fcfab6eSJohn Baldwin 
13805fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13815fcfab6eSJohn Baldwin 
13825fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
13835fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13845fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13855fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13865fcfab6eSJohn Baldwin 
13875fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13885fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
13895fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
13905fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
13915fcfab6eSJohn Baldwin 
13925fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13935fcfab6eSJohn Baldwin 
13945fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13955fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13965fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
13975fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
13985fcfab6eSJohn Baldwin 
13995fcfab6eSJohn Baldwin 	wpid = wait(&status);
14005fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14015fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
14025fcfab6eSJohn Baldwin }
14035fcfab6eSJohn Baldwin 
14043340c45bSJohn Baldwin static void
14053340c45bSJohn Baldwin handler(int sig __unused)
14063340c45bSJohn Baldwin {
14073340c45bSJohn Baldwin }
14083340c45bSJohn Baldwin 
14093340c45bSJohn Baldwin static void
14103340c45bSJohn Baldwin signal_main(void)
14113340c45bSJohn Baldwin {
14123340c45bSJohn Baldwin 
14133340c45bSJohn Baldwin 	signal(SIGINFO, handler);
14143340c45bSJohn Baldwin 	raise(SIGINFO);
14153340c45bSJohn Baldwin 	exit(0);
14163340c45bSJohn Baldwin }
14173340c45bSJohn Baldwin 
14183340c45bSJohn Baldwin /*
14193340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
14203340c45bSJohn Baldwin  */
14213340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
14223340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
14233340c45bSJohn Baldwin {
14243340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
14253340c45bSJohn Baldwin 	pid_t fpid, wpid;
14263340c45bSJohn Baldwin 	int status;
14273340c45bSJohn Baldwin 
14283340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14293340c45bSJohn Baldwin 	if (fpid == 0) {
14303340c45bSJohn Baldwin 		trace_me();
14313340c45bSJohn Baldwin 		signal_main();
14323340c45bSJohn Baldwin 	}
14333340c45bSJohn Baldwin 
14343340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14353340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14363340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14373340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14383340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14393340c45bSJohn Baldwin 
14403340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14413340c45bSJohn Baldwin 
14423340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
14433340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14443340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14453340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGINFO);
14463340c45bSJohn Baldwin 
14473340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14483340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_event == PL_EVENT_SIGNAL);
14493340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
14503340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == SI_LWP);
14513340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_pid == wpid);
14523340c45bSJohn Baldwin 
14533340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14543340c45bSJohn Baldwin 
14553340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
14563340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14573340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
14583340c45bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
14593340c45bSJohn Baldwin 
14603340c45bSJohn Baldwin 	wpid = wait(&status);
14613340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14623340c45bSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
14633340c45bSJohn Baldwin }
14643340c45bSJohn Baldwin 
14658d570f64SJohn Baldwin /*
14668d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
14678d570f64SJohn Baldwin  */
14688d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
14698d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
14708d570f64SJohn Baldwin {
14718d570f64SJohn Baldwin 	pid_t fpid, wpid;
14728d570f64SJohn Baldwin 	int events, status;
14738d570f64SJohn Baldwin 
14748d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14758d570f64SJohn Baldwin 	if (fpid == 0) {
14768d570f64SJohn Baldwin 		trace_me();
14778d570f64SJohn Baldwin 		exec_thread(NULL);
14788d570f64SJohn Baldwin 	}
14798d570f64SJohn Baldwin 
14808d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14818d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14828d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14838d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14848d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14858d570f64SJohn Baldwin 
14868d570f64SJohn Baldwin 	events = 0;
14878d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
14888d570f64SJohn Baldwin 	    sizeof(events)) == 0);
14898d570f64SJohn Baldwin 
14908d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14918d570f64SJohn Baldwin 
14928d570f64SJohn Baldwin 	/* Should get one event at exit. */
14938d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14948d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
14958d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
14968d570f64SJohn Baldwin 
14978d570f64SJohn Baldwin 	wpid = wait(&status);
14988d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14998d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15008d570f64SJohn Baldwin }
15018d570f64SJohn Baldwin 
15028d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
15038d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
15048d570f64SJohn Baldwin {
15058d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
15068d570f64SJohn Baldwin 	pid_t fpid, wpid;
15078d570f64SJohn Baldwin 	int events, status;
15088d570f64SJohn Baldwin 
15098d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15108d570f64SJohn Baldwin 	if (fpid == 0) {
15118d570f64SJohn Baldwin 		trace_me();
15128d570f64SJohn Baldwin 		exec_thread(NULL);
15138d570f64SJohn Baldwin 	}
15148d570f64SJohn Baldwin 
15158d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15168d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15178d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15188d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15198d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15208d570f64SJohn Baldwin 
15218d570f64SJohn Baldwin 	events = PTRACE_EXEC;
15228d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15238d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15248d570f64SJohn Baldwin 
15258d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15268d570f64SJohn Baldwin 
15278d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
15288d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15298d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15308d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
15318d570f64SJohn Baldwin 
15328d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
15338d570f64SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
15348d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
15358d570f64SJohn Baldwin 
15368d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15378d570f64SJohn Baldwin 
15388d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
15398d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15408d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15418d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15428d570f64SJohn Baldwin 
15438d570f64SJohn Baldwin 	wpid = wait(&status);
15448d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15458d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15468d570f64SJohn Baldwin }
15478d570f64SJohn Baldwin 
15488d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
15498d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
15508d570f64SJohn Baldwin {
15518d570f64SJohn Baldwin 	pid_t fpid, wpid;
15528d570f64SJohn Baldwin 	int events, status;
15538d570f64SJohn Baldwin 
15548d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15558d570f64SJohn Baldwin 	if (fpid == 0) {
15568d570f64SJohn Baldwin 		trace_me();
15578d570f64SJohn Baldwin 		exit(0);
15588d570f64SJohn Baldwin 	}
15598d570f64SJohn Baldwin 
15608d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15618d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15628d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15638d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15648d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15658d570f64SJohn Baldwin 
15668d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
15678d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
15688d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15698d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15708d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_FORK);
15718d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
15728d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15738d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15748d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_FORK));
15758d570f64SJohn Baldwin 
15768d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
15778d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
15788d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15798d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15808d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_LWP);
15818d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
15828d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15838d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15848d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_LWP));
15858d570f64SJohn Baldwin 
15868d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15878d570f64SJohn Baldwin 
15888d570f64SJohn Baldwin 	/* Should get one event at exit. */
15898d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15908d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15918d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15928d570f64SJohn Baldwin 
15938d570f64SJohn Baldwin 	wpid = wait(&status);
15948d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15958d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15968d570f64SJohn Baldwin }
15978d570f64SJohn Baldwin 
1598fc4f075aSJohn Baldwin /*
1599fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1600fc4f075aSJohn Baldwin  */
1601fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
1602fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1603fc4f075aSJohn Baldwin {
1604fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1605fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1606fc4f075aSJohn Baldwin 	int events, status;
1607fc4f075aSJohn Baldwin 
1608fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1609fc4f075aSJohn Baldwin 	if (fpid == 0) {
1610fc4f075aSJohn Baldwin 		trace_me();
1611fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1612fc4f075aSJohn Baldwin 	}
1613fc4f075aSJohn Baldwin 
1614fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1615fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1616fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1617fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1618fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1619fc4f075aSJohn Baldwin 
1620fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1621fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1622fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1623fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1624fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1625fc4f075aSJohn Baldwin 
1626fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1627fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1628fc4f075aSJohn Baldwin 
1629fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1630fc4f075aSJohn Baldwin 	wpid = wait(&status);
1631fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1632fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1633fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1634fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1635fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1636fc4f075aSJohn Baldwin 
1637fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1638fc4f075aSJohn Baldwin 
1639fc4f075aSJohn Baldwin 	wpid = wait(&status);
1640fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1641fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1642fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1643fc4f075aSJohn Baldwin 
1644fc4f075aSJohn Baldwin 	wpid = wait(&status);
1645fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1646fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1647fc4f075aSJohn Baldwin }
1648fc4f075aSJohn Baldwin 
1649fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
1650fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1651fc4f075aSJohn Baldwin {
1652fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1653fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1654fc4f075aSJohn Baldwin 	int events, status;
1655fc4f075aSJohn Baldwin 
1656fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1657fc4f075aSJohn Baldwin 	if (fpid == 0) {
1658fc4f075aSJohn Baldwin 		trace_me();
1659fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1660fc4f075aSJohn Baldwin 	}
1661fc4f075aSJohn Baldwin 
1662fc4f075aSJohn Baldwin 	/* Parent process. */
1663fc4f075aSJohn Baldwin 	children[0] = fpid;
1664fc4f075aSJohn Baldwin 
1665fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1666fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1667fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1668fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1669fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1670fc4f075aSJohn Baldwin 
1671fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1672fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1673fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1674fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1675fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1676fc4f075aSJohn Baldwin 
1677fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1678fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1679fc4f075aSJohn Baldwin 
1680fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1681fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1682fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1683fc4f075aSJohn Baldwin 
1684fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1685fc4f075aSJohn Baldwin 
1686fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1687fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1688fc4f075aSJohn Baldwin 
1689fc4f075aSJohn Baldwin 	/*
1690fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1691fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1692fc4f075aSJohn Baldwin 	 */
1693fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
1694fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1695fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1696fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1697fc4f075aSJohn Baldwin 
1698fc4f075aSJohn Baldwin 	/*
1699fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1700fc4f075aSJohn Baldwin 	 * exits.
1701fc4f075aSJohn Baldwin 	 */
1702fc4f075aSJohn Baldwin 	wpid = wait(&status);
1703fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1704fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1705fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1706fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1707fc4f075aSJohn Baldwin 	    -1);
1708fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1709fc4f075aSJohn Baldwin 
1710fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1711fc4f075aSJohn Baldwin 
1712fc4f075aSJohn Baldwin 	wpid = wait(&status);
1713fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1714fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1715fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1716fc4f075aSJohn Baldwin 
1717fc4f075aSJohn Baldwin 	wpid = wait(&status);
1718fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1719fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1720fc4f075aSJohn Baldwin }
1721fc4f075aSJohn Baldwin 
1722403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
1723e2ebfbbfSEric Badger /*
172482a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
172582a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
172682a4538fSEric Badger  */
172782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
172882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
172982a4538fSEric Badger {
173082a4538fSEric Badger 	pid_t fpid, wpid;
173182a4538fSEric Badger 	int status;
173282a4538fSEric Badger 
173382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
173482a4538fSEric Badger 	if (fpid == 0) {
173582a4538fSEric Badger 		trace_me();
17369e0d1159SEric Badger 		breakpoint();
173782a4538fSEric Badger 		exit(1);
173882a4538fSEric Badger 	}
173982a4538fSEric Badger 
174082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
174182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
174282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
174382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
174482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
174582a4538fSEric Badger 
174682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
174782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
174882a4538fSEric Badger 
174982a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
175082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
175182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
175282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
175382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
175482a4538fSEric Badger 
175582a4538fSEric Badger 	/* Kill the child process. */
175682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
175782a4538fSEric Badger 
175882a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
175982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
176082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
176182a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
176282a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
176382a4538fSEric Badger 
176482a4538fSEric Badger 	wpid = wait(&status);
176582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
176682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
176782a4538fSEric Badger }
1768403e331dSJohn Baldwin #endif /* HAVE_BREAKPOINT */
176982a4538fSEric Badger 
177082a4538fSEric Badger /*
177182a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
177282a4538fSEric Badger  * process exit when stopped inside of a system call.
177382a4538fSEric Badger  */
177482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
177582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
177682a4538fSEric Badger {
177782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
177882a4538fSEric Badger 	pid_t fpid, wpid;
177982a4538fSEric Badger 	int status;
178082a4538fSEric Badger 
178182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
178282a4538fSEric Badger 	if (fpid == 0) {
178382a4538fSEric Badger 		trace_me();
178482a4538fSEric Badger 		getpid();
178582a4538fSEric Badger 		exit(1);
178682a4538fSEric Badger 	}
178782a4538fSEric Badger 
178882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
178982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
179082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
179182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
179282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
179382a4538fSEric Badger 
179482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
179582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
179682a4538fSEric Badger 
179782a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
179882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
179982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
180082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
180182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
180282a4538fSEric Badger 
180382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
180482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
180582a4538fSEric Badger 
180682a4538fSEric Badger 	/* Kill the child process. */
180782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
180882a4538fSEric Badger 
180982a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
181082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
181182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
181282a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
181382a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
181482a4538fSEric Badger 
181582a4538fSEric Badger 	wpid = wait(&status);
181682a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
181782a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
181882a4538fSEric Badger }
181982a4538fSEric Badger 
182082a4538fSEric Badger /*
182182a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
182282a4538fSEric Badger  * process exit when killing a multithreaded process.
182382a4538fSEric Badger  */
182482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
182582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
182682a4538fSEric Badger {
182782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
182882a4538fSEric Badger 	pid_t fpid, wpid;
182982a4538fSEric Badger 	lwpid_t main_lwp;
183082a4538fSEric Badger 	int status;
183182a4538fSEric Badger 
183282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
183382a4538fSEric Badger 	if (fpid == 0) {
183482a4538fSEric Badger 		trace_me();
183582a4538fSEric Badger 		simple_thread_main();
183682a4538fSEric Badger 	}
183782a4538fSEric Badger 
183882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
183982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
184082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
184182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
184282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
184382a4538fSEric Badger 
184482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
184582a4538fSEric Badger 	    sizeof(pl)) != -1);
184682a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
184782a4538fSEric Badger 
184882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
184982a4538fSEric Badger 
185082a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
185182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
185282a4538fSEric Badger 
185382a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
185482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
185582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
185682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
185782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
185882a4538fSEric Badger 
185982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
186082a4538fSEric Badger 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
186182a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
186282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
186382a4538fSEric Badger 
186482a4538fSEric Badger 	/* Kill the child process. */
186582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
186682a4538fSEric Badger 
186782a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
186882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
186982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
187082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
187182a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
187282a4538fSEric Badger 
187382a4538fSEric Badger 	wpid = wait(&status);
187482a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
187582a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
187682a4538fSEric Badger }
187782a4538fSEric Badger 
187882a4538fSEric Badger static void *
187982a4538fSEric Badger mask_usr1_thread(void *arg)
188082a4538fSEric Badger {
188182a4538fSEric Badger 	pthread_barrier_t *pbarrier;
188282a4538fSEric Badger 	sigset_t sigmask;
188382a4538fSEric Badger 
188482a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
188582a4538fSEric Badger 
188682a4538fSEric Badger 	sigemptyset(&sigmask);
188782a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
188882a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
188982a4538fSEric Badger 
189082a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
189182a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
189282a4538fSEric Badger 
189382a4538fSEric Badger 	for (;;)
189482a4538fSEric Badger 		sleep(60);
189582a4538fSEric Badger 
189682a4538fSEric Badger 	return (NULL);
189782a4538fSEric Badger }
189882a4538fSEric Badger 
189982a4538fSEric Badger /*
190082a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
190182a4538fSEric Badger  * and prevents spurious stops due to those other signals.
190282a4538fSEric Badger  */
19033cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal);
19043cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
19053cf56bb4SEnji Cooper {
19063cf56bb4SEnji Cooper 
19073cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
19083cf56bb4SEnji Cooper }
190982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
191082a4538fSEric Badger {
191182a4538fSEric Badger 	pid_t fpid, wpid;
191282a4538fSEric Badger 	int status;
191382a4538fSEric Badger 	cpuset_t setmask;
191482a4538fSEric Badger 	pthread_t t;
191582a4538fSEric Badger 	pthread_barrier_t barrier;
1916bc2be1d3SEric Badger 	struct sched_param sched_param;
191782a4538fSEric Badger 
191882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
191982a4538fSEric Badger 	if (fpid == 0) {
1920bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
192182a4538fSEric Badger 		CPU_ZERO(&setmask);
192282a4538fSEric Badger 		CPU_SET(0, &setmask);
192382a4538fSEric Badger 		cpusetid_t setid;
192482a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
192582a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
192682a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
192782a4538fSEric Badger 
192882a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
192982a4538fSEric Badger 
193082a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
193182a4538fSEric Badger 		    (void*)&barrier) == 0);
193282a4538fSEric Badger 
1933bc2be1d3SEric Badger 		/*
1934bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
1935bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
1936bc2be1d3SEric Badger 		 * thread runs first.
1937bc2be1d3SEric Badger 		 */
1938bc2be1d3SEric Badger 		sched_param.sched_priority =
1939bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
1940bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
1941bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
1942bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
1943bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
1944bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
1945bc2be1d3SEric Badger 		    &sched_param) == 0);
1946bc2be1d3SEric Badger 
194782a4538fSEric Badger 		sigset_t sigmask;
194882a4538fSEric Badger 		sigemptyset(&sigmask);
194982a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
195082a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
195182a4538fSEric Badger 
195282a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
195382a4538fSEric Badger 		pthread_barrier_wait(&barrier);
195482a4538fSEric Badger 
195582a4538fSEric Badger 		trace_me();
195682a4538fSEric Badger 
195782a4538fSEric Badger 		for (;;)
195882a4538fSEric Badger 			sleep(60);
195982a4538fSEric Badger 
196082a4538fSEric Badger 		exit(1);
196182a4538fSEric Badger 	}
196282a4538fSEric Badger 
196382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
196482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
196582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
196682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
196782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
196882a4538fSEric Badger 
196982a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
197082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
197182a4538fSEric Badger 
197282a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
197382a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
197482a4538fSEric Badger 
197582a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
197682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
197782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
197882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
197982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
198082a4538fSEric Badger 
198182a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
198282a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
198382a4538fSEric Badger 
198482a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
198582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
198682a4538fSEric Badger 
198782a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
198882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
198982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
199082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
199182a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
199282a4538fSEric Badger 
199382a4538fSEric Badger 	wpid = wait(&status);
199482a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
199582a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
199682a4538fSEric Badger }
199782a4538fSEric Badger 
199882a4538fSEric Badger /*
199982a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
200082a4538fSEric Badger  * and prevents spurious stops caused by those events.
200182a4538fSEric Badger  */
20023cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop);
20033cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, 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_stop, tc)
200982a4538fSEric Badger {
201082a4538fSEric Badger 	pid_t fpid, wpid;
2011bc2be1d3SEric Badger 	int status;
201282a4538fSEric Badger 	cpuset_t setmask;
201382a4538fSEric Badger 	pthread_t t;
201482a4538fSEric Badger 	pthread_barrier_t barrier;
201582a4538fSEric Badger 	lwpid_t main_lwp;
201682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2017bc2be1d3SEric Badger 	struct sched_param sched_param;
201882a4538fSEric Badger 
201982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
202082a4538fSEric Badger 	if (fpid == 0) {
202182a4538fSEric Badger 		trace_me();
202282a4538fSEric Badger 
2023bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
202482a4538fSEric Badger 		CPU_ZERO(&setmask);
202582a4538fSEric Badger 		CPU_SET(0, &setmask);
202682a4538fSEric Badger 		cpusetid_t setid;
202782a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
202882a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
202982a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
203082a4538fSEric Badger 
203182a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
203282a4538fSEric Badger 
203382a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
203482a4538fSEric Badger 		    (void*)&barrier) == 0);
203582a4538fSEric Badger 
2036bc2be1d3SEric Badger 		/*
2037bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2038bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2039bc2be1d3SEric Badger 		 * thread runs first.
2040bc2be1d3SEric Badger 		 */
2041bc2be1d3SEric Badger 		sched_param.sched_priority =
2042bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2043bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2044bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2045bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2046bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2047bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2048bc2be1d3SEric Badger 		    &sched_param) == 0);
2049bc2be1d3SEric Badger 
205082a4538fSEric Badger 		sigset_t sigmask;
205182a4538fSEric Badger 		sigemptyset(&sigmask);
205282a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
205382a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
205482a4538fSEric Badger 
205582a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
205682a4538fSEric Badger 		pthread_barrier_wait(&barrier);
205782a4538fSEric Badger 
205882a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
205982a4538fSEric Badger 		raise(SIGSTOP);
206082a4538fSEric Badger 
206182a4538fSEric Badger 		getpid();
206282a4538fSEric Badger 		exit(1);
206382a4538fSEric Badger 	}
206482a4538fSEric Badger 
206582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
206682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
206782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
206882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
206982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
207082a4538fSEric Badger 
207182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
207282a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
207382a4538fSEric Badger 
207482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
207582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
207682a4538fSEric Badger 
207782a4538fSEric Badger 	/*
207882a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
207982a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
208082a4538fSEric Badger 	 */
208182a4538fSEric Badger 	for (;;) {
208282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
208382a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
208482a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
208582a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
208682a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
208782a4538fSEric Badger 			    sizeof(pl)) != -1);
208882a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
208982a4538fSEric Badger 		} else {
209082a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
209182a4538fSEric Badger 			break;
209282a4538fSEric Badger 		}
209382a4538fSEric Badger 		ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
209482a4538fSEric Badger 	}
209582a4538fSEric Badger 
2096bc2be1d3SEric Badger 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
209782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
209882a4538fSEric Badger 
209982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
210082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
210182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
210282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
210382a4538fSEric Badger 
210482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
210582a4538fSEric Badger 	    sizeof(pl)) != -1);
2106bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid == main_lwp);
210782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
2108bc2be1d3SEric Badger 	/* Prevent the main thread from hitting its syscall exit for now. */
210982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0);
211082a4538fSEric Badger 
2111bc2be1d3SEric Badger 	/*
2112bc2be1d3SEric Badger 	 * Proceed, allowing second thread to hit syscall exit for
2113bc2be1d3SEric Badger 	 * pthread_barrier_wait().
2114bc2be1d3SEric Badger 	 */
2115bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
2116bc2be1d3SEric Badger 
2117bc2be1d3SEric Badger 	wpid = waitpid(fpid, &status, 0);
2118bc2be1d3SEric Badger 	ATF_REQUIRE(wpid == fpid);
2119bc2be1d3SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2120bc2be1d3SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
2121bc2be1d3SEric Badger 
2122bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
2123bc2be1d3SEric Badger 	    sizeof(pl)) != -1);
2124bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
2125bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
212682a4538fSEric Badger 
212782a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
212882a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
212982a4538fSEric Badger 
213082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
213182a4538fSEric Badger 
2132bc2be1d3SEric Badger 	/* The next wait() should report the SIGUSR2. */
213382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
213482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
213582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
213682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
213782a4538fSEric Badger 
213882a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
213982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_RESUME, main_lwp, 0, 0) == 0);
214082a4538fSEric Badger 
214182a4538fSEric Badger 	/*
214282a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
2143bc2be1d3SEric Badger 	 * has been resumed. The second thread has taken a SIGUSR2 which will
2144bc2be1d3SEric Badger 	 * be replaced with a SIGKILL below. The main thread will get to run
2145bc2be1d3SEric Badger 	 * first. It should notice the kill request (even though the signal
2146bc2be1d3SEric Badger 	 * replacement occurred in the other thread) and exit accordingly.  It
2147bc2be1d3SEric Badger 	 * should not stop for the system call exit event.
214882a4538fSEric Badger 	 */
214982a4538fSEric Badger 
215082a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
215182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
215282a4538fSEric Badger 
215382a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
215482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
215582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
215682a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
215782a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
215882a4538fSEric Badger 
215982a4538fSEric Badger 	wpid = wait(&status);
216082a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
216182a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
216282a4538fSEric Badger }
216382a4538fSEric Badger 
216482a4538fSEric Badger static void
216582a4538fSEric Badger sigusr1_handler(int sig)
216682a4538fSEric Badger {
216782a4538fSEric Badger 
216882a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
216982a4538fSEric Badger 	_exit(2);
217082a4538fSEric Badger }
217182a4538fSEric Badger 
217282a4538fSEric Badger /*
217382a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
217482a4538fSEric Badger  * a PT_KILL will kill the process.
217582a4538fSEric Badger  */
217682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
217782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
217882a4538fSEric Badger {
217982a4538fSEric Badger 	pid_t fpid, wpid;
218082a4538fSEric Badger 	int status;
218182a4538fSEric Badger 	int max_pending_per_proc;
218282a4538fSEric Badger 	size_t len;
218382a4538fSEric Badger 	int i;
218482a4538fSEric Badger 
218582a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
218682a4538fSEric Badger 
218782a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
218882a4538fSEric Badger 	if (fpid == 0) {
218982a4538fSEric Badger 		trace_me();
219082a4538fSEric Badger 		exit(1);
219182a4538fSEric Badger 	}
219282a4538fSEric Badger 
219382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
219482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
219582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
219682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
219782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
219882a4538fSEric Badger 
219982a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
220082a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
220182a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
220282a4538fSEric Badger 
220382a4538fSEric Badger 	/* Fill the signal queue. */
220482a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
220582a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
220682a4538fSEric Badger 
220782a4538fSEric Badger 	/* Kill the child process. */
220882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
220982a4538fSEric Badger 
221082a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
221182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
221282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
221382a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
221482a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
221582a4538fSEric Badger 
221682a4538fSEric Badger 	wpid = wait(&status);
221782a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
221882a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
221982a4538fSEric Badger }
222082a4538fSEric Badger 
222182a4538fSEric Badger /*
222282a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
222382a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
222482a4538fSEric Badger  * call is complete.
222582a4538fSEric Badger  */
222682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
222782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
222882a4538fSEric Badger {
222982a4538fSEric Badger 	struct ptrace_lwpinfo pl;
223082a4538fSEric Badger 	pid_t fpid, wpid;
223182a4538fSEric Badger 	int status;
223282a4538fSEric Badger 
223382a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
223482a4538fSEric Badger 
223582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
223682a4538fSEric Badger 	if (fpid == 0) {
223782a4538fSEric Badger 		trace_me();
223882a4538fSEric Badger 		getpid();
223982a4538fSEric Badger 		exit(1);
224082a4538fSEric Badger 	}
224182a4538fSEric Badger 
224282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
224382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
224482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
224582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
224682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
224782a4538fSEric Badger 
224882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
224982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
225082a4538fSEric Badger 
225182a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
225282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
225382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
225482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
225582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
225682a4538fSEric Badger 
225782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
225882a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
225982a4538fSEric Badger 
226082a4538fSEric Badger 	/* Continue the child process with a signal. */
226182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
226282a4538fSEric Badger 
226382a4538fSEric Badger 	for (;;) {
226482a4538fSEric Badger 		/*
226582a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
226682a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
226782a4538fSEric Badger 		 * past any syscall stops.
226882a4538fSEric Badger 		 */
226982a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
227082a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
227182a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
227282a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
227382a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
227482a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
227582a4538fSEric Badger 		} else {
227682a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
227782a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
227882a4538fSEric Badger 			break;
227982a4538fSEric Badger 		}
228082a4538fSEric Badger 	}
228182a4538fSEric Badger 
228282a4538fSEric Badger 	wpid = wait(&status);
228382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
228482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
228582a4538fSEric Badger }
228682a4538fSEric Badger 
228782a4538fSEric Badger static void
228882a4538fSEric Badger sigusr1_counting_handler(int sig)
228982a4538fSEric Badger {
229082a4538fSEric Badger 	static int counter = 0;
229182a4538fSEric Badger 
229282a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
229382a4538fSEric Badger 	counter++;
229482a4538fSEric Badger 	if (counter == 2)
229582a4538fSEric Badger 		_exit(2);
229682a4538fSEric Badger }
229782a4538fSEric Badger 
229882a4538fSEric Badger /*
229982a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
230082a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
230182a4538fSEric Badger  * the system call is complete.
230282a4538fSEric Badger  */
230382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
230482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
230582a4538fSEric Badger {
230682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
230782a4538fSEric Badger 	pid_t fpid, wpid;
230882a4538fSEric Badger 	int status;
230982a4538fSEric Badger 
231082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
231182a4538fSEric Badger 
231282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
231382a4538fSEric Badger 	if (fpid == 0) {
231482a4538fSEric Badger 		trace_me();
231582a4538fSEric Badger 		getpid();
231682a4538fSEric Badger 		exit(1);
231782a4538fSEric Badger 	}
231882a4538fSEric Badger 
231982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
232082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
232182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
232282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
232382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
232482a4538fSEric Badger 
232582a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
232682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
232782a4538fSEric Badger 
232882a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
232982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
233082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
233182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
233282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
233382a4538fSEric Badger 
233482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
233582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
233682a4538fSEric Badger 
233782a4538fSEric Badger 	/* Continue the child process with a signal. */
233882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
233982a4538fSEric Badger 
234082a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
234182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
234282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
234382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
234482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
234582a4538fSEric Badger 
234682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
234782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
234882a4538fSEric Badger 
234982a4538fSEric Badger 	/* Continue the child process with a signal. */
235082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
235182a4538fSEric Badger 
235282a4538fSEric Badger 	for (;;) {
235382a4538fSEric Badger 		/*
235482a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
235582a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
235682a4538fSEric Badger 		 * past any syscall stops.
235782a4538fSEric Badger 		 */
235882a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
235982a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
236082a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
236182a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
236282a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
236382a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
236482a4538fSEric Badger 		} else {
236582a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
236682a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
236782a4538fSEric Badger 			break;
236882a4538fSEric Badger 		}
236982a4538fSEric Badger 	}
237082a4538fSEric Badger 
237182a4538fSEric Badger 	wpid = wait(&status);
237282a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
237382a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
237482a4538fSEric Badger }
237582a4538fSEric Badger 
237682a4538fSEric Badger /*
237782a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
237882a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
237982a4538fSEric Badger  */
238082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
238182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
238282a4538fSEric Badger {
238382a4538fSEric Badger 	pid_t fpid, wpid;
238482a4538fSEric Badger 	int status;
238582a4538fSEric Badger 	int max_pending_per_proc;
238682a4538fSEric Badger 	size_t len;
238782a4538fSEric Badger 	int i;
238882a4538fSEric Badger 
238982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
239082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
239182a4538fSEric Badger 
239282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
239382a4538fSEric Badger 	if (fpid == 0) {
239482a4538fSEric Badger 		trace_me();
239582a4538fSEric Badger 		exit(1);
239682a4538fSEric Badger 	}
239782a4538fSEric Badger 
239882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
239982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
240082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
240182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
240282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
240382a4538fSEric Badger 
240482a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
240582a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
240682a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
240782a4538fSEric Badger 
240882a4538fSEric Badger 	/* Fill the signal queue. */
240982a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
241082a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
241182a4538fSEric Badger 
241282a4538fSEric Badger 	/* Continue with signal. */
241382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
241482a4538fSEric Badger 
241582a4538fSEric Badger 	for (;;) {
241682a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
241782a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
241882a4538fSEric Badger 		if (WIFSTOPPED(status)) {
241982a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
242082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
242182a4538fSEric Badger 		} else {
242282a4538fSEric Badger 			/*
242382a4538fSEric Badger 			 * The last wait() should report normal _exit from the
242482a4538fSEric Badger 			 * SIGUSR1 handler.
242582a4538fSEric Badger 			 */
242682a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
242782a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
242882a4538fSEric Badger 			break;
242982a4538fSEric Badger 		}
243082a4538fSEric Badger 	}
243182a4538fSEric Badger 
243282a4538fSEric Badger 	wpid = wait(&status);
243382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
243482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
243582a4538fSEric Badger }
243682a4538fSEric Badger 
2437753e2922SBryan Drewery static sem_t sigusr1_sem;
2438753e2922SBryan Drewery static int got_usr1;
2439753e2922SBryan Drewery 
2440753e2922SBryan Drewery static void
2441753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused)
2442753e2922SBryan Drewery {
2443753e2922SBryan Drewery 
2444753e2922SBryan Drewery 	got_usr1++;
2445753e2922SBryan Drewery 	CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0);
2446753e2922SBryan Drewery }
2447753e2922SBryan Drewery 
2448753e2922SBryan Drewery /*
2449753e2922SBryan Drewery  * Verify that even if the signal queue is full for a child process,
2450753e2922SBryan Drewery  * and the signal is masked, a PT_CONTINUE with a signal will not
2451753e2922SBryan Drewery  * result in loss of that signal.
2452753e2922SBryan Drewery  */
2453753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
2454753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
2455753e2922SBryan Drewery {
2456753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2457753e2922SBryan Drewery 	pid_t fpid, wpid;
2458753e2922SBryan Drewery 	int status, err;
2459753e2922SBryan Drewery 	int max_pending_per_proc;
2460753e2922SBryan Drewery 	size_t len;
2461753e2922SBryan Drewery 	int i;
2462753e2922SBryan Drewery 	sigset_t sigmask;
2463753e2922SBryan Drewery 
2464753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
2465753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2466753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2467753e2922SBryan Drewery 
2468753e2922SBryan Drewery 	got_usr1 = 0;
2469753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2470753e2922SBryan Drewery 	if (fpid == 0) {
2471753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2472753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2473753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2474753e2922SBryan Drewery 
2475753e2922SBryan Drewery 		trace_me();
2476753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2477753e2922SBryan Drewery 
2478753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2479753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2480753e2922SBryan Drewery 		/* Wait to receive the SIGUSR1. */
2481753e2922SBryan Drewery 		do {
2482753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2483753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2484753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2485753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2486753e2922SBryan Drewery 		exit(1);
2487753e2922SBryan Drewery 	}
2488753e2922SBryan Drewery 
2489753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2490753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2491753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2492753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2493753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2494753e2922SBryan Drewery 
2495753e2922SBryan Drewery 	len = sizeof(max_pending_per_proc);
2496753e2922SBryan Drewery 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
2497753e2922SBryan Drewery 	    &max_pending_per_proc, &len, NULL, 0) == 0);
2498753e2922SBryan Drewery 
2499753e2922SBryan Drewery 	/* Fill the signal queue. */
2500753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i)
2501753e2922SBryan Drewery 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
2502753e2922SBryan Drewery 
2503753e2922SBryan Drewery 	/* Continue with signal. */
2504753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2505753e2922SBryan Drewery 
2506753e2922SBryan Drewery 	/* Collect and ignore all of the SIGUSR2. */
2507753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i) {
2508753e2922SBryan Drewery 		wpid = waitpid(fpid, &status, 0);
2509753e2922SBryan Drewery 		ATF_REQUIRE(wpid == fpid);
2510753e2922SBryan Drewery 		ATF_REQUIRE(WIFSTOPPED(status));
2511753e2922SBryan Drewery 		ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
2512753e2922SBryan Drewery 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2513753e2922SBryan Drewery 	}
2514753e2922SBryan Drewery 
2515753e2922SBryan Drewery 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
2516753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2517753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2518753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2519753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2520753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2521753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2522753e2922SBryan Drewery 
2523753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
2524753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2525753e2922SBryan Drewery 
2526753e2922SBryan Drewery 	/* The last wait() should report exit after receiving SIGUSR1. */
2527753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2528753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2529753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2530753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2531753e2922SBryan Drewery 
2532753e2922SBryan Drewery 	wpid = wait(&status);
2533753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2534753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2535753e2922SBryan Drewery }
2536753e2922SBryan Drewery 
253782a4538fSEric Badger /*
253882a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
253982a4538fSEric Badger  * replaced with another signal.
254082a4538fSEric Badger  */
254182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
254282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
254382a4538fSEric Badger {
254482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
254582a4538fSEric Badger 	pid_t fpid, wpid;
254682a4538fSEric Badger 	int status;
254782a4538fSEric Badger 
254882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
254982a4538fSEric Badger 	if (fpid == 0) {
255082a4538fSEric Badger 		trace_me();
255182a4538fSEric Badger 		sleep(20);
255282a4538fSEric Badger 		exit(1);
255382a4538fSEric Badger 	}
255482a4538fSEric Badger 
255582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
255682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
255782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
255882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
255982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
256082a4538fSEric Badger 
256182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
256282a4538fSEric Badger 
256382a4538fSEric Badger 	/* Send a signal without ptrace. */
256482a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGINT) == 0);
256582a4538fSEric Badger 
256682a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
256782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
256882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
256982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
257082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGINT);
257182a4538fSEric Badger 
257282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
257382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
257482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGINT);
257582a4538fSEric Badger 
257682a4538fSEric Badger 	/* Continue the child process with a different signal. */
257782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM) == 0);
257882a4538fSEric Badger 
257982a4538fSEric Badger 	/*
258082a4538fSEric Badger 	 * The last wait() should report having died due to the new
258182a4538fSEric Badger 	 * signal, SIGTERM.
258282a4538fSEric Badger 	 */
258382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
258482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
258582a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
258682a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGTERM);
258782a4538fSEric Badger 
258882a4538fSEric Badger 	wpid = wait(&status);
258982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
259082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
259182a4538fSEric Badger }
259282a4538fSEric Badger 
259382a4538fSEric Badger /*
259482a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
259582a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
259682a4538fSEric Badger  * invented for e.g, system call stops.
259782a4538fSEric Badger  */
259882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
259982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
260082a4538fSEric Badger {
260182a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2602fc1e29dcSBryan Drewery 	struct rlimit rl;
260382a4538fSEric Badger 	pid_t fpid, wpid;
260482a4538fSEric Badger 	int status;
260582a4538fSEric Badger 
260682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
260782a4538fSEric Badger 	if (fpid == 0) {
260882a4538fSEric Badger 		trace_me();
2609fc1e29dcSBryan Drewery 		/* SIGTRAP expected to cause exit on syscall entry. */
2610fc1e29dcSBryan Drewery 		rl.rlim_cur = rl.rlim_max = 0;
2611fc1e29dcSBryan Drewery 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0);
261282a4538fSEric Badger 		getpid();
261382a4538fSEric Badger 		exit(1);
261482a4538fSEric Badger 	}
261582a4538fSEric Badger 
261682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
261782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
261882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
261982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
262082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
262182a4538fSEric Badger 
262282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
262382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
262482a4538fSEric Badger 
262582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
262682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
262782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
262882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
262982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
263082a4538fSEric Badger 
263182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
263282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
263382a4538fSEric Badger 
263482a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
263582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP) == 0);
263682a4538fSEric Badger 
263782a4538fSEric Badger 	for (;;) {
263882a4538fSEric Badger 		/*
263982a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
264082a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
264182a4538fSEric Badger 		 */
264282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
264382a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
264482a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
264582a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
264682a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
264782a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
264882a4538fSEric Badger 		} else {
264982a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
265082a4538fSEric Badger 			ATF_REQUIRE(WTERMSIG(status) == SIGTRAP);
265182a4538fSEric Badger 			break;
265282a4538fSEric Badger 		}
265382a4538fSEric Badger 	}
265482a4538fSEric Badger 
265582a4538fSEric Badger 	wpid = wait(&status);
265682a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
265782a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
265882a4538fSEric Badger 
265982a4538fSEric Badger }
266082a4538fSEric Badger 
266182a4538fSEric Badger /*
266282a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
266382a4538fSEric Badger  */
266482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
266582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
266682a4538fSEric Badger {
266782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
266882a4538fSEric Badger 	pid_t fpid, wpid;
266982a4538fSEric Badger 	int status;
267082a4538fSEric Badger 
267182a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
267282a4538fSEric Badger 
267382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
267482a4538fSEric Badger 	if (fpid == 0) {
267582a4538fSEric Badger 		trace_me();
267682a4538fSEric Badger 		getpid();
267782a4538fSEric Badger 		exit(1);
267882a4538fSEric Badger 	}
267982a4538fSEric Badger 
268082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
268182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
268282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
268382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
268482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
268582a4538fSEric Badger 
268682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
268782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
268882a4538fSEric Badger 
268982a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
269082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
269182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
269282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
269382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
269482a4538fSEric Badger 
269582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
269682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
269782a4538fSEric Badger 
269882a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
269982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
270082a4538fSEric Badger 
270182a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
270282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
270382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
270482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
270582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
270682a4538fSEric Badger 
270782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
270882a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
270982a4538fSEric Badger 
271082a4538fSEric Badger 	/* Send an ABRT without ptrace. */
271182a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGABRT) == 0);
271282a4538fSEric Badger 
271382a4538fSEric Badger 	/* Continue normally. */
271482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
271582a4538fSEric Badger 
271682a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
271782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
271882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
271982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
272082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
272182a4538fSEric Badger 
272282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
272382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
272482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
272582a4538fSEric Badger 
272682a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
272782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
272882a4538fSEric Badger 
272982a4538fSEric Badger 	for (;;) {
273082a4538fSEric Badger 		/*
273182a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
273282a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
273382a4538fSEric Badger 		 * past any syscall stops.
273482a4538fSEric Badger 		 */
273582a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
273682a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
273782a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
273882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
273982a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
274082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
274182a4538fSEric Badger 		} else {
274282a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
274382a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
274482a4538fSEric Badger 			break;
274582a4538fSEric Badger 		}
274682a4538fSEric Badger 	}
274782a4538fSEric Badger 
274882a4538fSEric Badger 	wpid = wait(&status);
274982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
275082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
275182a4538fSEric Badger 
275282a4538fSEric Badger }
275382a4538fSEric Badger 
275482a4538fSEric Badger /*
275582a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
275682a4538fSEric Badger  */
275782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
275882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
275982a4538fSEric Badger {
276082a4538fSEric Badger 	pid_t fpid, wpid;
276182a4538fSEric Badger 	int status, kq, nevents;
276282a4538fSEric Badger 	struct kevent kev;
276382a4538fSEric Badger 
276482a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
276582a4538fSEric Badger 
276682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
276782a4538fSEric Badger 	if (fpid == 0) {
276882a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
276982a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
277082a4538fSEric Badger 		CHILD_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0);
277182a4538fSEric Badger 
277282a4538fSEric Badger 		trace_me();
277382a4538fSEric Badger 
277482a4538fSEric Badger 		for (;;) {
277582a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
277682a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
277782a4538fSEric Badger 				continue;
277882a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
277982a4538fSEric Badger 			CHILD_REQUIRE(kev.filter == EVFILT_SIGNAL);
278082a4538fSEric Badger 			CHILD_REQUIRE(kev.ident == SIGUSR1);
278182a4538fSEric Badger 			break;
278282a4538fSEric Badger 		}
278382a4538fSEric Badger 
278482a4538fSEric Badger 		exit(1);
278582a4538fSEric Badger 	}
278682a4538fSEric Badger 
278782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
278882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
278982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
279082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
279182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
279282a4538fSEric Badger 
279382a4538fSEric Badger 	/* Continue with the SIGUSR1. */
279482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
279582a4538fSEric Badger 
279682a4538fSEric Badger 	/*
279782a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
279882a4538fSEric Badger 	 */
279982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
280082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
280182a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
280282a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
280382a4538fSEric Badger 
280482a4538fSEric Badger 	wpid = wait(&status);
280582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
280682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
280782a4538fSEric Badger }
280882a4538fSEric Badger 
280982a4538fSEric Badger static void *
281082a4538fSEric Badger signal_thread(void *arg)
281182a4538fSEric Badger {
281282a4538fSEric Badger 	int err;
281382a4538fSEric Badger 	sigset_t sigmask;
281482a4538fSEric Badger 
281582a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
281682a4538fSEric Badger 
281782a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
281882a4538fSEric Badger 	do {
281982a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
282082a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
282182a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
282282a4538fSEric Badger 
282382a4538fSEric Badger 	/* Free our companion thread from the barrier. */
282482a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
282582a4538fSEric Badger 
282682a4538fSEric Badger 	/*
282782a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
282882a4538fSEric Badger 	 * other thread.
282982a4538fSEric Badger 	 */
283082a4538fSEric Badger 	CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
283182a4538fSEric Badger 	CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
283282a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
283382a4538fSEric Badger 
283482a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
283582a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
283682a4538fSEric Badger 
283782a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
283882a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
283982a4538fSEric Badger 
284082a4538fSEric Badger 	return (NULL);
284182a4538fSEric Badger }
284282a4538fSEric Badger 
284382a4538fSEric Badger /*
2844753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2845753e2922SBryan Drewery  * signal from kill() once unmasked.
2846753e2922SBryan Drewery  */
2847753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
2848753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
2849753e2922SBryan Drewery {
2850753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2851753e2922SBryan Drewery 	pid_t fpid, wpid;
2852753e2922SBryan Drewery 	int status, err;
2853753e2922SBryan Drewery 	sigset_t sigmask;
2854753e2922SBryan Drewery 
2855753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2856753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2857753e2922SBryan Drewery 	got_usr1 = 0;
2858753e2922SBryan Drewery 
2859753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2860753e2922SBryan Drewery 	if (fpid == 0) {
2861753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2862753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2863753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2864753e2922SBryan Drewery 
2865753e2922SBryan Drewery 		trace_me();
2866753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2867753e2922SBryan Drewery 
2868753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2869753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2870753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2871753e2922SBryan Drewery 		do {
2872753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2873753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2874753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2875753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2876753e2922SBryan Drewery 		exit(1);
2877753e2922SBryan Drewery 	}
2878753e2922SBryan Drewery 
2879753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2880753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2881753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2882753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2883753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2884753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2885753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
2886753e2922SBryan Drewery 
2887753e2922SBryan Drewery 	/* Send blocked SIGUSR1 which should cause a stop. */
2888753e2922SBryan Drewery 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
2889753e2922SBryan Drewery 
2890753e2922SBryan Drewery 	/* Continue the child ignoring the SIGSTOP. */
2891753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2892753e2922SBryan Drewery 
2893753e2922SBryan Drewery 	/* The next wait() should report the kill(SIGUSR1) was received. */
2894753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2895753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2896753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2897753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2898753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2899753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2900753e2922SBryan Drewery 
2901753e2922SBryan Drewery 	/* Continue the child, allowing in the SIGUSR1. */
2902753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2903753e2922SBryan Drewery 
2904753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
2905753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2906753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2907753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2908753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2909753e2922SBryan Drewery 
2910753e2922SBryan Drewery 	wpid = wait(&status);
2911753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2912753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2913753e2922SBryan Drewery }
2914753e2922SBryan Drewery 
2915753e2922SBryan Drewery /*
2916753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2917753e2922SBryan Drewery  * signal from PT_CONTINUE once unmasked.
2918753e2922SBryan Drewery  */
2919753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
2920753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
2921753e2922SBryan Drewery {
2922753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2923753e2922SBryan Drewery 	pid_t fpid, wpid;
2924753e2922SBryan Drewery 	int status, err;
2925753e2922SBryan Drewery 	sigset_t sigmask;
2926753e2922SBryan Drewery 
2927753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2928753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2929753e2922SBryan Drewery 	got_usr1 = 0;
2930753e2922SBryan Drewery 
2931753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2932753e2922SBryan Drewery 	if (fpid == 0) {
2933753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2934753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2935753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2936753e2922SBryan Drewery 
2937753e2922SBryan Drewery 		trace_me();
2938753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2939753e2922SBryan Drewery 
2940753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2941753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2942753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2943753e2922SBryan Drewery 		do {
2944753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2945753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2946753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2947753e2922SBryan Drewery 
2948753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2949753e2922SBryan Drewery 		exit(1);
2950753e2922SBryan Drewery 	}
2951753e2922SBryan Drewery 
2952753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2953753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2954753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2955753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2956753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2957753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2958753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
2959753e2922SBryan Drewery 
2960753e2922SBryan Drewery 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
2961753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2962753e2922SBryan Drewery 
2963753e2922SBryan Drewery 	/* The next wait() should report the SIGUSR1 was received. */
2964753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2965753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2966753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2967753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2968753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2969753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2970753e2922SBryan Drewery 
2971753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
2972753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2973753e2922SBryan Drewery 
2974753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
2975753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2976753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2977753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2978753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2979753e2922SBryan Drewery 
2980753e2922SBryan Drewery 	wpid = wait(&status);
2981753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2982753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2983753e2922SBryan Drewery }
2984753e2922SBryan Drewery 
2985753e2922SBryan Drewery /*
298682a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
298782a4538fSEric Badger  * a different signal that the new signal is routed to a thread
298899144520SEitan Adler  * that can accept it, and that the thread is awakened by the signal
298982a4538fSEric Badger  * in a timely manner.
299082a4538fSEric Badger  */
299182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
299282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
299382a4538fSEric Badger {
299482a4538fSEric Badger 	pid_t fpid, wpid;
299582a4538fSEric Badger 	int status, err;
299682a4538fSEric Badger 	pthread_t t;
299782a4538fSEric Badger 	sigset_t sigmask;
299882a4538fSEric Badger 	pthread_barrier_t barrier;
299982a4538fSEric Badger 
300082a4538fSEric Badger 	ATF_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
300182a4538fSEric Badger 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
300282a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
300382a4538fSEric Badger 
300482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
300582a4538fSEric Badger 	if (fpid == 0) {
300682a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, signal_thread, (void*)&barrier) == 0);
300782a4538fSEric Badger 
300882a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
300982a4538fSEric Badger 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
301082a4538fSEric Badger 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
301182a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
301282a4538fSEric Badger 
301382a4538fSEric Badger 		trace_me();
301482a4538fSEric Badger 
301582a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
301682a4538fSEric Badger 		pthread_barrier_wait(&barrier);
301782a4538fSEric Badger 
301882a4538fSEric Badger 		/*
301982a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
302082a4538fSEric Badger 		 * thread.
302182a4538fSEric Badger 		 */
302282a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
302382a4538fSEric Badger 
302482a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
302582a4538fSEric Badger 		pthread_barrier_wait(&barrier);
302682a4538fSEric Badger 
302782a4538fSEric Badger 		/*
302882a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
302982a4538fSEric Badger 		 * now.
303082a4538fSEric Badger 		 */
303182a4538fSEric Badger 		raise(SIGSTOP);
303282a4538fSEric Badger 
303382a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
303482a4538fSEric Badger 		do {
303582a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
303682a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
303782a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
303882a4538fSEric Badger 
303982a4538fSEric Badger 		/* Free the other thread from the barrier. */
304082a4538fSEric Badger 		pthread_barrier_wait(&barrier);
304182a4538fSEric Badger 
304282a4538fSEric Badger 		CHILD_REQUIRE(pthread_join(t, NULL) == 0);
304382a4538fSEric Badger 
304482a4538fSEric Badger 		exit(1);
304582a4538fSEric Badger 	}
304682a4538fSEric Badger 
304782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
304882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
304982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
305082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
305182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
305282a4538fSEric Badger 
305382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
305482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
305582a4538fSEric Badger 
305682a4538fSEric Badger 	/*
305782a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
305882a4538fSEric Badger 	 * in this case).
305982a4538fSEric Badger 	 */
306082a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
306182a4538fSEric Badger 
306282a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
306382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
306482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
306582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
306682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
306782a4538fSEric Badger 
306882a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
306982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
307082a4538fSEric Badger 
307182a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
307282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
307382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
307482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
307582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
307682a4538fSEric Badger 
307782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
307882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
307982a4538fSEric Badger 
308082a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
308182a4538fSEric Badger 
308282a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
308382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
308482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
308582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
308682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
308782a4538fSEric Badger 
308882a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
308982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
309082a4538fSEric Badger 
309182a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
309282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
309382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
309482a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
309582a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
309682a4538fSEric Badger 
309782a4538fSEric Badger 	wpid = wait(&status);
309882a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
309982a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
310082a4538fSEric Badger }
310182a4538fSEric Badger 
3102b38bd91fSEric Badger static void *
3103b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
3104b38bd91fSEric Badger {
3105b38bd91fSEric Badger 
3106b38bd91fSEric Badger 	raise(SIGSTOP);
3107b38bd91fSEric Badger 	return NULL;
3108b38bd91fSEric Badger }
3109b38bd91fSEric Badger 
3110b38bd91fSEric Badger static void *
3111b38bd91fSEric Badger sleep_thread(void *arg __unused)
3112b38bd91fSEric Badger {
3113b38bd91fSEric Badger 
3114b38bd91fSEric Badger 	sleep(60);
3115b38bd91fSEric Badger 	return NULL;
3116b38bd91fSEric Badger }
3117b38bd91fSEric Badger 
3118b38bd91fSEric Badger static void
3119b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
3120b38bd91fSEric Badger {
3121b38bd91fSEric Badger 	pid_t fpid, wpid;
3122b38bd91fSEric Badger 	int status, i;
3123b38bd91fSEric Badger 	cpuset_t setmask;
3124b38bd91fSEric Badger 	cpusetid_t setid;
3125b38bd91fSEric Badger 	pthread_t t;
3126b38bd91fSEric Badger 
3127b38bd91fSEric Badger 	/*
3128b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
3129b38bd91fSEric Badger 	 * that both child and grandchild have died.
3130b38bd91fSEric Badger 	 */
3131b38bd91fSEric Badger 	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
3132b38bd91fSEric Badger 
3133b38bd91fSEric Badger 	fpid = fork();
3134b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
3135b38bd91fSEric Badger 	if (fpid == 0) {
3136b38bd91fSEric Badger 		fpid = fork();
3137b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
3138b38bd91fSEric Badger 		if (fpid == 0) {
3139b38bd91fSEric Badger 			trace_me();
3140b38bd91fSEric Badger 
3141b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
3142b38bd91fSEric Badger 			CPU_ZERO(&setmask);
3143b38bd91fSEric Badger 			CPU_SET(0, &setmask);
3144b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset(&setid) == 0);
3145b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
3146b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
3147b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
3148b38bd91fSEric Badger 
3149b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
3150b38bd91fSEric Badger 				/*
3151b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
3152b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
3153b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
3154b38bd91fSEric Badger 				 * threads compete.
3155b38bd91fSEric Badger 				 */
3156b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3157b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
3158b38bd91fSEric Badger 				raise(SIGSTOP);
3159b38bd91fSEric Badger 			} else {
3160b38bd91fSEric Badger 				/*
3161b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
3162b38bd91fSEric Badger 				 * this thread. After creating the new thread,
3163b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
3164b38bd91fSEric Badger 				 * raise the SIGSTOP.
3165b38bd91fSEric Badger 				 */
3166b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3167b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
3168b38bd91fSEric Badger 				sleep(60);
3169b38bd91fSEric Badger 			}
3170b38bd91fSEric Badger 
3171b38bd91fSEric Badger 			exit(0);
3172b38bd91fSEric Badger 		}
3173b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
3174b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3175b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
3176b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3177b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3178b38bd91fSEric Badger 
3179b38bd91fSEric Badger 		CHILD_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3180b38bd91fSEric Badger 
3181b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
3182b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3183b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
3184b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3185b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3186b38bd91fSEric Badger 
3187b38bd91fSEric Badger 		/*
3188b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
3189b38bd91fSEric Badger 		 * should be killed.
3190b38bd91fSEric Badger 		 */
3191b38bd91fSEric Badger 		exit(0);
3192b38bd91fSEric Badger 	}
3193b38bd91fSEric Badger 
3194b38bd91fSEric Badger 	/*
3195b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
3196b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
3197b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
3198b38bd91fSEric Badger 	 * left dangling when its parent died.
3199b38bd91fSEric Badger 	 */
3200b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
3201b38bd91fSEric Badger 		wpid = wait(&status);
3202b38bd91fSEric Badger 		if (wpid == fpid)
3203b38bd91fSEric Badger 			ATF_REQUIRE(WIFEXITED(status) &&
3204b38bd91fSEric Badger 			    WEXITSTATUS(status) == 0);
3205b38bd91fSEric Badger 		else
3206b38bd91fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status) &&
3207b38bd91fSEric Badger 			    WTERMSIG(status) == SIGKILL);
3208b38bd91fSEric Badger 	}
3209b38bd91fSEric Badger }
3210b38bd91fSEric Badger 
3211b38bd91fSEric Badger /*
3212b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
3213b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
3214b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
3215b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
3216b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
3217b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
3218b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
3219b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
3220b38bd91fSEric Badger  * past, so make no assumption.
3221b38bd91fSEric Badger  */
32223cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
32233cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
32243cf56bb4SEnji Cooper {
32253cf56bb4SEnji Cooper 
32263cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
32273cf56bb4SEnji Cooper }
3228b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
3229b38bd91fSEric Badger {
3230b38bd91fSEric Badger 
3231b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
3232b38bd91fSEric Badger }
32333cf56bb4SEnji Cooper 
32343cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
32353cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
32363cf56bb4SEnji Cooper {
32373cf56bb4SEnji Cooper 
32383cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
32393cf56bb4SEnji Cooper }
3240b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
3241b38bd91fSEric Badger {
3242b38bd91fSEric Badger 
3243b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
3244b38bd91fSEric Badger }
3245b38bd91fSEric Badger 
3246b4d33259SEric Badger /*
3247b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
3248b4d33259SEric Badger  * is not modified.
3249b4d33259SEric Badger  */
3250b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
3251b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
3252b4d33259SEric Badger {
3253b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
3254b4d33259SEric Badger 	pid_t fpid, wpid;
3255b4d33259SEric Badger 	int status, event_mask, new_event_mask;
3256b4d33259SEric Badger 
3257b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
3258b4d33259SEric Badger 	if (fpid == 0) {
3259b4d33259SEric Badger 		trace_me();
3260b4d33259SEric Badger 		raise(SIGSTOP);
3261b4d33259SEric Badger 		exit(0);
3262b4d33259SEric Badger 	}
3263b4d33259SEric Badger 
3264b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
3265b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3266b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3267b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3268b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3269b4d33259SEric Badger 
3270b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
3271b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
3272b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
3273b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
3274b4d33259SEric Badger 
3275b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
3276b4d33259SEric Badger 	ATF_REQUIRE(kill(fpid, SIGKILL) == 0);
3277b4d33259SEric Badger 
3278b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
3279b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3280b4d33259SEric Badger 
3281b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
3282b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3283b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3284b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3285b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGKILL);
3286b4d33259SEric Badger 
3287b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3288b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3289b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGKILL);
3290b4d33259SEric Badger 
3291b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
3292b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3293b4d33259SEric Badger 
3294b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
3295b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3296b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3297b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3298b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3299b4d33259SEric Badger 
3300b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
3301b4d33259SEric Badger 	new_event_mask = 0;
3302b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
3303b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
3304b4d33259SEric Badger 	ATF_REQUIRE(event_mask == new_event_mask);
3305b4d33259SEric Badger 
3306b4d33259SEric Badger 	/* Continue the child to let it exit. */
3307b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3308b4d33259SEric Badger 
3309b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
3310b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3311b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
3312b4d33259SEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
3313b4d33259SEric Badger 
3314b4d33259SEric Badger 	wpid = wait(&status);
3315b4d33259SEric Badger 	ATF_REQUIRE(wpid == -1);
3316b4d33259SEric Badger 	ATF_REQUIRE(errno == ECHILD);
3317b4d33259SEric Badger }
3318b4d33259SEric Badger 
3319d74da94cSMark Johnston static void *
3320d74da94cSMark Johnston flock_thread(void *arg)
3321d74da94cSMark Johnston {
3322d74da94cSMark Johnston 	int fd;
3323d74da94cSMark Johnston 
3324d74da94cSMark Johnston 	fd = *(int *)arg;
3325d74da94cSMark Johnston 	(void)flock(fd, LOCK_EX);
3326d74da94cSMark Johnston 	(void)flock(fd, LOCK_UN);
3327d74da94cSMark Johnston 	return (NULL);
3328d74da94cSMark Johnston }
3329d74da94cSMark Johnston 
3330d74da94cSMark Johnston /*
3331d74da94cSMark Johnston  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
3332d74da94cSMark Johnston  * We rely on the fact that the lockf implementation sets SBDRY before blocking
3333d74da94cSMark Johnston  * on a lock. This is a regression test for r318191.
3334d74da94cSMark Johnston  */
3335d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
3336d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
3337d74da94cSMark Johnston {
3338d74da94cSMark Johnston 	pthread_barrier_t barrier;
3339d74da94cSMark Johnston 	pthread_barrierattr_t battr;
3340d74da94cSMark Johnston 	char tmpfile[64];
3341d74da94cSMark Johnston 	pid_t child, wpid;
3342d74da94cSMark Johnston 	int error, fd, i, status;
3343d74da94cSMark Johnston 
3344d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_init(&battr) == 0);
3345d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
3346d74da94cSMark Johnston 	    PTHREAD_PROCESS_SHARED) == 0);
3347d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrier_init(&barrier, &battr, 2) == 0);
3348d74da94cSMark Johnston 
3349d74da94cSMark Johnston 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
3350d74da94cSMark Johnston 	fd = mkstemp(tmpfile);
3351d74da94cSMark Johnston 	ATF_REQUIRE(fd >= 0);
3352d74da94cSMark Johnston 
3353d74da94cSMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
3354d74da94cSMark Johnston 	if (child == 0) {
3355d74da94cSMark Johnston 		pthread_t t[2];
335696437391SBryan Drewery 		int cfd;
3357d74da94cSMark Johnston 
3358d74da94cSMark Johnston 		error = pthread_barrier_wait(&barrier);
3359d74da94cSMark Johnston 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
3360d74da94cSMark Johnston 			_exit(1);
3361d74da94cSMark Johnston 
3362d74da94cSMark Johnston 		cfd = open(tmpfile, O_RDONLY);
3363d74da94cSMark Johnston 		if (cfd < 0)
3364d74da94cSMark Johnston 			_exit(1);
3365d74da94cSMark Johnston 
3366d74da94cSMark Johnston 		/*
3367d74da94cSMark Johnston 		 * We want at least two threads blocked on the file lock since
3368d74da94cSMark Johnston 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
3369d74da94cSMark Johnston 		 * sleep.
3370d74da94cSMark Johnston 		 */
3371d74da94cSMark Johnston 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
3372d74da94cSMark Johnston 			_exit(1);
3373d74da94cSMark Johnston 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
3374d74da94cSMark Johnston 			_exit(1);
3375d74da94cSMark Johnston 		if (pthread_join(t[0], NULL) != 0)
3376d74da94cSMark Johnston 			_exit(1);
3377d74da94cSMark Johnston 		if (pthread_join(t[1], NULL) != 0)
3378d74da94cSMark Johnston 			_exit(1);
3379d74da94cSMark Johnston 		_exit(0);
3380d74da94cSMark Johnston 	}
3381d74da94cSMark Johnston 
3382d74da94cSMark Johnston 	ATF_REQUIRE(flock(fd, LOCK_EX) == 0);
3383d74da94cSMark Johnston 
3384d74da94cSMark Johnston 	error = pthread_barrier_wait(&barrier);
3385d74da94cSMark Johnston 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
3386d74da94cSMark Johnston 
3387d74da94cSMark Johnston 	/*
3388d74da94cSMark Johnston 	 * Give the child some time to block. Is there a better way to do this?
3389d74da94cSMark Johnston 	 */
3390d74da94cSMark Johnston 	sleep(1);
3391d74da94cSMark Johnston 
3392d74da94cSMark Johnston 	/*
3393d74da94cSMark Johnston 	 * Attach and give the child 3 seconds to stop.
3394d74da94cSMark Johnston 	 */
3395d74da94cSMark Johnston 	ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0);
3396d74da94cSMark Johnston 	for (i = 0; i < 3; i++) {
3397d74da94cSMark Johnston 		wpid = waitpid(child, &status, WNOHANG);
3398d74da94cSMark Johnston 		if (wpid == child && WIFSTOPPED(status) &&
3399d74da94cSMark Johnston 		    WSTOPSIG(status) == SIGSTOP)
3400d74da94cSMark Johnston 			break;
3401d74da94cSMark Johnston 		sleep(1);
3402d74da94cSMark Johnston 	}
3403d74da94cSMark Johnston 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
3404d74da94cSMark Johnston 
3405d74da94cSMark Johnston 	ATF_REQUIRE(ptrace(PT_DETACH, child, NULL, 0) == 0);
3406d74da94cSMark Johnston 
3407d74da94cSMark Johnston 	ATF_REQUIRE(flock(fd, LOCK_UN) == 0);
3408d74da94cSMark Johnston 	ATF_REQUIRE(unlink(tmpfile) == 0);
3409d74da94cSMark Johnston 	ATF_REQUIRE(close(fd) == 0);
3410d74da94cSMark Johnston }
3411d74da94cSMark Johnston 
341254cfb29eSJohn Baldwin static void
341354cfb29eSJohn Baldwin sigusr1_step_handler(int sig)
341454cfb29eSJohn Baldwin {
341554cfb29eSJohn Baldwin 
341654cfb29eSJohn Baldwin 	CHILD_REQUIRE(sig == SIGUSR1);
341754cfb29eSJohn Baldwin 	raise(SIGABRT);
341854cfb29eSJohn Baldwin }
341954cfb29eSJohn Baldwin 
342054cfb29eSJohn Baldwin /*
342154cfb29eSJohn Baldwin  * Verify that PT_STEP with a signal invokes the signal before
342254cfb29eSJohn Baldwin  * stepping the next instruction (and that the next instruction is
342354cfb29eSJohn Baldwin  * stepped correctly).
342454cfb29eSJohn Baldwin  */
342554cfb29eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal);
342654cfb29eSJohn Baldwin ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
342754cfb29eSJohn Baldwin {
342854cfb29eSJohn Baldwin 	struct ptrace_lwpinfo pl;
342954cfb29eSJohn Baldwin 	pid_t fpid, wpid;
343054cfb29eSJohn Baldwin 	int status;
343154cfb29eSJohn Baldwin 
343254cfb29eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
343354cfb29eSJohn Baldwin 	if (fpid == 0) {
343454cfb29eSJohn Baldwin 		trace_me();
343554cfb29eSJohn Baldwin 		signal(SIGUSR1, sigusr1_step_handler);
343654cfb29eSJohn Baldwin 		raise(SIGABRT);
343754cfb29eSJohn Baldwin 		exit(1);
343854cfb29eSJohn Baldwin 	}
343954cfb29eSJohn Baldwin 
344054cfb29eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
344154cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
344254cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
344354cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
344454cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
344554cfb29eSJohn Baldwin 
344654cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
344754cfb29eSJohn Baldwin 
344854cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
344954cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
345054cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
345154cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
345254cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
345354cfb29eSJohn Baldwin 
345454cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
345554cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
345654cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
345754cfb29eSJohn Baldwin 
345854cfb29eSJohn Baldwin 	/* Step the child process inserting SIGUSR1. */
345954cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1) == 0);
346054cfb29eSJohn Baldwin 
346154cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the signal handler. */
346254cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
346354cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
346454cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
346554cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
346654cfb29eSJohn Baldwin 
346754cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
346854cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
346954cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
347054cfb29eSJohn Baldwin 
347154cfb29eSJohn Baldwin 	/* Continue the child process discarding the signal. */
347254cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
347354cfb29eSJohn Baldwin 
347454cfb29eSJohn Baldwin 	/* The next stop should report a trace trap from PT_STEP. */
347554cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
347654cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
347754cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
347854cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
347954cfb29eSJohn Baldwin 
348054cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
348154cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
348254cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
348354cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE);
348454cfb29eSJohn Baldwin 
348554cfb29eSJohn Baldwin 	/* Continue the child to let it exit. */
348654cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
348754cfb29eSJohn Baldwin 
348854cfb29eSJohn Baldwin 	/* The last event should be for the child process's exit. */
348954cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
349054cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
349154cfb29eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
349254cfb29eSJohn Baldwin 
349354cfb29eSJohn Baldwin 	wpid = wait(&status);
349454cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
349554cfb29eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
349654cfb29eSJohn Baldwin }
349754cfb29eSJohn Baldwin 
3498643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3499643ce7deSJohn Baldwin /*
3500643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported
3501643ce7deSJohn Baldwin  * for a breakpoint trap.
3502643ce7deSJohn Baldwin  */
3503643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo);
3504643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__breakpoint_siginfo, tc)
3505643ce7deSJohn Baldwin {
3506643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3507643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3508643ce7deSJohn Baldwin 	int status;
3509643ce7deSJohn Baldwin 
3510643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3511643ce7deSJohn Baldwin 	if (fpid == 0) {
3512643ce7deSJohn Baldwin 		trace_me();
3513643ce7deSJohn Baldwin 		breakpoint();
3514643ce7deSJohn Baldwin 		exit(1);
3515643ce7deSJohn Baldwin 	}
3516643ce7deSJohn Baldwin 
3517643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3518643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3519643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3520643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3521643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3522643ce7deSJohn Baldwin 
3523643ce7deSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
3524643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3525643ce7deSJohn Baldwin 
3526643ce7deSJohn Baldwin 	/* The second wait() should report hitting the breakpoint. */
3527643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3528643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3529643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3530643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3531643ce7deSJohn Baldwin 
3532643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3533643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3534643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
3535643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_BRKPT);
3536643ce7deSJohn Baldwin 
3537643ce7deSJohn Baldwin 	/* Kill the child process. */
3538643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
3539643ce7deSJohn Baldwin 
3540643ce7deSJohn Baldwin 	/* The last wait() should report the SIGKILL. */
3541643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3542643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3543643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSIGNALED(status));
3544643ce7deSJohn Baldwin 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
3545643ce7deSJohn Baldwin 
3546643ce7deSJohn Baldwin 	wpid = wait(&status);
3547643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3548643ce7deSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3549643ce7deSJohn Baldwin }
3550643ce7deSJohn Baldwin #endif /* HAVE_BREAKPOINT */
3551643ce7deSJohn Baldwin 
3552643ce7deSJohn Baldwin /*
3553643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_TRACE code is reported
3554643ce7deSJohn Baldwin  * for a single-step trap from PT_STEP.
3555643ce7deSJohn Baldwin  */
3556643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo);
3557643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__step_siginfo, tc)
3558643ce7deSJohn Baldwin {
3559643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3560643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3561643ce7deSJohn Baldwin 	int status;
3562643ce7deSJohn Baldwin 
3563643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3564643ce7deSJohn Baldwin 	if (fpid == 0) {
3565643ce7deSJohn Baldwin 		trace_me();
3566643ce7deSJohn Baldwin 		exit(1);
3567643ce7deSJohn Baldwin 	}
3568643ce7deSJohn Baldwin 
3569643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3570643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3571643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3572643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3573643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3574643ce7deSJohn Baldwin 
3575643ce7deSJohn Baldwin 	/* Step the child ignoring the SIGSTOP. */
3576643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, 0) == 0);
3577643ce7deSJohn Baldwin 
3578643ce7deSJohn Baldwin 	/* The second wait() should report a single-step trap. */
3579643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3580643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3581643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3582643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3583643ce7deSJohn Baldwin 
3584643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3585643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3586643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
3587643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE);
3588643ce7deSJohn Baldwin 
3589643ce7deSJohn Baldwin 	/* Continue the child process. */
3590643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3591643ce7deSJohn Baldwin 
3592643ce7deSJohn Baldwin 	/* The last event should be for the child process's exit. */
3593643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3594643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3595643ce7deSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3596643ce7deSJohn Baldwin 
3597643ce7deSJohn Baldwin 	wpid = wait(&status);
3598643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3599643ce7deSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3600643ce7deSJohn Baldwin }
3601643ce7deSJohn Baldwin 
3602403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3603e012fe34SJohn Baldwin static void *
3604e0a40f30SJohn Baldwin continue_thread(void *arg __unused)
3605e012fe34SJohn Baldwin {
3606e012fe34SJohn Baldwin 	breakpoint();
3607e012fe34SJohn Baldwin 	return (NULL);
3608e012fe34SJohn Baldwin }
3609e012fe34SJohn Baldwin 
3610e012fe34SJohn Baldwin static __dead2 void
3611e012fe34SJohn Baldwin continue_thread_main(void)
3612e012fe34SJohn Baldwin {
3613e012fe34SJohn Baldwin 	pthread_t threads[2];
3614e012fe34SJohn Baldwin 
3615e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
3616e012fe34SJohn Baldwin 	    NULL) == 0);
3617e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
3618e012fe34SJohn Baldwin 	    NULL) == 0);
3619e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_join(threads[0], NULL) == 0);
3620e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_join(threads[1], NULL) == 0);
3621e012fe34SJohn Baldwin 	exit(1);
3622e012fe34SJohn Baldwin }
3623e012fe34SJohn Baldwin 
3624e012fe34SJohn Baldwin /*
3625e012fe34SJohn Baldwin  * Ensure that PT_CONTINUE clears the status of the thread that
3626e012fe34SJohn Baldwin  * triggered the stop even if a different thread's LWP was passed to
3627e012fe34SJohn Baldwin  * PT_CONTINUE.
3628e012fe34SJohn Baldwin  */
3629e012fe34SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
3630e012fe34SJohn Baldwin ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
3631e012fe34SJohn Baldwin {
3632e012fe34SJohn Baldwin 	struct ptrace_lwpinfo pl;
3633e012fe34SJohn Baldwin 	pid_t fpid, wpid;
3634e012fe34SJohn Baldwin 	lwpid_t lwps[2];
3635e012fe34SJohn Baldwin 	bool hit_break[2];
3636403e331dSJohn Baldwin 	struct reg reg;
3637e012fe34SJohn Baldwin 	int i, j, status;
3638e012fe34SJohn Baldwin 
3639e012fe34SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3640e012fe34SJohn Baldwin 	if (fpid == 0) {
3641e012fe34SJohn Baldwin 		trace_me();
3642e012fe34SJohn Baldwin 		continue_thread_main();
3643e012fe34SJohn Baldwin 	}
3644e012fe34SJohn Baldwin 
3645e012fe34SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3646e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3647e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3648e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3649e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3650e012fe34SJohn Baldwin 
3651e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3652e012fe34SJohn Baldwin 	    sizeof(pl)) != -1);
3653e012fe34SJohn Baldwin 
3654e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
3655e012fe34SJohn Baldwin 
3656e012fe34SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
3657e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3658e012fe34SJohn Baldwin 
3659e012fe34SJohn Baldwin 	/* One of the new threads should report it's birth. */
3660e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3661e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3662e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3663e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3664e012fe34SJohn Baldwin 
3665e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3666e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
3667e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3668e012fe34SJohn Baldwin 	lwps[0] = pl.pl_lwpid;
3669e012fe34SJohn Baldwin 
3670e012fe34SJohn Baldwin 	/*
3671e012fe34SJohn Baldwin 	 * Suspend this thread to ensure both threads are alive before
3672e012fe34SJohn Baldwin 	 * hitting the breakpoint.
3673e012fe34SJohn Baldwin 	 */
3674e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
3675e012fe34SJohn Baldwin 
3676e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3677e012fe34SJohn Baldwin 
3678e012fe34SJohn Baldwin 	/* Second thread should report it's birth. */
3679e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3680e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3681e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3682e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3683e012fe34SJohn Baldwin 
3684e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3685e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
3686e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3687e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
3688e012fe34SJohn Baldwin 	lwps[1] = pl.pl_lwpid;
3689e012fe34SJohn Baldwin 
3690e012fe34SJohn Baldwin 	/* Resume both threads waiting for breakpoint events. */
3691e012fe34SJohn Baldwin 	hit_break[0] = hit_break[1] = false;
3692e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
3693e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3694e012fe34SJohn Baldwin 
3695e012fe34SJohn Baldwin 	/* One thread should report a breakpoint. */
3696e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3697e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3698e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3699e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3700e012fe34SJohn Baldwin 
3701e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3702e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3703e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
3704e012fe34SJohn Baldwin 	    pl.pl_siginfo.si_code == TRAP_BRKPT);
3705e012fe34SJohn Baldwin 	if (pl.pl_lwpid == lwps[0])
3706e012fe34SJohn Baldwin 		i = 0;
3707e012fe34SJohn Baldwin 	else
3708e012fe34SJohn Baldwin 		i = 1;
3709e012fe34SJohn Baldwin 	hit_break[i] = true;
3710403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3711403e331dSJohn Baldwin 	SKIP_BREAK(&reg);
3712403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3713e012fe34SJohn Baldwin 
3714e012fe34SJohn Baldwin 	/*
3715e012fe34SJohn Baldwin 	 * Resume both threads but pass the other thread's LWPID to
3716e012fe34SJohn Baldwin 	 * PT_CONTINUE.
3717e012fe34SJohn Baldwin 	 */
3718e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0) == 0);
3719e012fe34SJohn Baldwin 
3720e012fe34SJohn Baldwin 	/*
3721e012fe34SJohn Baldwin 	 * Will now get two thread exit events and one more breakpoint
3722e012fe34SJohn Baldwin 	 * event.
3723e012fe34SJohn Baldwin 	 */
3724e012fe34SJohn Baldwin 	for (j = 0; j < 3; j++) {
3725e012fe34SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
3726e012fe34SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
3727e012fe34SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
3728e012fe34SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3729e012fe34SJohn Baldwin 
3730e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3731e012fe34SJohn Baldwin 		    sizeof(pl)) != -1);
3732e012fe34SJohn Baldwin 
3733e012fe34SJohn Baldwin 		if (pl.pl_lwpid == lwps[0])
3734e012fe34SJohn Baldwin 			i = 0;
3735e012fe34SJohn Baldwin 		else
3736e012fe34SJohn Baldwin 			i = 1;
3737e012fe34SJohn Baldwin 
3738e012fe34SJohn Baldwin 		ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
3739e012fe34SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_EXITED) {
3740e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(hit_break[i],
3741e012fe34SJohn Baldwin 			    "exited thread did not report breakpoint");
3742e012fe34SJohn Baldwin 			lwps[i] = 0;
3743e012fe34SJohn Baldwin 		} else {
3744e012fe34SJohn Baldwin 			ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3745e012fe34SJohn Baldwin 			ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
3746e012fe34SJohn Baldwin 			    pl.pl_siginfo.si_code == TRAP_BRKPT);
3747e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(!hit_break[i],
3748e012fe34SJohn Baldwin 			    "double breakpoint event");
3749e012fe34SJohn Baldwin 			hit_break[i] = true;
3750403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
3751403e331dSJohn Baldwin 			    0) != -1);
3752403e331dSJohn Baldwin 			SKIP_BREAK(&reg);
3753403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
3754403e331dSJohn Baldwin 			    0) != -1);
3755e012fe34SJohn Baldwin 		}
3756e012fe34SJohn Baldwin 
3757e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3758e012fe34SJohn Baldwin 	}
3759e012fe34SJohn Baldwin 
3760e012fe34SJohn Baldwin 	/* Both threads should have exited. */
3761e012fe34SJohn Baldwin 	ATF_REQUIRE(lwps[0] == 0);
3762e012fe34SJohn Baldwin 	ATF_REQUIRE(lwps[1] == 0);
3763e012fe34SJohn Baldwin 
3764e012fe34SJohn Baldwin 	/* The last event should be for the child process's exit. */
3765e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3766e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3767e012fe34SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3768e012fe34SJohn Baldwin 
3769e012fe34SJohn Baldwin 	wpid = wait(&status);
3770e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3771e012fe34SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3772e012fe34SJohn Baldwin }
3773e012fe34SJohn Baldwin #endif
3774e012fe34SJohn Baldwin 
3775c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
3776c209e3e2SJohn Baldwin {
3777c209e3e2SJohn Baldwin 
3778c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
3779c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
378057c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
378157c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
378298685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
378398685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
378498685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
378598685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
378698685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
378798685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
378898685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
378998685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
3790368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
3791189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
3792189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
3793189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
37945fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
37955fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
37963340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
37978d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
37988d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
37998d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
3800fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
3801fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
3802403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
380382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
3804e2ebfbbfSEric Badger #endif
380582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
380682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
380782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
380882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
380982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
381082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
381182a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
381282a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
381382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
3814753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
381582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
381682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
381782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
381882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
3819753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
3820753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
382182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
3822b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
3823b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
3824b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
3825d74da94cSMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
382654cfb29eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
3827643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3828643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo);
3829643ce7deSJohn Baldwin #endif
3830643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__step_siginfo);
3831403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3832e012fe34SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
3833e012fe34SJohn Baldwin #endif
3834c209e3e2SJohn Baldwin 
3835c209e3e2SJohn Baldwin 	return (atf_no_error());
3836c209e3e2SJohn Baldwin }
3837