xref: /freebsd/tests/sys/kern/ptrace_test.c (revision fd631bcd95ada78ecd2150b81959df46b763c716)
1c209e3e2SJohn Baldwin /*-
2c209e3e2SJohn Baldwin  * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
3c209e3e2SJohn Baldwin  *
4c209e3e2SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
5c209e3e2SJohn Baldwin  * modification, are permitted provided that the following conditions
6c209e3e2SJohn Baldwin  * are met:
7c209e3e2SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
8c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
9c209e3e2SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
10c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
11c209e3e2SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
12c209e3e2SJohn Baldwin  *
13c209e3e2SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14c209e3e2SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15c209e3e2SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16c209e3e2SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17c209e3e2SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18c209e3e2SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19c209e3e2SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20c209e3e2SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21c209e3e2SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22c209e3e2SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23c209e3e2SJohn Baldwin  * SUCH DAMAGE.
24c209e3e2SJohn Baldwin  */
25c209e3e2SJohn Baldwin 
26c209e3e2SJohn Baldwin #include <sys/cdefs.h>
27c209e3e2SJohn Baldwin __FBSDID("$FreeBSD$");
28c209e3e2SJohn Baldwin 
29c209e3e2SJohn Baldwin #include <sys/types.h>
3082a4538fSEric Badger #include <sys/cpuset.h>
3182a4538fSEric Badger #include <sys/event.h>
32d74da94cSMark Johnston #include <sys/file.h>
3382a4538fSEric Badger #include <sys/time.h>
34b38bd91fSEric Badger #include <sys/procctl.h>
35*fd631bcdSMariusz Zaborski #include <sys/procdesc.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  */
57a9c91abdSJohn Baldwin #if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) ||	\
58a9c91abdSJohn Baldwin     defined(__i386__) || defined(__mips__) || defined(__riscv) ||	\
59a9c91abdSJohn 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
67a9c91abdSJohn Baldwin #if defined(__aarch64__)
68a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->elr += 4)
69a9c91abdSJohn Baldwin #elif defined(__amd64__) || defined(__i386__)
70403e331dSJohn Baldwin #define	SKIP_BREAK(reg)
71a9c91abdSJohn Baldwin #elif defined(__arm__)
72a9c91abdSJohn 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 
2629777e354SLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool(tc, "ci"))
263c2dc497aSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/239399");
264c2dc497aSLi-Wen Hsu 
26557c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
26657c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
26757c74f5bSJohn Baldwin 
26857c74f5bSJohn Baldwin 	if (child == 0) {
26957c74f5bSJohn Baldwin 		/* Child process. */
27057c74f5bSJohn Baldwin 		close(cpipe[0]);
27157c74f5bSJohn Baldwin 
27257c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
273dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
27457c74f5bSJohn Baldwin 
275b98cb919SJohn Baldwin 		_exit(1);
27657c74f5bSJohn Baldwin 	}
27757c74f5bSJohn Baldwin 	close(cpipe[1]);
27857c74f5bSJohn Baldwin 
27957c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
28057c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
28157c74f5bSJohn Baldwin 
28257c74f5bSJohn Baldwin 	if (debugger == 0) {
28357c74f5bSJohn Baldwin 		/* Debugger process. */
28457c74f5bSJohn Baldwin 		close(dpipe[0]);
28557c74f5bSJohn Baldwin 
286dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
28757c74f5bSJohn Baldwin 
28857c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
289dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
290dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
291dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
29257c74f5bSJohn Baldwin 
293dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
29457c74f5bSJohn Baldwin 
29557c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
296dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
29757c74f5bSJohn Baldwin 
29857c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
299dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0);
30057c74f5bSJohn Baldwin 
30157c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
302dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
303dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
304dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
30557c74f5bSJohn Baldwin 
306b98cb919SJohn Baldwin 		_exit(0);
30757c74f5bSJohn Baldwin 	}
30857c74f5bSJohn Baldwin 	close(dpipe[1]);
30957c74f5bSJohn Baldwin 
31057c74f5bSJohn Baldwin 	/* Parent process. */
31157c74f5bSJohn Baldwin 
31257c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
31357c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
31457c74f5bSJohn Baldwin 
31557c74f5bSJohn Baldwin 	/* Release the child. */
31657c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
31757c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
31857c74f5bSJohn Baldwin 	close(cpipe[0]);
31957c74f5bSJohn Baldwin 
32098685dc8SJohn Baldwin 	wait_for_zombie(child);
32157c74f5bSJohn Baldwin 
32257c74f5bSJohn Baldwin 	/*
3232f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3242f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3252f021998SJohn Baldwin 	 * until the debugger sees the exit.
32657c74f5bSJohn Baldwin 	 */
32757c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
32857c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
32957c74f5bSJohn Baldwin 
33057c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
33157c74f5bSJohn Baldwin 	close(dpipe[0]);
33257c74f5bSJohn Baldwin 
33357c74f5bSJohn Baldwin 	/* Wait for the debugger. */
33457c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
33557c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
33657c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
33757c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
33857c74f5bSJohn Baldwin 
33957c74f5bSJohn Baldwin 	/* The child process should now be ready. */
34057c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
34157c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
34257c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
34357c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
34457c74f5bSJohn Baldwin }
34557c74f5bSJohn Baldwin 
34657c74f5bSJohn Baldwin /*
34757c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
34857c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
34957c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
35057c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
35157c74f5bSJohn Baldwin  */
35257c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
35357c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
35457c74f5bSJohn Baldwin {
35557c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
35657c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
35757c74f5bSJohn Baldwin 	char c;
35857c74f5bSJohn Baldwin 
35957c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
36057c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
36157c74f5bSJohn Baldwin 
36257c74f5bSJohn Baldwin 	if (child == 0) {
36357c74f5bSJohn Baldwin 		/* Child process. */
36457c74f5bSJohn Baldwin 		close(cpipe[0]);
36557c74f5bSJohn Baldwin 
36657c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
367dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
36857c74f5bSJohn Baldwin 
369b98cb919SJohn Baldwin 		_exit(1);
37057c74f5bSJohn Baldwin 	}
37157c74f5bSJohn Baldwin 	close(cpipe[1]);
37257c74f5bSJohn Baldwin 
37357c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
37457c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
37557c74f5bSJohn Baldwin 
37657c74f5bSJohn Baldwin 	if (debugger == 0) {
37757c74f5bSJohn Baldwin 		/* Debugger parent. */
37857c74f5bSJohn Baldwin 
37957c74f5bSJohn Baldwin 		/*
38057c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
38157c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
38257c74f5bSJohn Baldwin 		 */
383dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
38457c74f5bSJohn Baldwin 		if (fpid != 0)
385b98cb919SJohn Baldwin 			_exit(2);
38657c74f5bSJohn Baldwin 
38757c74f5bSJohn Baldwin 		/* Debugger process. */
38857c74f5bSJohn Baldwin 		close(dpipe[0]);
38957c74f5bSJohn Baldwin 
390dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
39157c74f5bSJohn Baldwin 
39257c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
393dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
394dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
395dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
39657c74f5bSJohn Baldwin 
397dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
39857c74f5bSJohn Baldwin 
39957c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
400dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
40157c74f5bSJohn Baldwin 
40257c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
403dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c));
40457c74f5bSJohn Baldwin 
40557c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
406dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
407dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
408dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
40957c74f5bSJohn Baldwin 
410b98cb919SJohn Baldwin 		_exit(0);
41157c74f5bSJohn Baldwin 	}
412eddb85c6SJohn Baldwin 	close(dpipe[1]);
41357c74f5bSJohn Baldwin 
41457c74f5bSJohn Baldwin 	/* Parent process. */
41557c74f5bSJohn Baldwin 
41657c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
41757c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
41857c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
41957c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
42057c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
42157c74f5bSJohn Baldwin 
42257c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
42357c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
42457c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
42557c74f5bSJohn Baldwin 
42657c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
42757c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
42857c74f5bSJohn Baldwin 
42957c74f5bSJohn Baldwin 	/* Release the child. */
43057c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
43157c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
43257c74f5bSJohn Baldwin 	close(cpipe[0]);
43357c74f5bSJohn Baldwin 
43498685dc8SJohn Baldwin 	wait_for_zombie(child);
43557c74f5bSJohn Baldwin 
43657c74f5bSJohn Baldwin 	/*
4372f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
4382f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
4392f021998SJohn Baldwin 	 * until the debugger sees the exit.
44057c74f5bSJohn Baldwin 	 */
44157c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
44257c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
44357c74f5bSJohn Baldwin 
44457c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
445eddb85c6SJohn Baldwin 	ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c));
44657c74f5bSJohn Baldwin 
44757c74f5bSJohn Baldwin 	/* Wait for the debugger. */
448eddb85c6SJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0);
449eddb85c6SJohn Baldwin 	close(dpipe[0]);
45057c74f5bSJohn Baldwin 
45157c74f5bSJohn Baldwin 	/* The child process should now be ready. */
45257c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
45357c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
45457c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
45557c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
45657c74f5bSJohn Baldwin }
45757c74f5bSJohn Baldwin 
45898685dc8SJohn Baldwin /*
459128c9bc0SMark Johnston  * Make sure that we can collect the exit status of an orphaned process.
460128c9bc0SMark Johnston  */
461128c9bc0SMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
462128c9bc0SMark Johnston ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
463128c9bc0SMark Johnston {
464128c9bc0SMark Johnston 	ssize_t n;
465128c9bc0SMark Johnston 	int cpipe1[2], cpipe2[2], gcpipe[2], status;
466128c9bc0SMark Johnston 	pid_t child, gchild;
467128c9bc0SMark Johnston 
468128c9bc0SMark Johnston 	ATF_REQUIRE(pipe(cpipe1) == 0);
469128c9bc0SMark Johnston 	ATF_REQUIRE(pipe(cpipe2) == 0);
470128c9bc0SMark Johnston 	ATF_REQUIRE(pipe(gcpipe) == 0);
471128c9bc0SMark Johnston 
472128c9bc0SMark Johnston 	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
473128c9bc0SMark Johnston 
474128c9bc0SMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
475128c9bc0SMark Johnston 	if (child == 0) {
476128c9bc0SMark Johnston 		CHILD_REQUIRE((gchild = fork()) != -1);
477128c9bc0SMark Johnston 		if (gchild == 0) {
478128c9bc0SMark Johnston 			status = 1;
479128c9bc0SMark Johnston 			do {
480128c9bc0SMark Johnston 				n = read(gcpipe[0], &status, sizeof(status));
481128c9bc0SMark Johnston 			} while (n == -1 && errno == EINTR);
482128c9bc0SMark Johnston 			_exit(status);
483128c9bc0SMark Johnston 		}
484128c9bc0SMark Johnston 
485128c9bc0SMark Johnston 		CHILD_REQUIRE(write(cpipe1[1], &gchild, sizeof(gchild)) ==
486128c9bc0SMark Johnston 		    sizeof(gchild));
487128c9bc0SMark Johnston 		CHILD_REQUIRE(read(cpipe2[0], &status, sizeof(status)) ==
488128c9bc0SMark Johnston 		    sizeof(status));
489128c9bc0SMark Johnston 		_exit(status);
490128c9bc0SMark Johnston 	}
491128c9bc0SMark Johnston 
492128c9bc0SMark Johnston 	ATF_REQUIRE(read(cpipe1[0], &gchild, sizeof(gchild)) == sizeof(gchild));
493128c9bc0SMark Johnston 
494128c9bc0SMark Johnston 	ATF_REQUIRE(ptrace(PT_ATTACH, gchild, NULL, 0) == 0);
495128c9bc0SMark Johnston 
496128c9bc0SMark Johnston 	status = 0;
497128c9bc0SMark Johnston 	ATF_REQUIRE(write(cpipe2[1], &status, sizeof(status)) ==
498128c9bc0SMark Johnston 	    sizeof(status));
499128c9bc0SMark Johnston 	ATF_REQUIRE(waitpid(child, &status, 0) == child);
500128c9bc0SMark Johnston 	ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
501128c9bc0SMark Johnston 
502128c9bc0SMark Johnston 	status = 0;
503128c9bc0SMark Johnston 	ATF_REQUIRE(write(gcpipe[1], &status, sizeof(status)) ==
504128c9bc0SMark Johnston 	    sizeof(status));
505128c9bc0SMark Johnston 	ATF_REQUIRE(waitpid(gchild, &status, 0) == gchild);
506128c9bc0SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
507128c9bc0SMark Johnston 	ATF_REQUIRE(ptrace(PT_DETACH, gchild, (caddr_t)1, 0) == 0);
508128c9bc0SMark Johnston 	ATF_REQUIRE(waitpid(gchild, &status, 0) == gchild);
509128c9bc0SMark Johnston 	ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
510128c9bc0SMark Johnston 
511128c9bc0SMark Johnston 	ATF_REQUIRE(close(cpipe1[0]) == 0);
512128c9bc0SMark Johnston 	ATF_REQUIRE(close(cpipe1[1]) == 0);
513128c9bc0SMark Johnston 	ATF_REQUIRE(close(cpipe2[0]) == 0);
514128c9bc0SMark Johnston 	ATF_REQUIRE(close(cpipe2[1]) == 0);
515128c9bc0SMark Johnston 	ATF_REQUIRE(close(gcpipe[0]) == 0);
516128c9bc0SMark Johnston 	ATF_REQUIRE(close(gcpipe[1]) == 0);
517128c9bc0SMark Johnston }
518128c9bc0SMark Johnston 
519128c9bc0SMark Johnston /*
52098685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
52198685dc8SJohn Baldwin  * debugger is attached to it.
52298685dc8SJohn Baldwin  */
52398685dc8SJohn Baldwin static __dead2 void
524189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
52598685dc8SJohn Baldwin {
52698685dc8SJohn Baldwin 	pid_t fpid, wpid;
52798685dc8SJohn Baldwin 	int status;
52898685dc8SJohn Baldwin 
529189ac973SJohn Baldwin 	if (use_vfork)
530189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
531189ac973SJohn Baldwin 	else
53298685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
53398685dc8SJohn Baldwin 
53498685dc8SJohn Baldwin 	if (fpid == 0)
53598685dc8SJohn Baldwin 		/* Child */
536b98cb919SJohn Baldwin 		_exit(2);
53798685dc8SJohn Baldwin 
53898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
53998685dc8SJohn Baldwin 	CHILD_REQUIRE(wpid == fpid);
54098685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
54198685dc8SJohn Baldwin 	CHILD_REQUIRE(WEXITSTATUS(status) == 2);
54298685dc8SJohn Baldwin 
543b98cb919SJohn Baldwin 	_exit(1);
54498685dc8SJohn Baldwin }
54598685dc8SJohn Baldwin 
54698685dc8SJohn Baldwin /*
54798685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
54898685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
54998685dc8SJohn Baldwin  * child process.
55098685dc8SJohn Baldwin  */
55198685dc8SJohn Baldwin static pid_t
552189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
55398685dc8SJohn Baldwin {
55498685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
55598685dc8SJohn Baldwin 	bool fork_reported[2];
55698685dc8SJohn Baldwin 	pid_t child, wpid;
55798685dc8SJohn Baldwin 	int i, status;
55898685dc8SJohn Baldwin 
55998685dc8SJohn Baldwin 	fork_reported[0] = false;
56098685dc8SJohn Baldwin 	fork_reported[1] = false;
56198685dc8SJohn Baldwin 	child = -1;
56298685dc8SJohn Baldwin 
56398685dc8SJohn Baldwin 	/*
56498685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
56598685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
56698685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
56798685dc8SJohn Baldwin 	 */
56898685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
56998685dc8SJohn Baldwin 		wpid = wait(&status);
57098685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
57198685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
57298685dc8SJohn Baldwin 
57398685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
57498685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
57598685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
57698685dc8SJohn Baldwin 		    0);
57798685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
57898685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
57998685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
58098685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
58198685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
58298685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
58398685dc8SJohn Baldwin 			if (child == -1)
58498685dc8SJohn Baldwin 				child = wpid;
58598685dc8SJohn Baldwin 			else
58698685dc8SJohn Baldwin 				ATF_REQUIRE(child == wpid);
587189ac973SJohn Baldwin 			if (ppl != NULL)
588189ac973SJohn Baldwin 				ppl[1] = pl;
58998685dc8SJohn Baldwin 			fork_reported[1] = true;
59098685dc8SJohn Baldwin 		} else {
59198685dc8SJohn Baldwin 			ATF_REQUIRE(wpid == parent);
59298685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
59398685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
59498685dc8SJohn Baldwin 			if (child == -1)
59598685dc8SJohn Baldwin 				child = pl.pl_child_pid;
59698685dc8SJohn Baldwin 			else
59798685dc8SJohn Baldwin 				ATF_REQUIRE(child == pl.pl_child_pid);
598189ac973SJohn Baldwin 			if (ppl != NULL)
599189ac973SJohn Baldwin 				ppl[0] = pl;
60098685dc8SJohn Baldwin 			fork_reported[0] = true;
60198685dc8SJohn Baldwin 		}
60298685dc8SJohn Baldwin 	}
60398685dc8SJohn Baldwin 
60498685dc8SJohn Baldwin 	return (child);
60598685dc8SJohn Baldwin }
60698685dc8SJohn Baldwin 
60798685dc8SJohn Baldwin /*
60898685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
60998685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
61098685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
61198685dc8SJohn Baldwin  */
61298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
61398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
61498685dc8SJohn Baldwin {
615479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
61698685dc8SJohn Baldwin 	int status;
61798685dc8SJohn Baldwin 
61898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
61998685dc8SJohn Baldwin 	if (fpid == 0) {
62098685dc8SJohn Baldwin 		trace_me();
621189ac973SJohn Baldwin 		follow_fork_parent(false);
62298685dc8SJohn Baldwin 	}
62398685dc8SJohn Baldwin 
62498685dc8SJohn Baldwin 	/* Parent process. */
62598685dc8SJohn Baldwin 	children[0] = fpid;
62698685dc8SJohn Baldwin 
62798685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
62898685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
62998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
63098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
63198685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
63298685dc8SJohn Baldwin 
63398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
63498685dc8SJohn Baldwin 
63598685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
63698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
63798685dc8SJohn Baldwin 
638189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
63998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
64098685dc8SJohn Baldwin 
64198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
64298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
64398685dc8SJohn Baldwin 
64498685dc8SJohn Baldwin 	/*
64598685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
64698685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
64798685dc8SJohn Baldwin 	 */
64898685dc8SJohn Baldwin 	wpid = wait(&status);
64998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
65098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
65198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
65298685dc8SJohn Baldwin 
65398685dc8SJohn Baldwin 	wpid = wait(&status);
65498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
65598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
65698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
65798685dc8SJohn Baldwin 
65898685dc8SJohn Baldwin 	wpid = wait(&status);
65998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
66098685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
66198685dc8SJohn Baldwin }
66298685dc8SJohn Baldwin 
66398685dc8SJohn Baldwin /*
66498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
66598685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
66698685dc8SJohn Baldwin  * child process is detached after it reports its fork.
66798685dc8SJohn Baldwin  */
66898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
66998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
67098685dc8SJohn Baldwin {
671479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
67298685dc8SJohn Baldwin 	int status;
67398685dc8SJohn Baldwin 
67498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
67598685dc8SJohn Baldwin 	if (fpid == 0) {
67698685dc8SJohn Baldwin 		trace_me();
677189ac973SJohn Baldwin 		follow_fork_parent(false);
67898685dc8SJohn Baldwin 	}
67998685dc8SJohn Baldwin 
68098685dc8SJohn Baldwin 	/* Parent process. */
68198685dc8SJohn Baldwin 	children[0] = fpid;
68298685dc8SJohn Baldwin 
68398685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
68498685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
68598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
68698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
68798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
68898685dc8SJohn Baldwin 
68998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
69098685dc8SJohn Baldwin 
69198685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
69298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
69398685dc8SJohn Baldwin 
694189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
69598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
69698685dc8SJohn Baldwin 
69798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
69898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
69998685dc8SJohn Baldwin 
70098685dc8SJohn Baldwin 	/*
70198685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
70298685dc8SJohn Baldwin 	 * child.
70398685dc8SJohn Baldwin 	 */
70498685dc8SJohn Baldwin 	wpid = wait(&status);
70598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
70698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
70798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
70898685dc8SJohn Baldwin 
70998685dc8SJohn Baldwin 	wpid = wait(&status);
71098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
71198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
71298685dc8SJohn Baldwin }
71398685dc8SJohn Baldwin 
71498685dc8SJohn Baldwin /*
71598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
71698685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
71798685dc8SJohn Baldwin  * traced parent is detached after the fork.
71898685dc8SJohn Baldwin  */
71998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
72098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
72198685dc8SJohn Baldwin {
722479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
72398685dc8SJohn Baldwin 	int status;
72498685dc8SJohn Baldwin 
72598685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
72698685dc8SJohn Baldwin 	if (fpid == 0) {
72798685dc8SJohn Baldwin 		trace_me();
728189ac973SJohn Baldwin 		follow_fork_parent(false);
72998685dc8SJohn Baldwin 	}
73098685dc8SJohn Baldwin 
73198685dc8SJohn Baldwin 	/* Parent process. */
73298685dc8SJohn Baldwin 	children[0] = fpid;
73398685dc8SJohn Baldwin 
73498685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
73598685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
73698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
73798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
73898685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
73998685dc8SJohn Baldwin 
74098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
74198685dc8SJohn Baldwin 
74298685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
74398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
74498685dc8SJohn Baldwin 
745189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
74698685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
74798685dc8SJohn Baldwin 
74898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
74998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
75098685dc8SJohn Baldwin 
75198685dc8SJohn Baldwin 	/*
75298685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
75398685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
75498685dc8SJohn Baldwin 	 *
75598685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
75698685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
75798685dc8SJohn Baldwin 	 * after the grandchild.
75898685dc8SJohn Baldwin 	 */
75998685dc8SJohn Baldwin 	wpid = wait(&status);
76098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
76198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
76298685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
76398685dc8SJohn Baldwin 
76498685dc8SJohn Baldwin 	wpid = wait(&status);
76598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
76698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
76798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
76898685dc8SJohn Baldwin 
76998685dc8SJohn Baldwin 	wpid = wait(&status);
77098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
77198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
77298685dc8SJohn Baldwin }
77398685dc8SJohn Baldwin 
77498685dc8SJohn Baldwin static void
77598685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
77698685dc8SJohn Baldwin {
77798685dc8SJohn Baldwin 	pid_t fpid;
77898685dc8SJohn Baldwin 
77998685dc8SJohn Baldwin 	close(cpipe[0]);
78098685dc8SJohn Baldwin 
78198685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
78298685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
78398685dc8SJohn Baldwin 	if (fpid != 0)
784b98cb919SJohn Baldwin 		_exit(3);
78598685dc8SJohn Baldwin 
78698685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
78798685dc8SJohn Baldwin 	fpid = getpid();
78898685dc8SJohn Baldwin 	CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
78998685dc8SJohn Baldwin 
79098685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
79198685dc8SJohn Baldwin 	CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
79298685dc8SJohn Baldwin }
79398685dc8SJohn Baldwin 
79498685dc8SJohn Baldwin /*
79598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
79698685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
79798685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
79898685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
79998685dc8SJohn Baldwin  */
80098685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
80198685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
80298685dc8SJohn Baldwin {
803479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
80498685dc8SJohn Baldwin 	int cpipe[2], status;
80598685dc8SJohn Baldwin 
8069777e354SLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool(tc, "ci"))
807ea24861dSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/239397");
808ea24861dSLi-Wen Hsu 
80998685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
81098685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
81198685dc8SJohn Baldwin 	if (fpid == 0) {
81298685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
813189ac973SJohn Baldwin 		follow_fork_parent(false);
81498685dc8SJohn Baldwin 	}
81598685dc8SJohn Baldwin 
81698685dc8SJohn Baldwin 	/* Parent process. */
81798685dc8SJohn Baldwin 	close(cpipe[1]);
81898685dc8SJohn Baldwin 
81998685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
82098685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
82198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
82298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
82398685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
82498685dc8SJohn Baldwin 
82598685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
82698685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
82798685dc8SJohn Baldwin 	    sizeof(children[0]));
82898685dc8SJohn Baldwin 
82998685dc8SJohn Baldwin 	/* Attach to the fork parent. */
83098685dc8SJohn Baldwin 	attach_child(children[0]);
83198685dc8SJohn Baldwin 
83298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
83398685dc8SJohn Baldwin 
83498685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
83598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
83698685dc8SJohn Baldwin 
83798685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
83898685dc8SJohn Baldwin 	close(cpipe[0]);
83998685dc8SJohn Baldwin 
840189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
84198685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
84298685dc8SJohn Baldwin 
84398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
84498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
84598685dc8SJohn Baldwin 
84698685dc8SJohn Baldwin 	/*
84798685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
84898685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
84998685dc8SJohn Baldwin 	 */
85098685dc8SJohn Baldwin 	wpid = wait(&status);
85198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
85298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
85398685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
85498685dc8SJohn Baldwin 
85598685dc8SJohn Baldwin 	wpid = wait(&status);
85698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
85798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
85898685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
85998685dc8SJohn Baldwin 
86098685dc8SJohn Baldwin 	wpid = wait(&status);
86198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
86298685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
86398685dc8SJohn Baldwin }
86498685dc8SJohn Baldwin 
86598685dc8SJohn Baldwin /*
86698685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
86798685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
86898685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
86998685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
87098685dc8SJohn Baldwin  */
87198685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
87298685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
87398685dc8SJohn Baldwin {
874479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
87598685dc8SJohn Baldwin 	int cpipe[2], status;
87698685dc8SJohn Baldwin 
8779777e354SLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool(tc, "ci"))
87863b0609cSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/239292");
87937ba9b34SLi-Wen Hsu 
88098685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
88198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
88298685dc8SJohn Baldwin 	if (fpid == 0) {
88398685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
884189ac973SJohn Baldwin 		follow_fork_parent(false);
88598685dc8SJohn Baldwin 	}
88698685dc8SJohn Baldwin 
88798685dc8SJohn Baldwin 	/* Parent process. */
88898685dc8SJohn Baldwin 	close(cpipe[1]);
88998685dc8SJohn Baldwin 
89098685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
89198685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
89298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
89398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
89498685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
89598685dc8SJohn Baldwin 
89698685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
89798685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
89898685dc8SJohn Baldwin 	    sizeof(children[0]));
89998685dc8SJohn Baldwin 
90098685dc8SJohn Baldwin 	/* Attach to the fork parent. */
90198685dc8SJohn Baldwin 	attach_child(children[0]);
90298685dc8SJohn Baldwin 
90398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
90498685dc8SJohn Baldwin 
90598685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
90698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
90798685dc8SJohn Baldwin 
90898685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
90998685dc8SJohn Baldwin 	close(cpipe[0]);
91098685dc8SJohn Baldwin 
911189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
91298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
91398685dc8SJohn Baldwin 
91498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
91598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
91698685dc8SJohn Baldwin 
91798685dc8SJohn Baldwin 	/*
91898685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
91998685dc8SJohn Baldwin 	 * parent.
92098685dc8SJohn Baldwin 	 */
92198685dc8SJohn Baldwin 	wpid = wait(&status);
92298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
92398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
92498685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
92598685dc8SJohn Baldwin 
92698685dc8SJohn Baldwin 	wpid = wait(&status);
92798685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
92898685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
92998685dc8SJohn Baldwin }
93098685dc8SJohn Baldwin 
93198685dc8SJohn Baldwin /*
93298685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
93398685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
93498685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
93598685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
93698685dc8SJohn Baldwin  */
93798685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
93898685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
93998685dc8SJohn Baldwin {
940479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
94198685dc8SJohn Baldwin 	int cpipe[2], status;
94298685dc8SJohn Baldwin 
9439777e354SLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool(tc, "ci"))
9441ab93d1fSLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/239425");
9451ab93d1fSLi-Wen Hsu 
94698685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
94798685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
94898685dc8SJohn Baldwin 	if (fpid == 0) {
94998685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
950189ac973SJohn Baldwin 		follow_fork_parent(false);
95198685dc8SJohn Baldwin 	}
95298685dc8SJohn Baldwin 
95398685dc8SJohn Baldwin 	/* Parent process. */
95498685dc8SJohn Baldwin 	close(cpipe[1]);
95598685dc8SJohn Baldwin 
95698685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
95798685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
95898685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
95998685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
96098685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
96198685dc8SJohn Baldwin 
96298685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
96398685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
96498685dc8SJohn Baldwin 	    sizeof(children[0]));
96598685dc8SJohn Baldwin 
96698685dc8SJohn Baldwin 	/* Attach to the fork parent. */
96798685dc8SJohn Baldwin 	attach_child(children[0]);
96898685dc8SJohn Baldwin 
96998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
97098685dc8SJohn Baldwin 
97198685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
97298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
97398685dc8SJohn Baldwin 
97498685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
97598685dc8SJohn Baldwin 	close(cpipe[0]);
97698685dc8SJohn Baldwin 
977189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
97898685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
97998685dc8SJohn Baldwin 
98098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
98198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
98298685dc8SJohn Baldwin 
98398685dc8SJohn Baldwin 	/*
98498685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
98598685dc8SJohn Baldwin 	 * the child.
98698685dc8SJohn Baldwin 	 */
98798685dc8SJohn Baldwin 	wpid = wait(&status);
98898685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
98998685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
99098685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
99198685dc8SJohn Baldwin 
99298685dc8SJohn Baldwin 	wpid = wait(&status);
99398685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
99498685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
99598685dc8SJohn Baldwin }
99698685dc8SJohn Baldwin 
997368b2b1cSJohn Baldwin /*
998368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
999368b2b1cSJohn Baldwin  * parent but sees its original parent process.
1000368b2b1cSJohn Baldwin  */
1001368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
1002368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
1003368b2b1cSJohn Baldwin {
1004368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
1005368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
1006368b2b1cSJohn Baldwin 	char c;
1007368b2b1cSJohn Baldwin 
1008368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
1009368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
1010368b2b1cSJohn Baldwin 
1011368b2b1cSJohn Baldwin 	if (child == 0) {
1012368b2b1cSJohn Baldwin 		/* Child process. */
1013368b2b1cSJohn Baldwin 		close(cpipe[0]);
1014368b2b1cSJohn Baldwin 
1015368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
1016368b2b1cSJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
1017368b2b1cSJohn Baldwin 
1018368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
1019368b2b1cSJohn Baldwin 		ppid = getppid();
1020368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) ==
1021368b2b1cSJohn Baldwin 		    sizeof(ppid));
1022368b2b1cSJohn Baldwin 
1023368b2b1cSJohn Baldwin 		_exit(1);
1024368b2b1cSJohn Baldwin 	}
1025368b2b1cSJohn Baldwin 	close(cpipe[1]);
1026368b2b1cSJohn Baldwin 
1027368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
1028368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
1029368b2b1cSJohn Baldwin 
1030368b2b1cSJohn Baldwin 	if (debugger == 0) {
1031368b2b1cSJohn Baldwin 		/* Debugger process. */
1032368b2b1cSJohn Baldwin 		close(dpipe[0]);
1033368b2b1cSJohn Baldwin 
1034368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
1035368b2b1cSJohn Baldwin 
1036368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
1037368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
1038368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
1039368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1040368b2b1cSJohn Baldwin 
1041368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
1042368b2b1cSJohn Baldwin 
1043368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
1044368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
1045368b2b1cSJohn Baldwin 
1046368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
1047368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
1048368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
1049368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
1050368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
1051368b2b1cSJohn Baldwin 
1052368b2b1cSJohn Baldwin 		_exit(0);
1053368b2b1cSJohn Baldwin 	}
1054368b2b1cSJohn Baldwin 	close(dpipe[1]);
1055368b2b1cSJohn Baldwin 
1056368b2b1cSJohn Baldwin 	/* Parent process. */
1057368b2b1cSJohn Baldwin 
1058368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
1059368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
1060368b2b1cSJohn Baldwin 
1061368b2b1cSJohn Baldwin 	/* Release the child. */
1062368b2b1cSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
1063368b2b1cSJohn Baldwin 
1064368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
1065368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid));
1066368b2b1cSJohn Baldwin 	close(cpipe[0]);
1067368b2b1cSJohn Baldwin 
1068368b2b1cSJohn Baldwin 	ATF_REQUIRE(ppid == getpid());
1069368b2b1cSJohn Baldwin 
1070368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
1071368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
1072368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
1073368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1074368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
1075368b2b1cSJohn Baldwin 
1076368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
1077368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
1078368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == child);
1079368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1080368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1081368b2b1cSJohn Baldwin }
1082368b2b1cSJohn Baldwin 
1083189ac973SJohn Baldwin /*
1084189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1085189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
1086189ac973SJohn Baldwin  */
1087189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
1088189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
1089189ac973SJohn Baldwin {
1090189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1091189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1092189ac973SJohn Baldwin 	int status;
1093189ac973SJohn Baldwin 
1094189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1095189ac973SJohn Baldwin 	if (fpid == 0) {
1096189ac973SJohn Baldwin 		trace_me();
1097189ac973SJohn Baldwin 		follow_fork_parent(false);
1098189ac973SJohn Baldwin 	}
1099189ac973SJohn Baldwin 
1100189ac973SJohn Baldwin 	/* Parent process. */
1101189ac973SJohn Baldwin 	children[0] = fpid;
1102189ac973SJohn Baldwin 
1103189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1104189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1105189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1106189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1107189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1108189ac973SJohn Baldwin 
1109189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1110189ac973SJohn Baldwin 
1111189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1112189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1113189ac973SJohn Baldwin 
1114189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1115189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1116189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1117189ac973SJohn Baldwin 
1118189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1119189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1120189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork);
1121189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1122189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1123189ac973SJohn Baldwin 
1124189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1125189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1126189ac973SJohn Baldwin 
1127189ac973SJohn Baldwin 	/*
1128189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1129189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1130189ac973SJohn Baldwin 	 */
1131189ac973SJohn Baldwin 	wpid = wait(&status);
1132189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1133189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1134189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1135189ac973SJohn Baldwin 
1136189ac973SJohn Baldwin 	wpid = wait(&status);
1137189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1138189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1139189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1140189ac973SJohn Baldwin 
1141189ac973SJohn Baldwin 	wpid = wait(&status);
1142189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1143189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1144189ac973SJohn Baldwin }
1145189ac973SJohn Baldwin 
1146189ac973SJohn Baldwin /*
1147189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1148189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1149189ac973SJohn Baldwin  */
1150189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1151189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1152189ac973SJohn Baldwin {
1153189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1154189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1155189ac973SJohn Baldwin 	int status;
1156189ac973SJohn Baldwin 
1157189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1158189ac973SJohn Baldwin 	if (fpid == 0) {
1159189ac973SJohn Baldwin 		trace_me();
1160189ac973SJohn Baldwin 		follow_fork_parent(true);
1161189ac973SJohn Baldwin 	}
1162189ac973SJohn Baldwin 
1163189ac973SJohn Baldwin 	/* Parent process. */
1164189ac973SJohn Baldwin 	children[0] = fpid;
1165189ac973SJohn Baldwin 
1166189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1167189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1168189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1169189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1170189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1171189ac973SJohn Baldwin 
1172189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1173189ac973SJohn Baldwin 
1174189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1175189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1176189ac973SJohn Baldwin 
1177189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1178189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1179189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1180189ac973SJohn Baldwin 
1181189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1182189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1183189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork);
1184189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1185189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1186189ac973SJohn Baldwin 
1187189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1188189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1189189ac973SJohn Baldwin 
1190189ac973SJohn Baldwin 	/*
1191189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1192189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1193189ac973SJohn Baldwin 	 */
1194189ac973SJohn Baldwin 	wpid = wait(&status);
1195189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1196189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1197189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1198189ac973SJohn Baldwin 
1199189ac973SJohn Baldwin 	wpid = wait(&status);
1200189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1201189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1202189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1203189ac973SJohn Baldwin 
1204189ac973SJohn Baldwin 	wpid = wait(&status);
1205189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1206189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1207189ac973SJohn Baldwin }
1208189ac973SJohn Baldwin 
1209189ac973SJohn Baldwin static void *
1210189ac973SJohn Baldwin simple_thread(void *arg __unused)
1211189ac973SJohn Baldwin {
1212189ac973SJohn Baldwin 
1213189ac973SJohn Baldwin 	pthread_exit(NULL);
1214189ac973SJohn Baldwin }
1215189ac973SJohn Baldwin 
12165fcfab6eSJohn Baldwin static __dead2 void
12175fcfab6eSJohn Baldwin simple_thread_main(void)
12185fcfab6eSJohn Baldwin {
12195fcfab6eSJohn Baldwin 	pthread_t thread;
12205fcfab6eSJohn Baldwin 
12215fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, NULL) == 0);
12225fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_join(thread, NULL) == 0);
12235fcfab6eSJohn Baldwin 	exit(1);
12245fcfab6eSJohn Baldwin }
12255fcfab6eSJohn Baldwin 
1226189ac973SJohn Baldwin /*
1227189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1228189ac973SJohn Baldwin  * thread reports the correct value.
1229189ac973SJohn Baldwin  */
1230189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1231189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1232189ac973SJohn Baldwin {
1233189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1234189ac973SJohn Baldwin 	pid_t fpid, wpid;
1235e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1236189ac973SJohn Baldwin 	int status;
1237189ac973SJohn Baldwin 
1238189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1239189ac973SJohn Baldwin 	if (fpid == 0) {
1240189ac973SJohn Baldwin 		trace_me();
12415fcfab6eSJohn Baldwin 		simple_thread_main();
1242189ac973SJohn Baldwin 	}
1243189ac973SJohn Baldwin 
1244189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1245189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1246189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1247189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1248189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1249189ac973SJohn Baldwin 
1250189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1251189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1252e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1253189ac973SJohn Baldwin 
1254189ac973SJohn Baldwin 	/*
1255189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1256189ac973SJohn Baldwin 	 * system call exits.
1257189ac973SJohn Baldwin 	 */
1258189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1259189ac973SJohn Baldwin 
1260189ac973SJohn Baldwin 	/*
1261189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1262189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1263189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1264189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1265189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1266189ac973SJohn Baldwin 	 */
1267189ac973SJohn Baldwin 	for (;;) {
1268189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1269189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1270189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1271189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1272189ac973SJohn Baldwin 
1273189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1274189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1275189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1276189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1277e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1278189ac973SJohn Baldwin 			/* New thread seen. */
1279189ac973SJohn Baldwin 			break;
1280189ac973SJohn Baldwin 
1281189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1282189ac973SJohn Baldwin 	}
1283189ac973SJohn Baldwin 
1284189ac973SJohn Baldwin 	/* Wait for the child to exit. */
1285189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1286189ac973SJohn Baldwin 	for (;;) {
1287189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1288189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1289189ac973SJohn Baldwin 		if (WIFEXITED(status))
1290189ac973SJohn Baldwin 			break;
1291189ac973SJohn Baldwin 
1292189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1293189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1294189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1295189ac973SJohn Baldwin 	}
1296189ac973SJohn Baldwin 
1297189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1298189ac973SJohn Baldwin 
1299189ac973SJohn Baldwin 	wpid = wait(&status);
1300189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1301189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1302189ac973SJohn Baldwin }
1303189ac973SJohn Baldwin 
13045fcfab6eSJohn Baldwin /*
13055fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
13065fcfab6eSJohn Baldwin  */
13075fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
13085fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
13095fcfab6eSJohn Baldwin {
13105fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
13115fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
13125fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
13135fcfab6eSJohn Baldwin 	int status;
13145fcfab6eSJohn Baldwin 
13155fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13165fcfab6eSJohn Baldwin 	if (fpid == 0) {
13175fcfab6eSJohn Baldwin 		trace_me();
13185fcfab6eSJohn Baldwin 		simple_thread_main();
13195fcfab6eSJohn Baldwin 	}
13205fcfab6eSJohn Baldwin 
13215fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13225fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13235fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13245fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13255fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
13265fcfab6eSJohn Baldwin 
13275fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13285fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13295fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13305fcfab6eSJohn Baldwin 
13315fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
13325fcfab6eSJohn Baldwin 
13335fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
13345fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13355fcfab6eSJohn Baldwin 
13365fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13375fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13385fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13395fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13405fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13415fcfab6eSJohn Baldwin 
13425fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13435fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
13445fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13455fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13465fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13475fcfab6eSJohn Baldwin 
13485fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13495fcfab6eSJohn Baldwin 
13505fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
13515fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13525fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13535fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13545fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13555fcfab6eSJohn Baldwin 
13565fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13575fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
13585fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
13595fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
13605fcfab6eSJohn Baldwin 
13615fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13625fcfab6eSJohn Baldwin 
13635fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13645fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13655fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
13665fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
13675fcfab6eSJohn Baldwin 
13685fcfab6eSJohn Baldwin 	wpid = wait(&status);
13695fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
13705fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
13715fcfab6eSJohn Baldwin }
13725fcfab6eSJohn Baldwin 
13735fcfab6eSJohn Baldwin static void *
13745fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
13755fcfab6eSJohn Baldwin {
13765fcfab6eSJohn Baldwin 
13775fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
13785fcfab6eSJohn Baldwin 	exit(127);
13795fcfab6eSJohn Baldwin }
13805fcfab6eSJohn Baldwin 
13815fcfab6eSJohn Baldwin static __dead2 void
13825fcfab6eSJohn Baldwin exec_thread_main(void)
13835fcfab6eSJohn Baldwin {
13845fcfab6eSJohn Baldwin 	pthread_t thread;
13855fcfab6eSJohn Baldwin 
13865fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, exec_thread, NULL) == 0);
13875fcfab6eSJohn Baldwin 	for (;;)
13885fcfab6eSJohn Baldwin 		sleep(60);
13895fcfab6eSJohn Baldwin 	exit(1);
13905fcfab6eSJohn Baldwin }
13915fcfab6eSJohn Baldwin 
13925fcfab6eSJohn Baldwin /*
13935fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
13945fcfab6eSJohn Baldwin  * process that calls execve(2).
13955fcfab6eSJohn Baldwin  */
13965fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
13975fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
13985fcfab6eSJohn Baldwin {
13995fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
14005fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
14015fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
14025fcfab6eSJohn Baldwin 	int status;
14035fcfab6eSJohn Baldwin 
14045fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14055fcfab6eSJohn Baldwin 	if (fpid == 0) {
14065fcfab6eSJohn Baldwin 		trace_me();
14075fcfab6eSJohn Baldwin 		exec_thread_main();
14085fcfab6eSJohn Baldwin 	}
14095fcfab6eSJohn Baldwin 
14105fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14115fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14125fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14135fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14145fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14155fcfab6eSJohn Baldwin 
14165fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
14175fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
14185fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
14195fcfab6eSJohn Baldwin 
14205fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
14215fcfab6eSJohn Baldwin 
14225fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
14235fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14245fcfab6eSJohn Baldwin 
14255fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
14265fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14275fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14285fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14295fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
14305fcfab6eSJohn Baldwin 
14315fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14325fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
14335fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
14345fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
14355fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
14365fcfab6eSJohn Baldwin 
14375fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14385fcfab6eSJohn Baldwin 
14395fcfab6eSJohn Baldwin 	/*
14405fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
14415fcfab6eSJohn Baldwin 	 * single threading from execve().
14425fcfab6eSJohn Baldwin 	 */
14435fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14445fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14455fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14465fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
14475fcfab6eSJohn Baldwin 
14485fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14495fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
14505fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
14515fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[0]);
14525fcfab6eSJohn Baldwin 
14535fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14545fcfab6eSJohn Baldwin 
14555fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
14565fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14575fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14585fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
14595fcfab6eSJohn Baldwin 
14605fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14615fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
14625fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
14635fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
14645fcfab6eSJohn Baldwin 
14655fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14665fcfab6eSJohn Baldwin 
14675fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
14685fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14695fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
14705fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
14715fcfab6eSJohn Baldwin 
14725fcfab6eSJohn Baldwin 	wpid = wait(&status);
14735fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14745fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
14755fcfab6eSJohn Baldwin }
14765fcfab6eSJohn Baldwin 
14773340c45bSJohn Baldwin static void
14783340c45bSJohn Baldwin handler(int sig __unused)
14793340c45bSJohn Baldwin {
14803340c45bSJohn Baldwin }
14813340c45bSJohn Baldwin 
14823340c45bSJohn Baldwin static void
14833340c45bSJohn Baldwin signal_main(void)
14843340c45bSJohn Baldwin {
14853340c45bSJohn Baldwin 
14863340c45bSJohn Baldwin 	signal(SIGINFO, handler);
14873340c45bSJohn Baldwin 	raise(SIGINFO);
14883340c45bSJohn Baldwin 	exit(0);
14893340c45bSJohn Baldwin }
14903340c45bSJohn Baldwin 
14913340c45bSJohn Baldwin /*
14923340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
14933340c45bSJohn Baldwin  */
14943340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
14953340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
14963340c45bSJohn Baldwin {
14973340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
14983340c45bSJohn Baldwin 	pid_t fpid, wpid;
14993340c45bSJohn Baldwin 	int status;
15003340c45bSJohn Baldwin 
15013340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15023340c45bSJohn Baldwin 	if (fpid == 0) {
15033340c45bSJohn Baldwin 		trace_me();
15043340c45bSJohn Baldwin 		signal_main();
15053340c45bSJohn Baldwin 	}
15063340c45bSJohn Baldwin 
15073340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15083340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15093340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15103340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15113340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15123340c45bSJohn Baldwin 
15133340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15143340c45bSJohn Baldwin 
15153340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
15163340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15173340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15183340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGINFO);
15193340c45bSJohn Baldwin 
15203340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
15213340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_event == PL_EVENT_SIGNAL);
15223340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
15233340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == SI_LWP);
15243340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_pid == wpid);
15253340c45bSJohn Baldwin 
15263340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15273340c45bSJohn Baldwin 
15283340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
15293340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15303340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15313340c45bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15323340c45bSJohn Baldwin 
15333340c45bSJohn Baldwin 	wpid = wait(&status);
15343340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15353340c45bSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15363340c45bSJohn Baldwin }
15373340c45bSJohn Baldwin 
15388d570f64SJohn Baldwin /*
15398d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
15408d570f64SJohn Baldwin  */
15418d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
15428d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
15438d570f64SJohn Baldwin {
15448d570f64SJohn Baldwin 	pid_t fpid, wpid;
15458d570f64SJohn Baldwin 	int events, status;
15468d570f64SJohn Baldwin 
15478d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15488d570f64SJohn Baldwin 	if (fpid == 0) {
15498d570f64SJohn Baldwin 		trace_me();
15508d570f64SJohn Baldwin 		exec_thread(NULL);
15518d570f64SJohn Baldwin 	}
15528d570f64SJohn Baldwin 
15538d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15548d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15558d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15568d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15578d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15588d570f64SJohn Baldwin 
15598d570f64SJohn Baldwin 	events = 0;
15608d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15618d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15628d570f64SJohn Baldwin 
15638d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15648d570f64SJohn Baldwin 
15658d570f64SJohn Baldwin 	/* Should get one event at exit. */
15668d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15678d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15688d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15698d570f64SJohn Baldwin 
15708d570f64SJohn Baldwin 	wpid = wait(&status);
15718d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15728d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15738d570f64SJohn Baldwin }
15748d570f64SJohn Baldwin 
15758d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
15768d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
15778d570f64SJohn Baldwin {
15788d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
15798d570f64SJohn Baldwin 	pid_t fpid, wpid;
15808d570f64SJohn Baldwin 	int events, status;
15818d570f64SJohn Baldwin 
15828d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15838d570f64SJohn Baldwin 	if (fpid == 0) {
15848d570f64SJohn Baldwin 		trace_me();
15858d570f64SJohn Baldwin 		exec_thread(NULL);
15868d570f64SJohn Baldwin 	}
15878d570f64SJohn Baldwin 
15888d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15898d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15908d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15918d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15928d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15938d570f64SJohn Baldwin 
15948d570f64SJohn Baldwin 	events = PTRACE_EXEC;
15958d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15968d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15978d570f64SJohn Baldwin 
15988d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15998d570f64SJohn Baldwin 
16008d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
16018d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16028d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
16038d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
16048d570f64SJohn Baldwin 
16058d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
16068d570f64SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
16078d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
16088d570f64SJohn Baldwin 
16098d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
16108d570f64SJohn Baldwin 
16118d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
16128d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16138d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
16148d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
16158d570f64SJohn Baldwin 
16168d570f64SJohn Baldwin 	wpid = wait(&status);
16178d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
16188d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
16198d570f64SJohn Baldwin }
16208d570f64SJohn Baldwin 
16218d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
16228d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
16238d570f64SJohn Baldwin {
16248d570f64SJohn Baldwin 	pid_t fpid, wpid;
16258d570f64SJohn Baldwin 	int events, status;
16268d570f64SJohn Baldwin 
16278d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16288d570f64SJohn Baldwin 	if (fpid == 0) {
16298d570f64SJohn Baldwin 		trace_me();
16308d570f64SJohn Baldwin 		exit(0);
16318d570f64SJohn Baldwin 	}
16328d570f64SJohn Baldwin 
16338d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16348d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16358d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
16368d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
16378d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
16388d570f64SJohn Baldwin 
16398d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
16408d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
16418d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16428d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16438d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_FORK);
16448d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
16458d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16468d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16478d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_FORK));
16488d570f64SJohn Baldwin 
16498d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
16508d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
16518d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16528d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16538d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_LWP);
16548d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
16558d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16568d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16578d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_LWP));
16588d570f64SJohn Baldwin 
16598d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
16608d570f64SJohn Baldwin 
16618d570f64SJohn Baldwin 	/* Should get one event at exit. */
16628d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16638d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
16648d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
16658d570f64SJohn Baldwin 
16668d570f64SJohn Baldwin 	wpid = wait(&status);
16678d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
16688d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
16698d570f64SJohn Baldwin }
16708d570f64SJohn Baldwin 
1671fc4f075aSJohn Baldwin /*
1672fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1673fc4f075aSJohn Baldwin  */
1674fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
1675fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1676fc4f075aSJohn Baldwin {
1677fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1678fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1679fc4f075aSJohn Baldwin 	int events, status;
1680fc4f075aSJohn Baldwin 
1681fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1682fc4f075aSJohn Baldwin 	if (fpid == 0) {
1683fc4f075aSJohn Baldwin 		trace_me();
1684fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1685fc4f075aSJohn Baldwin 	}
1686fc4f075aSJohn Baldwin 
1687fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1688fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1689fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1690fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1691fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1692fc4f075aSJohn Baldwin 
1693fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1694fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1695fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1696fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1697fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1698fc4f075aSJohn Baldwin 
1699fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1700fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1701fc4f075aSJohn Baldwin 
1702fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1703fc4f075aSJohn Baldwin 	wpid = wait(&status);
1704fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1705fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1706fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1707fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1708fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1709fc4f075aSJohn Baldwin 
1710fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1711fc4f075aSJohn Baldwin 
1712fc4f075aSJohn Baldwin 	wpid = wait(&status);
1713fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
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 
1722fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
1723fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1724fc4f075aSJohn Baldwin {
1725fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1726fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1727fc4f075aSJohn Baldwin 	int events, status;
1728fc4f075aSJohn Baldwin 
1729fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1730fc4f075aSJohn Baldwin 	if (fpid == 0) {
1731fc4f075aSJohn Baldwin 		trace_me();
1732fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1733fc4f075aSJohn Baldwin 	}
1734fc4f075aSJohn Baldwin 
1735fc4f075aSJohn Baldwin 	/* Parent process. */
1736fc4f075aSJohn Baldwin 	children[0] = fpid;
1737fc4f075aSJohn Baldwin 
1738fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1739fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1740fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1741fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1742fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1743fc4f075aSJohn Baldwin 
1744fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1745fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1746fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1747fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1748fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1749fc4f075aSJohn Baldwin 
1750fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1751fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1752fc4f075aSJohn Baldwin 
1753fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1754fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1755fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1756fc4f075aSJohn Baldwin 
1757fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1758fc4f075aSJohn Baldwin 
1759fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1760fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1761fc4f075aSJohn Baldwin 
1762fc4f075aSJohn Baldwin 	/*
1763fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1764fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1765fc4f075aSJohn Baldwin 	 */
1766fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
1767fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1768fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1769fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1770fc4f075aSJohn Baldwin 
1771fc4f075aSJohn Baldwin 	/*
1772fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1773fc4f075aSJohn Baldwin 	 * exits.
1774fc4f075aSJohn Baldwin 	 */
1775fc4f075aSJohn Baldwin 	wpid = wait(&status);
1776fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1777fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1778fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1779fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1780fc4f075aSJohn Baldwin 	    -1);
1781fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1782fc4f075aSJohn Baldwin 
1783fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1784fc4f075aSJohn Baldwin 
1785fc4f075aSJohn Baldwin 	wpid = wait(&status);
1786fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1787fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1788fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1789fc4f075aSJohn Baldwin 
1790fc4f075aSJohn Baldwin 	wpid = wait(&status);
1791fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1792fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1793fc4f075aSJohn Baldwin }
1794fc4f075aSJohn Baldwin 
1795403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
1796e2ebfbbfSEric Badger /*
179782a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
179882a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
179982a4538fSEric Badger  */
180082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
180182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
180282a4538fSEric Badger {
180382a4538fSEric Badger 	pid_t fpid, wpid;
180482a4538fSEric Badger 	int status;
180582a4538fSEric Badger 
180682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
180782a4538fSEric Badger 	if (fpid == 0) {
180882a4538fSEric Badger 		trace_me();
18099e0d1159SEric Badger 		breakpoint();
181082a4538fSEric Badger 		exit(1);
181182a4538fSEric Badger 	}
181282a4538fSEric Badger 
181382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
181482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
181582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
181682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
181782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
181882a4538fSEric Badger 
181982a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
182082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
182182a4538fSEric Badger 
182282a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
182382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
182482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
182582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
182682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
182782a4538fSEric Badger 
182882a4538fSEric Badger 	/* Kill the child process. */
182982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
183082a4538fSEric Badger 
183182a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
183282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
183382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
183482a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
183582a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
183682a4538fSEric Badger 
183782a4538fSEric Badger 	wpid = wait(&status);
183882a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
183982a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
184082a4538fSEric Badger }
1841403e331dSJohn Baldwin #endif /* HAVE_BREAKPOINT */
184282a4538fSEric Badger 
184382a4538fSEric Badger /*
184482a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
184582a4538fSEric Badger  * process exit when stopped inside of a system call.
184682a4538fSEric Badger  */
184782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
184882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
184982a4538fSEric Badger {
185082a4538fSEric Badger 	struct ptrace_lwpinfo pl;
185182a4538fSEric Badger 	pid_t fpid, wpid;
185282a4538fSEric Badger 	int status;
185382a4538fSEric Badger 
185482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
185582a4538fSEric Badger 	if (fpid == 0) {
185682a4538fSEric Badger 		trace_me();
185782a4538fSEric Badger 		getpid();
185882a4538fSEric Badger 		exit(1);
185982a4538fSEric Badger 	}
186082a4538fSEric Badger 
186182a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
186282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
186382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
186482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
186582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
186682a4538fSEric Badger 
186782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
186882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
186982a4538fSEric Badger 
187082a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
187182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
187282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
187382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
187482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
187582a4538fSEric Badger 
187682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
187782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
187882a4538fSEric Badger 
187982a4538fSEric Badger 	/* Kill the child process. */
188082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
188182a4538fSEric Badger 
188282a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
188382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
188482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
188582a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
188682a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
188782a4538fSEric Badger 
188882a4538fSEric Badger 	wpid = wait(&status);
188982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
189082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
189182a4538fSEric Badger }
189282a4538fSEric Badger 
189382a4538fSEric Badger /*
189482a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
189582a4538fSEric Badger  * process exit when killing a multithreaded process.
189682a4538fSEric Badger  */
189782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
189882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
189982a4538fSEric Badger {
190082a4538fSEric Badger 	struct ptrace_lwpinfo pl;
190182a4538fSEric Badger 	pid_t fpid, wpid;
190282a4538fSEric Badger 	lwpid_t main_lwp;
190382a4538fSEric Badger 	int status;
190482a4538fSEric Badger 
190582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
190682a4538fSEric Badger 	if (fpid == 0) {
190782a4538fSEric Badger 		trace_me();
190882a4538fSEric Badger 		simple_thread_main();
190982a4538fSEric Badger 	}
191082a4538fSEric Badger 
191182a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
191282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
191382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
191482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
191582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
191682a4538fSEric Badger 
191782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
191882a4538fSEric Badger 	    sizeof(pl)) != -1);
191982a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
192082a4538fSEric Badger 
192182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
192282a4538fSEric Badger 
192382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
192482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
192582a4538fSEric Badger 
192682a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
192782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
192882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
192982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
193082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
193182a4538fSEric Badger 
193282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
193382a4538fSEric Badger 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
193482a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
193582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
193682a4538fSEric Badger 
193782a4538fSEric Badger 	/* Kill the child process. */
193882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
193982a4538fSEric Badger 
194082a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
194182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
194282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
194382a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
194482a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
194582a4538fSEric Badger 
194682a4538fSEric Badger 	wpid = wait(&status);
194782a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
194882a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
194982a4538fSEric Badger }
195082a4538fSEric Badger 
195182a4538fSEric Badger static void *
195282a4538fSEric Badger mask_usr1_thread(void *arg)
195382a4538fSEric Badger {
195482a4538fSEric Badger 	pthread_barrier_t *pbarrier;
195582a4538fSEric Badger 	sigset_t sigmask;
195682a4538fSEric Badger 
195782a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
195882a4538fSEric Badger 
195982a4538fSEric Badger 	sigemptyset(&sigmask);
196082a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
196182a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
196282a4538fSEric Badger 
196382a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
196482a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
196582a4538fSEric Badger 
196682a4538fSEric Badger 	for (;;)
196782a4538fSEric Badger 		sleep(60);
196882a4538fSEric Badger 
196982a4538fSEric Badger 	return (NULL);
197082a4538fSEric Badger }
197182a4538fSEric Badger 
197282a4538fSEric Badger /*
197382a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
197482a4538fSEric Badger  * and prevents spurious stops due to those other signals.
197582a4538fSEric Badger  */
19763cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal);
19773cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
19783cf56bb4SEnji Cooper {
19793cf56bb4SEnji Cooper 
19803cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
19813cf56bb4SEnji Cooper }
198282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
198382a4538fSEric Badger {
198482a4538fSEric Badger 	pid_t fpid, wpid;
198582a4538fSEric Badger 	int status;
198682a4538fSEric Badger 	cpuset_t setmask;
198782a4538fSEric Badger 	pthread_t t;
198882a4538fSEric Badger 	pthread_barrier_t barrier;
1989bc2be1d3SEric Badger 	struct sched_param sched_param;
199082a4538fSEric Badger 
199182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
199282a4538fSEric Badger 	if (fpid == 0) {
1993bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
199482a4538fSEric Badger 		CPU_ZERO(&setmask);
199582a4538fSEric Badger 		CPU_SET(0, &setmask);
199682a4538fSEric Badger 		cpusetid_t setid;
199782a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
199882a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
199982a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
200082a4538fSEric Badger 
200182a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
200282a4538fSEric Badger 
200382a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
200482a4538fSEric Badger 		    (void*)&barrier) == 0);
200582a4538fSEric Badger 
2006bc2be1d3SEric Badger 		/*
2007bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2008bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2009bc2be1d3SEric Badger 		 * thread runs first.
2010bc2be1d3SEric Badger 		 */
2011bc2be1d3SEric Badger 		sched_param.sched_priority =
2012bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2013bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2014bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2015bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2016bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2017bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2018bc2be1d3SEric Badger 		    &sched_param) == 0);
2019bc2be1d3SEric Badger 
202082a4538fSEric Badger 		sigset_t sigmask;
202182a4538fSEric Badger 		sigemptyset(&sigmask);
202282a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
202382a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
202482a4538fSEric Badger 
202582a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
202682a4538fSEric Badger 		pthread_barrier_wait(&barrier);
202782a4538fSEric Badger 
202882a4538fSEric Badger 		trace_me();
202982a4538fSEric Badger 
203082a4538fSEric Badger 		for (;;)
203182a4538fSEric Badger 			sleep(60);
203282a4538fSEric Badger 
203382a4538fSEric Badger 		exit(1);
203482a4538fSEric Badger 	}
203582a4538fSEric Badger 
203682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
203782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
203882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
203982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
204082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
204182a4538fSEric Badger 
204282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
204382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
204482a4538fSEric Badger 
204582a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
204682a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
204782a4538fSEric Badger 
204882a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
204982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
205082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
205182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
205282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
205382a4538fSEric Badger 
205482a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
205582a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
205682a4538fSEric Badger 
205782a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
205882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
205982a4538fSEric Badger 
206082a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
206182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
206282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
206382a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
206482a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
206582a4538fSEric Badger 
206682a4538fSEric Badger 	wpid = wait(&status);
206782a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
206882a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
206982a4538fSEric Badger }
207082a4538fSEric Badger 
207182a4538fSEric Badger /*
207282a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
207382a4538fSEric Badger  * and prevents spurious stops caused by those events.
207482a4538fSEric Badger  */
20753cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop);
20763cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc)
20773cf56bb4SEnji Cooper {
20783cf56bb4SEnji Cooper 
20793cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
20803cf56bb4SEnji Cooper }
208182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
208282a4538fSEric Badger {
208382a4538fSEric Badger 	pid_t fpid, wpid;
2084bc2be1d3SEric Badger 	int status;
208582a4538fSEric Badger 	cpuset_t setmask;
208682a4538fSEric Badger 	pthread_t t;
208782a4538fSEric Badger 	pthread_barrier_t barrier;
208882a4538fSEric Badger 	lwpid_t main_lwp;
208982a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2090bc2be1d3SEric Badger 	struct sched_param sched_param;
209182a4538fSEric Badger 
20929777e354SLi-Wen Hsu 	if (atf_tc_get_config_var_as_bool(tc, "ci"))
20937d1f7471SLi-Wen Hsu 		atf_tc_skip("https://bugs.freebsd.org/220841");
20947d1f7471SLi-Wen Hsu 
209582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
209682a4538fSEric Badger 	if (fpid == 0) {
209782a4538fSEric Badger 		trace_me();
209882a4538fSEric Badger 
2099bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
210082a4538fSEric Badger 		CPU_ZERO(&setmask);
210182a4538fSEric Badger 		CPU_SET(0, &setmask);
210282a4538fSEric Badger 		cpusetid_t setid;
210382a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
210482a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
210582a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
210682a4538fSEric Badger 
210782a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
210882a4538fSEric Badger 
210982a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
211082a4538fSEric Badger 		    (void*)&barrier) == 0);
211182a4538fSEric Badger 
2112bc2be1d3SEric Badger 		/*
2113bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2114bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2115bc2be1d3SEric Badger 		 * thread runs first.
2116bc2be1d3SEric Badger 		 */
2117bc2be1d3SEric Badger 		sched_param.sched_priority =
2118bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2119bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2120bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2121bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2122bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2123bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2124bc2be1d3SEric Badger 		    &sched_param) == 0);
2125bc2be1d3SEric Badger 
212682a4538fSEric Badger 		sigset_t sigmask;
212782a4538fSEric Badger 		sigemptyset(&sigmask);
212882a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
212982a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
213082a4538fSEric Badger 
213182a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
213282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
213382a4538fSEric Badger 
213482a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
213582a4538fSEric Badger 		raise(SIGSTOP);
213682a4538fSEric Badger 
213782a4538fSEric Badger 		getpid();
213882a4538fSEric Badger 		exit(1);
213982a4538fSEric Badger 	}
214082a4538fSEric Badger 
214182a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
214282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
214382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
214482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
214582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
214682a4538fSEric Badger 
214782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
214882a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
214982a4538fSEric Badger 
215082a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
215182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
215282a4538fSEric Badger 
215382a4538fSEric Badger 	/*
215482a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
215582a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
215682a4538fSEric Badger 	 */
215782a4538fSEric Badger 	for (;;) {
215882a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
215982a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
216082a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
216182a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
216282a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
216382a4538fSEric Badger 			    sizeof(pl)) != -1);
216482a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
216582a4538fSEric Badger 		} else {
216682a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
216782a4538fSEric Badger 			break;
216882a4538fSEric Badger 		}
216982a4538fSEric Badger 		ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
217082a4538fSEric Badger 	}
217182a4538fSEric Badger 
2172bc2be1d3SEric Badger 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
217382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
217482a4538fSEric Badger 
217582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
217682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
217782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
217882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
217982a4538fSEric Badger 
218082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
218182a4538fSEric Badger 	    sizeof(pl)) != -1);
2182bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid == main_lwp);
218382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
2184bc2be1d3SEric Badger 	/* Prevent the main thread from hitting its syscall exit for now. */
218582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0);
218682a4538fSEric Badger 
2187bc2be1d3SEric Badger 	/*
2188bc2be1d3SEric Badger 	 * Proceed, allowing second thread to hit syscall exit for
2189bc2be1d3SEric Badger 	 * pthread_barrier_wait().
2190bc2be1d3SEric Badger 	 */
2191bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
2192bc2be1d3SEric Badger 
2193bc2be1d3SEric Badger 	wpid = waitpid(fpid, &status, 0);
2194bc2be1d3SEric Badger 	ATF_REQUIRE(wpid == fpid);
2195bc2be1d3SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2196bc2be1d3SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
2197bc2be1d3SEric Badger 
2198bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
2199bc2be1d3SEric Badger 	    sizeof(pl)) != -1);
2200bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
2201bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
220282a4538fSEric Badger 
220382a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
220482a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
220582a4538fSEric Badger 
220682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
220782a4538fSEric Badger 
2208bc2be1d3SEric Badger 	/* The next wait() should report the SIGUSR2. */
220982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
221082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
221182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
221282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
221382a4538fSEric Badger 
221482a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
221582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_RESUME, main_lwp, 0, 0) == 0);
221682a4538fSEric Badger 
221782a4538fSEric Badger 	/*
221882a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
2219bc2be1d3SEric Badger 	 * has been resumed. The second thread has taken a SIGUSR2 which will
2220bc2be1d3SEric Badger 	 * be replaced with a SIGKILL below. The main thread will get to run
2221bc2be1d3SEric Badger 	 * first. It should notice the kill request (even though the signal
2222bc2be1d3SEric Badger 	 * replacement occurred in the other thread) and exit accordingly.  It
2223bc2be1d3SEric Badger 	 * should not stop for the system call exit event.
222482a4538fSEric Badger 	 */
222582a4538fSEric Badger 
222682a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
222782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
222882a4538fSEric Badger 
222982a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
223082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
223182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
223282a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
223382a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
223482a4538fSEric Badger 
223582a4538fSEric Badger 	wpid = wait(&status);
223682a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
223782a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
223882a4538fSEric Badger }
223982a4538fSEric Badger 
224082a4538fSEric Badger static void
224182a4538fSEric Badger sigusr1_handler(int sig)
224282a4538fSEric Badger {
224382a4538fSEric Badger 
224482a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
224582a4538fSEric Badger 	_exit(2);
224682a4538fSEric Badger }
224782a4538fSEric Badger 
224882a4538fSEric Badger /*
224982a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
225082a4538fSEric Badger  * a PT_KILL will kill the process.
225182a4538fSEric Badger  */
225282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
225382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
225482a4538fSEric Badger {
225582a4538fSEric Badger 	pid_t fpid, wpid;
225682a4538fSEric Badger 	int status;
225782a4538fSEric Badger 	int max_pending_per_proc;
225882a4538fSEric Badger 	size_t len;
225982a4538fSEric Badger 	int i;
226082a4538fSEric Badger 
226182a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
226282a4538fSEric Badger 
226382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
226482a4538fSEric Badger 	if (fpid == 0) {
226582a4538fSEric Badger 		trace_me();
226682a4538fSEric Badger 		exit(1);
226782a4538fSEric Badger 	}
226882a4538fSEric Badger 
226982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
227082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
227182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
227282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
227382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
227482a4538fSEric Badger 
227582a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
227682a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
227782a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
227882a4538fSEric Badger 
227982a4538fSEric Badger 	/* Fill the signal queue. */
228082a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
228182a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
228282a4538fSEric Badger 
228382a4538fSEric Badger 	/* Kill the child process. */
228482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
228582a4538fSEric Badger 
228682a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
228782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
228882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
228982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
229082a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
229182a4538fSEric Badger 
229282a4538fSEric Badger 	wpid = wait(&status);
229382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
229482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
229582a4538fSEric Badger }
229682a4538fSEric Badger 
229782a4538fSEric Badger /*
229882a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
229982a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
230082a4538fSEric Badger  * call is complete.
230182a4538fSEric Badger  */
230282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
230382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
230482a4538fSEric Badger {
230582a4538fSEric Badger 	struct ptrace_lwpinfo pl;
230682a4538fSEric Badger 	pid_t fpid, wpid;
230782a4538fSEric Badger 	int status;
230882a4538fSEric Badger 
230982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
231082a4538fSEric Badger 
231182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
231282a4538fSEric Badger 	if (fpid == 0) {
231382a4538fSEric Badger 		trace_me();
231482a4538fSEric Badger 		getpid();
231582a4538fSEric Badger 		exit(1);
231682a4538fSEric Badger 	}
231782a4538fSEric Badger 
231882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
231982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
232082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
232182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
232282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
232382a4538fSEric Badger 
232482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
232582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
232682a4538fSEric Badger 
232782a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
232882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
232982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
233082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
233182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
233282a4538fSEric Badger 
233382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
233482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
233582a4538fSEric Badger 
233682a4538fSEric Badger 	/* Continue the child process with a signal. */
233782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
233882a4538fSEric Badger 
233982a4538fSEric Badger 	for (;;) {
234082a4538fSEric Badger 		/*
234182a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
234282a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
234382a4538fSEric Badger 		 * past any syscall stops.
234482a4538fSEric Badger 		 */
234582a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
234682a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
234782a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
234882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
234982a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
235082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
235182a4538fSEric Badger 		} else {
235282a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
235382a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
235482a4538fSEric Badger 			break;
235582a4538fSEric Badger 		}
235682a4538fSEric Badger 	}
235782a4538fSEric Badger 
235882a4538fSEric Badger 	wpid = wait(&status);
235982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
236082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
236182a4538fSEric Badger }
236282a4538fSEric Badger 
236382a4538fSEric Badger static void
236482a4538fSEric Badger sigusr1_counting_handler(int sig)
236582a4538fSEric Badger {
236682a4538fSEric Badger 	static int counter = 0;
236782a4538fSEric Badger 
236882a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
236982a4538fSEric Badger 	counter++;
237082a4538fSEric Badger 	if (counter == 2)
237182a4538fSEric Badger 		_exit(2);
237282a4538fSEric Badger }
237382a4538fSEric Badger 
237482a4538fSEric Badger /*
237582a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
237682a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
237782a4538fSEric Badger  * the system call is complete.
237882a4538fSEric Badger  */
237982a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
238082a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
238182a4538fSEric Badger {
238282a4538fSEric Badger 	struct ptrace_lwpinfo pl;
238382a4538fSEric Badger 	pid_t fpid, wpid;
238482a4538fSEric Badger 	int status;
238582a4538fSEric Badger 
238682a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
238782a4538fSEric Badger 
238882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
238982a4538fSEric Badger 	if (fpid == 0) {
239082a4538fSEric Badger 		trace_me();
239182a4538fSEric Badger 		getpid();
239282a4538fSEric Badger 		exit(1);
239382a4538fSEric Badger 	}
239482a4538fSEric Badger 
239582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
239682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
239782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
239882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
239982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
240082a4538fSEric Badger 
240182a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
240282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
240382a4538fSEric Badger 
240482a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
240582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
240682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
240782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
240882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
240982a4538fSEric Badger 
241082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
241182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
241282a4538fSEric Badger 
241382a4538fSEric Badger 	/* Continue the child process with a signal. */
241482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
241582a4538fSEric Badger 
241682a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
241782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
241882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
241982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
242082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
242182a4538fSEric Badger 
242282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
242382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
242482a4538fSEric Badger 
242582a4538fSEric Badger 	/* Continue the child process with a signal. */
242682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
242782a4538fSEric Badger 
242882a4538fSEric Badger 	for (;;) {
242982a4538fSEric Badger 		/*
243082a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
243182a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
243282a4538fSEric Badger 		 * past any syscall stops.
243382a4538fSEric Badger 		 */
243482a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
243582a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
243682a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
243782a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
243882a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
243982a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
244082a4538fSEric Badger 		} else {
244182a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
244282a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
244382a4538fSEric Badger 			break;
244482a4538fSEric Badger 		}
244582a4538fSEric Badger 	}
244682a4538fSEric Badger 
244782a4538fSEric Badger 	wpid = wait(&status);
244882a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
244982a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
245082a4538fSEric Badger }
245182a4538fSEric Badger 
245282a4538fSEric Badger /*
245382a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
245482a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
245582a4538fSEric Badger  */
245682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
245782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
245882a4538fSEric Badger {
245982a4538fSEric Badger 	pid_t fpid, wpid;
246082a4538fSEric Badger 	int status;
246182a4538fSEric Badger 	int max_pending_per_proc;
246282a4538fSEric Badger 	size_t len;
246382a4538fSEric Badger 	int i;
246482a4538fSEric Badger 
246582a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
246682a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
246782a4538fSEric Badger 
246882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
246982a4538fSEric Badger 	if (fpid == 0) {
247082a4538fSEric Badger 		trace_me();
247182a4538fSEric Badger 		exit(1);
247282a4538fSEric Badger 	}
247382a4538fSEric Badger 
247482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
247582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
247682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
247782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
247882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
247982a4538fSEric Badger 
248082a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
248182a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
248282a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
248382a4538fSEric Badger 
248482a4538fSEric Badger 	/* Fill the signal queue. */
248582a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
248682a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
248782a4538fSEric Badger 
248882a4538fSEric Badger 	/* Continue with signal. */
248982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
249082a4538fSEric Badger 
249182a4538fSEric Badger 	for (;;) {
249282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
249382a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
249482a4538fSEric Badger 		if (WIFSTOPPED(status)) {
249582a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
249682a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
249782a4538fSEric Badger 		} else {
249882a4538fSEric Badger 			/*
249982a4538fSEric Badger 			 * The last wait() should report normal _exit from the
250082a4538fSEric Badger 			 * SIGUSR1 handler.
250182a4538fSEric Badger 			 */
250282a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
250382a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
250482a4538fSEric Badger 			break;
250582a4538fSEric Badger 		}
250682a4538fSEric Badger 	}
250782a4538fSEric Badger 
250882a4538fSEric Badger 	wpid = wait(&status);
250982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
251082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
251182a4538fSEric Badger }
251282a4538fSEric Badger 
2513753e2922SBryan Drewery static sem_t sigusr1_sem;
2514753e2922SBryan Drewery static int got_usr1;
2515753e2922SBryan Drewery 
2516753e2922SBryan Drewery static void
2517753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused)
2518753e2922SBryan Drewery {
2519753e2922SBryan Drewery 
2520753e2922SBryan Drewery 	got_usr1++;
2521753e2922SBryan Drewery 	CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0);
2522753e2922SBryan Drewery }
2523753e2922SBryan Drewery 
2524753e2922SBryan Drewery /*
2525753e2922SBryan Drewery  * Verify that even if the signal queue is full for a child process,
2526753e2922SBryan Drewery  * and the signal is masked, a PT_CONTINUE with a signal will not
2527753e2922SBryan Drewery  * result in loss of that signal.
2528753e2922SBryan Drewery  */
2529753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
2530753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
2531753e2922SBryan Drewery {
2532753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2533753e2922SBryan Drewery 	pid_t fpid, wpid;
2534753e2922SBryan Drewery 	int status, err;
2535753e2922SBryan Drewery 	int max_pending_per_proc;
2536753e2922SBryan Drewery 	size_t len;
2537753e2922SBryan Drewery 	int i;
2538753e2922SBryan Drewery 	sigset_t sigmask;
2539753e2922SBryan Drewery 
2540753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
2541753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2542753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2543753e2922SBryan Drewery 
2544753e2922SBryan Drewery 	got_usr1 = 0;
2545753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2546753e2922SBryan Drewery 	if (fpid == 0) {
2547753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2548753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2549753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2550753e2922SBryan Drewery 
2551753e2922SBryan Drewery 		trace_me();
2552753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2553753e2922SBryan Drewery 
2554753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2555753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2556753e2922SBryan Drewery 		/* Wait to receive the SIGUSR1. */
2557753e2922SBryan Drewery 		do {
2558753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2559753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2560753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2561753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2562753e2922SBryan Drewery 		exit(1);
2563753e2922SBryan Drewery 	}
2564753e2922SBryan Drewery 
2565753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2566753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2567753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2568753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2569753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2570753e2922SBryan Drewery 
2571753e2922SBryan Drewery 	len = sizeof(max_pending_per_proc);
2572753e2922SBryan Drewery 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
2573753e2922SBryan Drewery 	    &max_pending_per_proc, &len, NULL, 0) == 0);
2574753e2922SBryan Drewery 
2575753e2922SBryan Drewery 	/* Fill the signal queue. */
2576753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i)
2577753e2922SBryan Drewery 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
2578753e2922SBryan Drewery 
2579753e2922SBryan Drewery 	/* Continue with signal. */
2580753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2581753e2922SBryan Drewery 
2582753e2922SBryan Drewery 	/* Collect and ignore all of the SIGUSR2. */
2583753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i) {
2584753e2922SBryan Drewery 		wpid = waitpid(fpid, &status, 0);
2585753e2922SBryan Drewery 		ATF_REQUIRE(wpid == fpid);
2586753e2922SBryan Drewery 		ATF_REQUIRE(WIFSTOPPED(status));
2587753e2922SBryan Drewery 		ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
2588753e2922SBryan Drewery 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2589753e2922SBryan Drewery 	}
2590753e2922SBryan Drewery 
2591753e2922SBryan Drewery 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
2592753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2593753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2594753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2595753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2596753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2597753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2598753e2922SBryan Drewery 
2599753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
2600753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2601753e2922SBryan Drewery 
2602753e2922SBryan Drewery 	/* The last wait() should report exit after receiving SIGUSR1. */
2603753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2604753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2605753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2606753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2607753e2922SBryan Drewery 
2608753e2922SBryan Drewery 	wpid = wait(&status);
2609753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2610753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2611753e2922SBryan Drewery }
2612753e2922SBryan Drewery 
261382a4538fSEric Badger /*
261482a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
261582a4538fSEric Badger  * replaced with another signal.
261682a4538fSEric Badger  */
261782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
261882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
261982a4538fSEric Badger {
262082a4538fSEric Badger 	struct ptrace_lwpinfo pl;
262182a4538fSEric Badger 	pid_t fpid, wpid;
262282a4538fSEric Badger 	int status;
262382a4538fSEric Badger 
262482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
262582a4538fSEric Badger 	if (fpid == 0) {
262682a4538fSEric Badger 		trace_me();
262782a4538fSEric Badger 		sleep(20);
262882a4538fSEric Badger 		exit(1);
262982a4538fSEric Badger 	}
263082a4538fSEric Badger 
263182a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
263282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
263382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
263482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
263582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
263682a4538fSEric Badger 
263782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
263882a4538fSEric Badger 
263982a4538fSEric Badger 	/* Send a signal without ptrace. */
264082a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGINT) == 0);
264182a4538fSEric Badger 
264282a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
264382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
264482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
264582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
264682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGINT);
264782a4538fSEric Badger 
264882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
264982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
265082a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGINT);
265182a4538fSEric Badger 
265282a4538fSEric Badger 	/* Continue the child process with a different signal. */
265382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM) == 0);
265482a4538fSEric Badger 
265582a4538fSEric Badger 	/*
265682a4538fSEric Badger 	 * The last wait() should report having died due to the new
265782a4538fSEric Badger 	 * signal, SIGTERM.
265882a4538fSEric Badger 	 */
265982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
266082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
266182a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
266282a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGTERM);
266382a4538fSEric Badger 
266482a4538fSEric Badger 	wpid = wait(&status);
266582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
266682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
266782a4538fSEric Badger }
266882a4538fSEric Badger 
266982a4538fSEric Badger /*
267082a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
267182a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
267282a4538fSEric Badger  * invented for e.g, system call stops.
267382a4538fSEric Badger  */
267482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
267582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
267682a4538fSEric Badger {
267782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2678fc1e29dcSBryan Drewery 	struct rlimit rl;
267982a4538fSEric Badger 	pid_t fpid, wpid;
268082a4538fSEric Badger 	int status;
268182a4538fSEric Badger 
268282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
268382a4538fSEric Badger 	if (fpid == 0) {
268482a4538fSEric Badger 		trace_me();
2685fc1e29dcSBryan Drewery 		/* SIGTRAP expected to cause exit on syscall entry. */
2686fc1e29dcSBryan Drewery 		rl.rlim_cur = rl.rlim_max = 0;
2687fc1e29dcSBryan Drewery 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0);
268882a4538fSEric Badger 		getpid();
268982a4538fSEric Badger 		exit(1);
269082a4538fSEric Badger 	}
269182a4538fSEric Badger 
269282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
269382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
269482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
269582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
269682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
269782a4538fSEric Badger 
269882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
269982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
270082a4538fSEric Badger 
270182a4538fSEric Badger 	/* The second wait() should report a system call entry 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_SCE);
270982a4538fSEric Badger 
271082a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
271182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP) == 0);
271282a4538fSEric Badger 
271382a4538fSEric Badger 	for (;;) {
271482a4538fSEric Badger 		/*
271582a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
271682a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
271782a4538fSEric Badger 		 */
271882a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
271982a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
272082a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
272182a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
272282a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
272382a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
272482a4538fSEric Badger 		} else {
272582a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
272682a4538fSEric Badger 			ATF_REQUIRE(WTERMSIG(status) == SIGTRAP);
272782a4538fSEric Badger 			break;
272882a4538fSEric Badger 		}
272982a4538fSEric Badger 	}
273082a4538fSEric Badger 
273182a4538fSEric Badger 	wpid = wait(&status);
273282a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
273382a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
273482a4538fSEric Badger 
273582a4538fSEric Badger }
273682a4538fSEric Badger 
273782a4538fSEric Badger /*
273882a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
273982a4538fSEric Badger  */
274082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
274182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
274282a4538fSEric Badger {
274382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
274482a4538fSEric Badger 	pid_t fpid, wpid;
274582a4538fSEric Badger 	int status;
274682a4538fSEric Badger 
274782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
274882a4538fSEric Badger 
274982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
275082a4538fSEric Badger 	if (fpid == 0) {
275182a4538fSEric Badger 		trace_me();
275282a4538fSEric Badger 		getpid();
275382a4538fSEric Badger 		exit(1);
275482a4538fSEric Badger 	}
275582a4538fSEric Badger 
275682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
275782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
275882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
275982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
276082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
276182a4538fSEric Badger 
276282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
276382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
276482a4538fSEric Badger 
276582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
276682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
276782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
276882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
276982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
277082a4538fSEric Badger 
277182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
277282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
277382a4538fSEric Badger 
277482a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
277582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
277682a4538fSEric Badger 
277782a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
277882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
277982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
278082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
278182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
278282a4538fSEric Badger 
278382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
278482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
278582a4538fSEric Badger 
278682a4538fSEric Badger 	/* Send an ABRT without ptrace. */
278782a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGABRT) == 0);
278882a4538fSEric Badger 
278982a4538fSEric Badger 	/* Continue normally. */
279082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
279182a4538fSEric Badger 
279282a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
279382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
279482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
279582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
279682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
279782a4538fSEric Badger 
279882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
279982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
280082a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
280182a4538fSEric Badger 
280282a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
280382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
280482a4538fSEric Badger 
280582a4538fSEric Badger 	for (;;) {
280682a4538fSEric Badger 		/*
280782a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
280882a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
280982a4538fSEric Badger 		 * past any syscall stops.
281082a4538fSEric Badger 		 */
281182a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
281282a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
281382a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
281482a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
281582a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
281682a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
281782a4538fSEric Badger 		} else {
281882a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
281982a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
282082a4538fSEric Badger 			break;
282182a4538fSEric Badger 		}
282282a4538fSEric Badger 	}
282382a4538fSEric Badger 
282482a4538fSEric Badger 	wpid = wait(&status);
282582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
282682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
282782a4538fSEric Badger 
282882a4538fSEric Badger }
282982a4538fSEric Badger 
283082a4538fSEric Badger /*
283182a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
283282a4538fSEric Badger  */
283382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
283482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
283582a4538fSEric Badger {
283682a4538fSEric Badger 	pid_t fpid, wpid;
283782a4538fSEric Badger 	int status, kq, nevents;
283882a4538fSEric Badger 	struct kevent kev;
283982a4538fSEric Badger 
284082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
284182a4538fSEric Badger 
284282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
284382a4538fSEric Badger 	if (fpid == 0) {
284482a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
284582a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
284682a4538fSEric Badger 		CHILD_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0);
284782a4538fSEric Badger 
284882a4538fSEric Badger 		trace_me();
284982a4538fSEric Badger 
285082a4538fSEric Badger 		for (;;) {
285182a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
285282a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
285382a4538fSEric Badger 				continue;
285482a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
285582a4538fSEric Badger 			CHILD_REQUIRE(kev.filter == EVFILT_SIGNAL);
285682a4538fSEric Badger 			CHILD_REQUIRE(kev.ident == SIGUSR1);
285782a4538fSEric Badger 			break;
285882a4538fSEric Badger 		}
285982a4538fSEric Badger 
286082a4538fSEric Badger 		exit(1);
286182a4538fSEric Badger 	}
286282a4538fSEric Badger 
286382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
286482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
286582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
286682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
286782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
286882a4538fSEric Badger 
286982a4538fSEric Badger 	/* Continue with the SIGUSR1. */
287082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
287182a4538fSEric Badger 
287282a4538fSEric Badger 	/*
287382a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
287482a4538fSEric Badger 	 */
287582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
287682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
287782a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
287882a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
287982a4538fSEric Badger 
288082a4538fSEric Badger 	wpid = wait(&status);
288182a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
288282a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
288382a4538fSEric Badger }
288482a4538fSEric Badger 
288582a4538fSEric Badger static void *
288682a4538fSEric Badger signal_thread(void *arg)
288782a4538fSEric Badger {
288882a4538fSEric Badger 	int err;
288982a4538fSEric Badger 	sigset_t sigmask;
289082a4538fSEric Badger 
289182a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
289282a4538fSEric Badger 
289382a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
289482a4538fSEric Badger 	do {
289582a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
289682a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
289782a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
289882a4538fSEric Badger 
289982a4538fSEric Badger 	/* Free our companion thread from the barrier. */
290082a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
290182a4538fSEric Badger 
290282a4538fSEric Badger 	/*
290382a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
290482a4538fSEric Badger 	 * other thread.
290582a4538fSEric Badger 	 */
290682a4538fSEric Badger 	CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
290782a4538fSEric Badger 	CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
290882a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
290982a4538fSEric Badger 
291082a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
291182a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
291282a4538fSEric Badger 
291382a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
291482a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
291582a4538fSEric Badger 
291682a4538fSEric Badger 	return (NULL);
291782a4538fSEric Badger }
291882a4538fSEric Badger 
291982a4538fSEric Badger /*
2920753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2921753e2922SBryan Drewery  * signal from kill() once unmasked.
2922753e2922SBryan Drewery  */
2923753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
2924753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
2925753e2922SBryan Drewery {
2926753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2927753e2922SBryan Drewery 	pid_t fpid, wpid;
2928753e2922SBryan Drewery 	int status, err;
2929753e2922SBryan Drewery 	sigset_t sigmask;
2930753e2922SBryan Drewery 
2931753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2932753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2933753e2922SBryan Drewery 	got_usr1 = 0;
2934753e2922SBryan Drewery 
2935753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2936753e2922SBryan Drewery 	if (fpid == 0) {
2937753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2938753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2939753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2940753e2922SBryan Drewery 
2941753e2922SBryan Drewery 		trace_me();
2942753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2943753e2922SBryan Drewery 
2944753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2945753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2946753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2947753e2922SBryan Drewery 		do {
2948753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2949753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2950753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2951753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2952753e2922SBryan Drewery 		exit(1);
2953753e2922SBryan Drewery 	}
2954753e2922SBryan Drewery 
2955753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2956753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2957753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2958753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2959753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2960753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2961753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
2962753e2922SBryan Drewery 
2963753e2922SBryan Drewery 	/* Send blocked SIGUSR1 which should cause a stop. */
2964753e2922SBryan Drewery 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
2965753e2922SBryan Drewery 
2966753e2922SBryan Drewery 	/* Continue the child ignoring the SIGSTOP. */
2967753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2968753e2922SBryan Drewery 
2969753e2922SBryan Drewery 	/* The next wait() should report the kill(SIGUSR1) was received. */
2970753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2971753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2972753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2973753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2974753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2975753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2976753e2922SBryan Drewery 
2977753e2922SBryan Drewery 	/* Continue the child, allowing in the SIGUSR1. */
2978753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2979753e2922SBryan Drewery 
2980753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
2981753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2982753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2983753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2984753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2985753e2922SBryan Drewery 
2986753e2922SBryan Drewery 	wpid = wait(&status);
2987753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2988753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2989753e2922SBryan Drewery }
2990753e2922SBryan Drewery 
2991753e2922SBryan Drewery /*
2992753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2993753e2922SBryan Drewery  * signal from PT_CONTINUE once unmasked.
2994753e2922SBryan Drewery  */
2995753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
2996753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
2997753e2922SBryan Drewery {
2998753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2999753e2922SBryan Drewery 	pid_t fpid, wpid;
3000753e2922SBryan Drewery 	int status, err;
3001753e2922SBryan Drewery 	sigset_t sigmask;
3002753e2922SBryan Drewery 
3003753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
3004753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
3005753e2922SBryan Drewery 	got_usr1 = 0;
3006753e2922SBryan Drewery 
3007753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
3008753e2922SBryan Drewery 	if (fpid == 0) {
3009753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
3010753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
3011753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
3012753e2922SBryan Drewery 
3013753e2922SBryan Drewery 		trace_me();
3014753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
3015753e2922SBryan Drewery 
3016753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
3017753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
3018753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
3019753e2922SBryan Drewery 		do {
3020753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
3021753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
3022753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
3023753e2922SBryan Drewery 
3024753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
3025753e2922SBryan Drewery 		exit(1);
3026753e2922SBryan Drewery 	}
3027753e2922SBryan Drewery 
3028753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
3029753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3030753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
3031753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
3032753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3033753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
3034753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
3035753e2922SBryan Drewery 
3036753e2922SBryan Drewery 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
3037753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
3038753e2922SBryan Drewery 
3039753e2922SBryan Drewery 	/* The next wait() should report the SIGUSR1 was received. */
3040753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3041753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
3042753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
3043753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
3044753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
3045753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
3046753e2922SBryan Drewery 
3047753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
3048753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3049753e2922SBryan Drewery 
3050753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3051753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
3052753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
3053753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
3054753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3055753e2922SBryan Drewery 
3056753e2922SBryan Drewery 	wpid = wait(&status);
3057753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
3058753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
3059753e2922SBryan Drewery }
3060753e2922SBryan Drewery 
3061753e2922SBryan Drewery /*
306282a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
306382a4538fSEric Badger  * a different signal that the new signal is routed to a thread
306499144520SEitan Adler  * that can accept it, and that the thread is awakened by the signal
306582a4538fSEric Badger  * in a timely manner.
306682a4538fSEric Badger  */
306782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
306882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
306982a4538fSEric Badger {
307082a4538fSEric Badger 	pid_t fpid, wpid;
307182a4538fSEric Badger 	int status, err;
307282a4538fSEric Badger 	pthread_t t;
307382a4538fSEric Badger 	sigset_t sigmask;
307482a4538fSEric Badger 	pthread_barrier_t barrier;
307582a4538fSEric Badger 
307682a4538fSEric Badger 	ATF_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
307782a4538fSEric Badger 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
307882a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
307982a4538fSEric Badger 
308082a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
308182a4538fSEric Badger 	if (fpid == 0) {
308282a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, signal_thread, (void*)&barrier) == 0);
308382a4538fSEric Badger 
308482a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
308582a4538fSEric Badger 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
308682a4538fSEric Badger 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
308782a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
308882a4538fSEric Badger 
308982a4538fSEric Badger 		trace_me();
309082a4538fSEric Badger 
309182a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
309282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
309382a4538fSEric Badger 
309482a4538fSEric Badger 		/*
309582a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
309682a4538fSEric Badger 		 * thread.
309782a4538fSEric Badger 		 */
309882a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
309982a4538fSEric Badger 
310082a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
310182a4538fSEric Badger 		pthread_barrier_wait(&barrier);
310282a4538fSEric Badger 
310382a4538fSEric Badger 		/*
310482a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
310582a4538fSEric Badger 		 * now.
310682a4538fSEric Badger 		 */
310782a4538fSEric Badger 		raise(SIGSTOP);
310882a4538fSEric Badger 
310982a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
311082a4538fSEric Badger 		do {
311182a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
311282a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
311382a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
311482a4538fSEric Badger 
311582a4538fSEric Badger 		/* Free the other thread from the barrier. */
311682a4538fSEric Badger 		pthread_barrier_wait(&barrier);
311782a4538fSEric Badger 
311882a4538fSEric Badger 		CHILD_REQUIRE(pthread_join(t, NULL) == 0);
311982a4538fSEric Badger 
312082a4538fSEric Badger 		exit(1);
312182a4538fSEric Badger 	}
312282a4538fSEric Badger 
312382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
312482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
312582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
312682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
312782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
312882a4538fSEric Badger 
312982a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
313082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
313182a4538fSEric Badger 
313282a4538fSEric Badger 	/*
313382a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
313482a4538fSEric Badger 	 * in this case).
313582a4538fSEric Badger 	 */
313682a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
313782a4538fSEric Badger 
313882a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
313982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
314082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
314182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
314282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
314382a4538fSEric Badger 
314482a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
314582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
314682a4538fSEric Badger 
314782a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
314882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
314982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
315082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
315182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
315282a4538fSEric Badger 
315382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
315482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
315582a4538fSEric Badger 
315682a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
315782a4538fSEric Badger 
315882a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
315982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
316082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
316182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
316282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
316382a4538fSEric Badger 
316482a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
316582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
316682a4538fSEric Badger 
316782a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
316882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
316982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
317082a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
317182a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
317282a4538fSEric Badger 
317382a4538fSEric Badger 	wpid = wait(&status);
317482a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
317582a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
317682a4538fSEric Badger }
317782a4538fSEric Badger 
3178b38bd91fSEric Badger static void *
3179b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
3180b38bd91fSEric Badger {
3181b38bd91fSEric Badger 
3182b38bd91fSEric Badger 	raise(SIGSTOP);
3183b38bd91fSEric Badger 	return NULL;
3184b38bd91fSEric Badger }
3185b38bd91fSEric Badger 
3186b38bd91fSEric Badger static void *
3187b38bd91fSEric Badger sleep_thread(void *arg __unused)
3188b38bd91fSEric Badger {
3189b38bd91fSEric Badger 
3190b38bd91fSEric Badger 	sleep(60);
3191b38bd91fSEric Badger 	return NULL;
3192b38bd91fSEric Badger }
3193b38bd91fSEric Badger 
3194b38bd91fSEric Badger static void
3195b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
3196b38bd91fSEric Badger {
3197b38bd91fSEric Badger 	pid_t fpid, wpid;
3198b38bd91fSEric Badger 	int status, i;
3199b38bd91fSEric Badger 	cpuset_t setmask;
3200b38bd91fSEric Badger 	cpusetid_t setid;
3201b38bd91fSEric Badger 	pthread_t t;
3202b38bd91fSEric Badger 
3203b38bd91fSEric Badger 	/*
3204b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
3205b38bd91fSEric Badger 	 * that both child and grandchild have died.
3206b38bd91fSEric Badger 	 */
3207b38bd91fSEric Badger 	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
3208b38bd91fSEric Badger 
3209b38bd91fSEric Badger 	fpid = fork();
3210b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
3211b38bd91fSEric Badger 	if (fpid == 0) {
3212b38bd91fSEric Badger 		fpid = fork();
3213b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
3214b38bd91fSEric Badger 		if (fpid == 0) {
3215b38bd91fSEric Badger 			trace_me();
3216b38bd91fSEric Badger 
3217b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
3218b38bd91fSEric Badger 			CPU_ZERO(&setmask);
3219b38bd91fSEric Badger 			CPU_SET(0, &setmask);
3220b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset(&setid) == 0);
3221b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
3222b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
3223b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
3224b38bd91fSEric Badger 
3225b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
3226b38bd91fSEric Badger 				/*
3227b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
3228b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
3229b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
3230b38bd91fSEric Badger 				 * threads compete.
3231b38bd91fSEric Badger 				 */
3232b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3233b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
3234b38bd91fSEric Badger 				raise(SIGSTOP);
3235b38bd91fSEric Badger 			} else {
3236b38bd91fSEric Badger 				/*
3237b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
3238b38bd91fSEric Badger 				 * this thread. After creating the new thread,
3239b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
3240b38bd91fSEric Badger 				 * raise the SIGSTOP.
3241b38bd91fSEric Badger 				 */
3242b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3243b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
3244b38bd91fSEric Badger 				sleep(60);
3245b38bd91fSEric Badger 			}
3246b38bd91fSEric Badger 
3247b38bd91fSEric Badger 			exit(0);
3248b38bd91fSEric Badger 		}
3249b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
3250b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3251b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
3252b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3253b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3254b38bd91fSEric Badger 
3255b38bd91fSEric Badger 		CHILD_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3256b38bd91fSEric Badger 
3257b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
3258b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3259b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
3260b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3261b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3262b38bd91fSEric Badger 
3263b38bd91fSEric Badger 		/*
3264b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
3265b38bd91fSEric Badger 		 * should be killed.
3266b38bd91fSEric Badger 		 */
3267b38bd91fSEric Badger 		exit(0);
3268b38bd91fSEric Badger 	}
3269b38bd91fSEric Badger 
3270b38bd91fSEric Badger 	/*
3271b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
3272b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
3273b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
3274b38bd91fSEric Badger 	 * left dangling when its parent died.
3275b38bd91fSEric Badger 	 */
3276b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
3277b38bd91fSEric Badger 		wpid = wait(&status);
3278b38bd91fSEric Badger 		if (wpid == fpid)
3279b38bd91fSEric Badger 			ATF_REQUIRE(WIFEXITED(status) &&
3280b38bd91fSEric Badger 			    WEXITSTATUS(status) == 0);
3281b38bd91fSEric Badger 		else
3282b38bd91fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status) &&
3283b38bd91fSEric Badger 			    WTERMSIG(status) == SIGKILL);
3284b38bd91fSEric Badger 	}
3285b38bd91fSEric Badger }
3286b38bd91fSEric Badger 
3287b38bd91fSEric Badger /*
3288b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
3289b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
3290b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
3291b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
3292b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
3293b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
3294b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
3295b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
3296b38bd91fSEric Badger  * past, so make no assumption.
3297b38bd91fSEric Badger  */
32983cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
32993cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
33003cf56bb4SEnji Cooper {
33013cf56bb4SEnji Cooper 
33023cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33033cf56bb4SEnji Cooper }
3304b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
3305b38bd91fSEric Badger {
3306b38bd91fSEric Badger 
3307b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
3308b38bd91fSEric Badger }
33093cf56bb4SEnji Cooper 
33103cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
33113cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
33123cf56bb4SEnji Cooper {
33133cf56bb4SEnji Cooper 
33143cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33153cf56bb4SEnji Cooper }
3316b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
3317b38bd91fSEric Badger {
3318b38bd91fSEric Badger 
3319b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
3320b38bd91fSEric Badger }
3321b38bd91fSEric Badger 
3322b4d33259SEric Badger /*
3323b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
3324b4d33259SEric Badger  * is not modified.
3325b4d33259SEric Badger  */
3326b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
3327b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
3328b4d33259SEric Badger {
3329b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
3330b4d33259SEric Badger 	pid_t fpid, wpid;
3331b4d33259SEric Badger 	int status, event_mask, new_event_mask;
3332b4d33259SEric Badger 
3333b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
3334b4d33259SEric Badger 	if (fpid == 0) {
3335b4d33259SEric Badger 		trace_me();
3336b4d33259SEric Badger 		raise(SIGSTOP);
3337b4d33259SEric Badger 		exit(0);
3338b4d33259SEric Badger 	}
3339b4d33259SEric Badger 
3340b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
3341b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3342b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3343b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3344b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3345b4d33259SEric Badger 
3346b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
3347b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
3348b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
3349b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
3350b4d33259SEric Badger 
3351b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
3352b4d33259SEric Badger 	ATF_REQUIRE(kill(fpid, SIGKILL) == 0);
3353b4d33259SEric Badger 
3354b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
3355b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3356b4d33259SEric Badger 
3357b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
3358b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3359b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3360b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3361b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGKILL);
3362b4d33259SEric Badger 
3363b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3364b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3365b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGKILL);
3366b4d33259SEric Badger 
3367b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
3368b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3369b4d33259SEric Badger 
3370b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
3371b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3372b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3373b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3374b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3375b4d33259SEric Badger 
3376b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
3377b4d33259SEric Badger 	new_event_mask = 0;
3378b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
3379b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
3380b4d33259SEric Badger 	ATF_REQUIRE(event_mask == new_event_mask);
3381b4d33259SEric Badger 
3382b4d33259SEric Badger 	/* Continue the child to let it exit. */
3383b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3384b4d33259SEric Badger 
3385b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
3386b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3387b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
3388b4d33259SEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
3389b4d33259SEric Badger 
3390b4d33259SEric Badger 	wpid = wait(&status);
3391b4d33259SEric Badger 	ATF_REQUIRE(wpid == -1);
3392b4d33259SEric Badger 	ATF_REQUIRE(errno == ECHILD);
3393b4d33259SEric Badger }
3394b4d33259SEric Badger 
3395d74da94cSMark Johnston static void *
3396d74da94cSMark Johnston flock_thread(void *arg)
3397d74da94cSMark Johnston {
3398d74da94cSMark Johnston 	int fd;
3399d74da94cSMark Johnston 
3400d74da94cSMark Johnston 	fd = *(int *)arg;
3401d74da94cSMark Johnston 	(void)flock(fd, LOCK_EX);
3402d74da94cSMark Johnston 	(void)flock(fd, LOCK_UN);
3403d74da94cSMark Johnston 	return (NULL);
3404d74da94cSMark Johnston }
3405d74da94cSMark Johnston 
3406d74da94cSMark Johnston /*
3407d74da94cSMark Johnston  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
3408d74da94cSMark Johnston  * We rely on the fact that the lockf implementation sets SBDRY before blocking
3409d74da94cSMark Johnston  * on a lock. This is a regression test for r318191.
3410d74da94cSMark Johnston  */
3411d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
3412d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
3413d74da94cSMark Johnston {
3414d74da94cSMark Johnston 	pthread_barrier_t barrier;
3415d74da94cSMark Johnston 	pthread_barrierattr_t battr;
3416d74da94cSMark Johnston 	char tmpfile[64];
3417d74da94cSMark Johnston 	pid_t child, wpid;
3418d74da94cSMark Johnston 	int error, fd, i, status;
3419d74da94cSMark Johnston 
3420d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_init(&battr) == 0);
3421d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
3422d74da94cSMark Johnston 	    PTHREAD_PROCESS_SHARED) == 0);
3423d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrier_init(&barrier, &battr, 2) == 0);
3424d74da94cSMark Johnston 
3425d74da94cSMark Johnston 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
3426d74da94cSMark Johnston 	fd = mkstemp(tmpfile);
3427d74da94cSMark Johnston 	ATF_REQUIRE(fd >= 0);
3428d74da94cSMark Johnston 
3429d74da94cSMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
3430d74da94cSMark Johnston 	if (child == 0) {
3431d74da94cSMark Johnston 		pthread_t t[2];
343296437391SBryan Drewery 		int cfd;
3433d74da94cSMark Johnston 
3434d74da94cSMark Johnston 		error = pthread_barrier_wait(&barrier);
3435d74da94cSMark Johnston 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
3436d74da94cSMark Johnston 			_exit(1);
3437d74da94cSMark Johnston 
3438d74da94cSMark Johnston 		cfd = open(tmpfile, O_RDONLY);
3439d74da94cSMark Johnston 		if (cfd < 0)
3440d74da94cSMark Johnston 			_exit(1);
3441d74da94cSMark Johnston 
3442d74da94cSMark Johnston 		/*
3443d74da94cSMark Johnston 		 * We want at least two threads blocked on the file lock since
3444d74da94cSMark Johnston 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
3445d74da94cSMark Johnston 		 * sleep.
3446d74da94cSMark Johnston 		 */
3447d74da94cSMark Johnston 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
3448d74da94cSMark Johnston 			_exit(1);
3449d74da94cSMark Johnston 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
3450d74da94cSMark Johnston 			_exit(1);
3451d74da94cSMark Johnston 		if (pthread_join(t[0], NULL) != 0)
3452d74da94cSMark Johnston 			_exit(1);
3453d74da94cSMark Johnston 		if (pthread_join(t[1], NULL) != 0)
3454d74da94cSMark Johnston 			_exit(1);
3455d74da94cSMark Johnston 		_exit(0);
3456d74da94cSMark Johnston 	}
3457d74da94cSMark Johnston 
3458d74da94cSMark Johnston 	ATF_REQUIRE(flock(fd, LOCK_EX) == 0);
3459d74da94cSMark Johnston 
3460d74da94cSMark Johnston 	error = pthread_barrier_wait(&barrier);
3461d74da94cSMark Johnston 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
3462d74da94cSMark Johnston 
3463d74da94cSMark Johnston 	/*
3464d74da94cSMark Johnston 	 * Give the child some time to block. Is there a better way to do this?
3465d74da94cSMark Johnston 	 */
3466d74da94cSMark Johnston 	sleep(1);
3467d74da94cSMark Johnston 
3468d74da94cSMark Johnston 	/*
3469d74da94cSMark Johnston 	 * Attach and give the child 3 seconds to stop.
3470d74da94cSMark Johnston 	 */
3471d74da94cSMark Johnston 	ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0);
3472d74da94cSMark Johnston 	for (i = 0; i < 3; i++) {
3473d74da94cSMark Johnston 		wpid = waitpid(child, &status, WNOHANG);
3474d74da94cSMark Johnston 		if (wpid == child && WIFSTOPPED(status) &&
3475d74da94cSMark Johnston 		    WSTOPSIG(status) == SIGSTOP)
3476d74da94cSMark Johnston 			break;
3477d74da94cSMark Johnston 		sleep(1);
3478d74da94cSMark Johnston 	}
3479d74da94cSMark Johnston 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
3480d74da94cSMark Johnston 
3481d74da94cSMark Johnston 	ATF_REQUIRE(ptrace(PT_DETACH, child, NULL, 0) == 0);
3482d74da94cSMark Johnston 
3483d74da94cSMark Johnston 	ATF_REQUIRE(flock(fd, LOCK_UN) == 0);
3484d74da94cSMark Johnston 	ATF_REQUIRE(unlink(tmpfile) == 0);
3485d74da94cSMark Johnston 	ATF_REQUIRE(close(fd) == 0);
3486d74da94cSMark Johnston }
3487d74da94cSMark Johnston 
348854cfb29eSJohn Baldwin static void
348954cfb29eSJohn Baldwin sigusr1_step_handler(int sig)
349054cfb29eSJohn Baldwin {
349154cfb29eSJohn Baldwin 
349254cfb29eSJohn Baldwin 	CHILD_REQUIRE(sig == SIGUSR1);
349354cfb29eSJohn Baldwin 	raise(SIGABRT);
349454cfb29eSJohn Baldwin }
349554cfb29eSJohn Baldwin 
349654cfb29eSJohn Baldwin /*
349754cfb29eSJohn Baldwin  * Verify that PT_STEP with a signal invokes the signal before
349854cfb29eSJohn Baldwin  * stepping the next instruction (and that the next instruction is
349954cfb29eSJohn Baldwin  * stepped correctly).
350054cfb29eSJohn Baldwin  */
350154cfb29eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal);
350254cfb29eSJohn Baldwin ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
350354cfb29eSJohn Baldwin {
350454cfb29eSJohn Baldwin 	struct ptrace_lwpinfo pl;
350554cfb29eSJohn Baldwin 	pid_t fpid, wpid;
350654cfb29eSJohn Baldwin 	int status;
350754cfb29eSJohn Baldwin 
350854cfb29eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
350954cfb29eSJohn Baldwin 	if (fpid == 0) {
351054cfb29eSJohn Baldwin 		trace_me();
351154cfb29eSJohn Baldwin 		signal(SIGUSR1, sigusr1_step_handler);
351254cfb29eSJohn Baldwin 		raise(SIGABRT);
351354cfb29eSJohn Baldwin 		exit(1);
351454cfb29eSJohn Baldwin 	}
351554cfb29eSJohn Baldwin 
351654cfb29eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
351754cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
351854cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
351954cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
352054cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
352154cfb29eSJohn Baldwin 
352254cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
352354cfb29eSJohn Baldwin 
352454cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
352554cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
352654cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
352754cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
352854cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
352954cfb29eSJohn Baldwin 
353054cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
353154cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
353254cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
353354cfb29eSJohn Baldwin 
353454cfb29eSJohn Baldwin 	/* Step the child process inserting SIGUSR1. */
353554cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1) == 0);
353654cfb29eSJohn Baldwin 
353754cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the signal handler. */
353854cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
353954cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
354054cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
354154cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
354254cfb29eSJohn Baldwin 
354354cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
354454cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
354554cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
354654cfb29eSJohn Baldwin 
354754cfb29eSJohn Baldwin 	/* Continue the child process discarding the signal. */
354854cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
354954cfb29eSJohn Baldwin 
355054cfb29eSJohn Baldwin 	/* The next stop should report a trace trap from PT_STEP. */
355154cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
355254cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
355354cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
355454cfb29eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
355554cfb29eSJohn Baldwin 
355654cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
355754cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
355854cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
355954cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE);
356054cfb29eSJohn Baldwin 
356154cfb29eSJohn Baldwin 	/* Continue the child to let it exit. */
356254cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
356354cfb29eSJohn Baldwin 
356454cfb29eSJohn Baldwin 	/* The last event should be for the child process's exit. */
356554cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
356654cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
356754cfb29eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
356854cfb29eSJohn Baldwin 
356954cfb29eSJohn Baldwin 	wpid = wait(&status);
357054cfb29eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
357154cfb29eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
357254cfb29eSJohn Baldwin }
357354cfb29eSJohn Baldwin 
3574643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3575643ce7deSJohn Baldwin /*
3576643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported
3577643ce7deSJohn Baldwin  * for a breakpoint trap.
3578643ce7deSJohn Baldwin  */
3579643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo);
3580643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__breakpoint_siginfo, tc)
3581643ce7deSJohn Baldwin {
3582643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3583643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3584643ce7deSJohn Baldwin 	int status;
3585643ce7deSJohn Baldwin 
3586643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3587643ce7deSJohn Baldwin 	if (fpid == 0) {
3588643ce7deSJohn Baldwin 		trace_me();
3589643ce7deSJohn Baldwin 		breakpoint();
3590643ce7deSJohn Baldwin 		exit(1);
3591643ce7deSJohn Baldwin 	}
3592643ce7deSJohn Baldwin 
3593643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3594643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3595643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3596643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3597643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3598643ce7deSJohn Baldwin 
3599643ce7deSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
3600643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3601643ce7deSJohn Baldwin 
3602643ce7deSJohn Baldwin 	/* The second wait() should report hitting the breakpoint. */
3603643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3604643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3605643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3606643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3607643ce7deSJohn Baldwin 
3608643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3609643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3610643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
3611643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_BRKPT);
3612643ce7deSJohn Baldwin 
3613643ce7deSJohn Baldwin 	/* Kill the child process. */
3614643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
3615643ce7deSJohn Baldwin 
3616643ce7deSJohn Baldwin 	/* The last wait() should report the SIGKILL. */
3617643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3618643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3619643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSIGNALED(status));
3620643ce7deSJohn Baldwin 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
3621643ce7deSJohn Baldwin 
3622643ce7deSJohn Baldwin 	wpid = wait(&status);
3623643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3624643ce7deSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3625643ce7deSJohn Baldwin }
3626643ce7deSJohn Baldwin #endif /* HAVE_BREAKPOINT */
3627643ce7deSJohn Baldwin 
3628643ce7deSJohn Baldwin /*
3629643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_TRACE code is reported
3630643ce7deSJohn Baldwin  * for a single-step trap from PT_STEP.
3631643ce7deSJohn Baldwin  */
3632643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo);
3633643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__step_siginfo, tc)
3634643ce7deSJohn Baldwin {
3635643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3636643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3637643ce7deSJohn Baldwin 	int status;
3638643ce7deSJohn Baldwin 
3639643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3640643ce7deSJohn Baldwin 	if (fpid == 0) {
3641643ce7deSJohn Baldwin 		trace_me();
3642643ce7deSJohn Baldwin 		exit(1);
3643643ce7deSJohn Baldwin 	}
3644643ce7deSJohn Baldwin 
3645643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3646643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3647643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3648643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3649643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3650643ce7deSJohn Baldwin 
3651643ce7deSJohn Baldwin 	/* Step the child ignoring the SIGSTOP. */
3652643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, 0) == 0);
3653643ce7deSJohn Baldwin 
3654643ce7deSJohn Baldwin 	/* The second wait() should report a single-step trap. */
3655643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3656643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3657643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3658643ce7deSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3659643ce7deSJohn Baldwin 
3660643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3661643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3662643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
3663643ce7deSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE);
3664643ce7deSJohn Baldwin 
3665643ce7deSJohn Baldwin 	/* Continue the child process. */
3666643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3667643ce7deSJohn Baldwin 
3668643ce7deSJohn Baldwin 	/* The last event should be for the child process's exit. */
3669643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3670643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3671643ce7deSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3672643ce7deSJohn Baldwin 
3673643ce7deSJohn Baldwin 	wpid = wait(&status);
3674643ce7deSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3675643ce7deSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3676643ce7deSJohn Baldwin }
3677643ce7deSJohn Baldwin 
3678403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3679e012fe34SJohn Baldwin static void *
3680e0a40f30SJohn Baldwin continue_thread(void *arg __unused)
3681e012fe34SJohn Baldwin {
3682e012fe34SJohn Baldwin 	breakpoint();
3683e012fe34SJohn Baldwin 	return (NULL);
3684e012fe34SJohn Baldwin }
3685e012fe34SJohn Baldwin 
3686e012fe34SJohn Baldwin static __dead2 void
3687e012fe34SJohn Baldwin continue_thread_main(void)
3688e012fe34SJohn Baldwin {
3689e012fe34SJohn Baldwin 	pthread_t threads[2];
3690e012fe34SJohn Baldwin 
3691e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
3692e012fe34SJohn Baldwin 	    NULL) == 0);
3693e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
3694e012fe34SJohn Baldwin 	    NULL) == 0);
3695e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_join(threads[0], NULL) == 0);
3696e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_join(threads[1], NULL) == 0);
3697e012fe34SJohn Baldwin 	exit(1);
3698e012fe34SJohn Baldwin }
3699e012fe34SJohn Baldwin 
3700e012fe34SJohn Baldwin /*
3701e012fe34SJohn Baldwin  * Ensure that PT_CONTINUE clears the status of the thread that
3702e012fe34SJohn Baldwin  * triggered the stop even if a different thread's LWP was passed to
3703e012fe34SJohn Baldwin  * PT_CONTINUE.
3704e012fe34SJohn Baldwin  */
3705e012fe34SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
3706e012fe34SJohn Baldwin ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
3707e012fe34SJohn Baldwin {
3708e012fe34SJohn Baldwin 	struct ptrace_lwpinfo pl;
3709e012fe34SJohn Baldwin 	pid_t fpid, wpid;
3710e012fe34SJohn Baldwin 	lwpid_t lwps[2];
3711e012fe34SJohn Baldwin 	bool hit_break[2];
3712403e331dSJohn Baldwin 	struct reg reg;
3713e012fe34SJohn Baldwin 	int i, j, status;
3714e012fe34SJohn Baldwin 
3715e012fe34SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3716e012fe34SJohn Baldwin 	if (fpid == 0) {
3717e012fe34SJohn Baldwin 		trace_me();
3718e012fe34SJohn Baldwin 		continue_thread_main();
3719e012fe34SJohn Baldwin 	}
3720e012fe34SJohn Baldwin 
3721e012fe34SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3722e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3723e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3724e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3725e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3726e012fe34SJohn Baldwin 
3727e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3728e012fe34SJohn Baldwin 	    sizeof(pl)) != -1);
3729e012fe34SJohn Baldwin 
3730e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
3731e012fe34SJohn Baldwin 
3732e012fe34SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
3733e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3734e012fe34SJohn Baldwin 
3735e012fe34SJohn Baldwin 	/* One of the new threads should report it's birth. */
3736e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3737e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3738e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3739e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3740e012fe34SJohn Baldwin 
3741e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3742e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
3743e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3744e012fe34SJohn Baldwin 	lwps[0] = pl.pl_lwpid;
3745e012fe34SJohn Baldwin 
3746e012fe34SJohn Baldwin 	/*
3747e012fe34SJohn Baldwin 	 * Suspend this thread to ensure both threads are alive before
3748e012fe34SJohn Baldwin 	 * hitting the breakpoint.
3749e012fe34SJohn Baldwin 	 */
3750e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
3751e012fe34SJohn Baldwin 
3752e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3753e012fe34SJohn Baldwin 
3754e012fe34SJohn Baldwin 	/* Second thread should report it's birth. */
3755e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3756e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3757e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3758e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3759e012fe34SJohn Baldwin 
3760e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3761e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
3762e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3763e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
3764e012fe34SJohn Baldwin 	lwps[1] = pl.pl_lwpid;
3765e012fe34SJohn Baldwin 
3766e012fe34SJohn Baldwin 	/* Resume both threads waiting for breakpoint events. */
3767e012fe34SJohn Baldwin 	hit_break[0] = hit_break[1] = false;
3768e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
3769e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3770e012fe34SJohn Baldwin 
3771e012fe34SJohn Baldwin 	/* One thread should report a breakpoint. */
3772e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3773e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3774e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3775e012fe34SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3776e012fe34SJohn Baldwin 
3777e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3778e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3779e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
3780e012fe34SJohn Baldwin 	    pl.pl_siginfo.si_code == TRAP_BRKPT);
3781e012fe34SJohn Baldwin 	if (pl.pl_lwpid == lwps[0])
3782e012fe34SJohn Baldwin 		i = 0;
3783e012fe34SJohn Baldwin 	else
3784e012fe34SJohn Baldwin 		i = 1;
3785e012fe34SJohn Baldwin 	hit_break[i] = true;
3786403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3787403e331dSJohn Baldwin 	SKIP_BREAK(&reg);
3788403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3789e012fe34SJohn Baldwin 
3790e012fe34SJohn Baldwin 	/*
3791e012fe34SJohn Baldwin 	 * Resume both threads but pass the other thread's LWPID to
3792e012fe34SJohn Baldwin 	 * PT_CONTINUE.
3793e012fe34SJohn Baldwin 	 */
3794e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0) == 0);
3795e012fe34SJohn Baldwin 
3796e012fe34SJohn Baldwin 	/*
3797e012fe34SJohn Baldwin 	 * Will now get two thread exit events and one more breakpoint
3798e012fe34SJohn Baldwin 	 * event.
3799e012fe34SJohn Baldwin 	 */
3800e012fe34SJohn Baldwin 	for (j = 0; j < 3; j++) {
3801e012fe34SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
3802e012fe34SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
3803e012fe34SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
3804e012fe34SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3805e012fe34SJohn Baldwin 
3806e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3807e012fe34SJohn Baldwin 		    sizeof(pl)) != -1);
3808e012fe34SJohn Baldwin 
3809e012fe34SJohn Baldwin 		if (pl.pl_lwpid == lwps[0])
3810e012fe34SJohn Baldwin 			i = 0;
3811e012fe34SJohn Baldwin 		else
3812e012fe34SJohn Baldwin 			i = 1;
3813e012fe34SJohn Baldwin 
3814e012fe34SJohn Baldwin 		ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
3815e012fe34SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_EXITED) {
3816e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(hit_break[i],
3817e012fe34SJohn Baldwin 			    "exited thread did not report breakpoint");
3818e012fe34SJohn Baldwin 			lwps[i] = 0;
3819e012fe34SJohn Baldwin 		} else {
3820e012fe34SJohn Baldwin 			ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
3821e012fe34SJohn Baldwin 			ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
3822e012fe34SJohn Baldwin 			    pl.pl_siginfo.si_code == TRAP_BRKPT);
3823e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(!hit_break[i],
3824e012fe34SJohn Baldwin 			    "double breakpoint event");
3825e012fe34SJohn Baldwin 			hit_break[i] = true;
3826403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
3827403e331dSJohn Baldwin 			    0) != -1);
3828403e331dSJohn Baldwin 			SKIP_BREAK(&reg);
3829403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
3830403e331dSJohn Baldwin 			    0) != -1);
3831e012fe34SJohn Baldwin 		}
3832e012fe34SJohn Baldwin 
3833e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3834e012fe34SJohn Baldwin 	}
3835e012fe34SJohn Baldwin 
3836e012fe34SJohn Baldwin 	/* Both threads should have exited. */
3837e012fe34SJohn Baldwin 	ATF_REQUIRE(lwps[0] == 0);
3838e012fe34SJohn Baldwin 	ATF_REQUIRE(lwps[1] == 0);
3839e012fe34SJohn Baldwin 
3840e012fe34SJohn Baldwin 	/* The last event should be for the child process's exit. */
3841e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3842e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3843e012fe34SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3844e012fe34SJohn Baldwin 
3845e012fe34SJohn Baldwin 	wpid = wait(&status);
3846e012fe34SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3847e012fe34SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3848e012fe34SJohn Baldwin }
3849e012fe34SJohn Baldwin #endif
3850e012fe34SJohn Baldwin 
3851c5786670SJohn Baldwin /*
3852c5786670SJohn Baldwin  * Verify that PT_LWPINFO doesn't return stale siginfo.
3853c5786670SJohn Baldwin  */
3854c5786670SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_LWPINFO_stale_siginfo);
3855c5786670SJohn Baldwin ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo, tc)
3856c5786670SJohn Baldwin {
3857c5786670SJohn Baldwin 	struct ptrace_lwpinfo pl;
3858c5786670SJohn Baldwin 	pid_t fpid, wpid;
3859c5786670SJohn Baldwin 	int events, status;
3860c5786670SJohn Baldwin 
3861c5786670SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3862c5786670SJohn Baldwin 	if (fpid == 0) {
3863c5786670SJohn Baldwin 		trace_me();
3864c5786670SJohn Baldwin 		raise(SIGABRT);
3865c5786670SJohn Baldwin 		exit(1);
3866c5786670SJohn Baldwin 	}
3867c5786670SJohn Baldwin 
3868c5786670SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3869c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3870c5786670SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3871c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3872c5786670SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3873c5786670SJohn Baldwin 
3874c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3875c5786670SJohn Baldwin 
3876c5786670SJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
3877c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3878c5786670SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3879c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3880c5786670SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
3881c5786670SJohn Baldwin 
3882c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3883c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3884c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
3885c5786670SJohn Baldwin 
3886c5786670SJohn Baldwin 	/*
3887c5786670SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
3888c5786670SJohn Baldwin 	 * syscall traps.
3889c5786670SJohn Baldwin 	 */
3890c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
3891c5786670SJohn Baldwin 
3892c5786670SJohn Baldwin 	/*
3893c5786670SJohn Baldwin 	 * The next stop should report a system call entry from
3894c5786670SJohn Baldwin 	 * exit().  PL_FLAGS_SI should not be set.
3895c5786670SJohn Baldwin 	 */
3896c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3897c5786670SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3898c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3899c5786670SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3900c5786670SJohn Baldwin 
3901c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3902c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
3903c5786670SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) == 0);
3904c5786670SJohn Baldwin 
3905c5786670SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
3906c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
3907c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3908c5786670SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
3909c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
3910c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3911c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3912c5786670SJohn Baldwin 
3913c5786670SJohn Baldwin 	/* The last event should be for the child process's exit. */
3914c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3915c5786670SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
3916c5786670SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
3917c5786670SJohn Baldwin 
3918c5786670SJohn Baldwin 	wpid = wait(&status);
3919c5786670SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
3920c5786670SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
3921c5786670SJohn Baldwin }
3922c5786670SJohn Baldwin 
3923c8ea8731SJohn Baldwin /*
392432451fb9SJohn Baldwin  * A simple test of PT_GET_SC_ARGS and PT_GET_SC_RET.
3925c8ea8731SJohn Baldwin  */
3926c8ea8731SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__syscall_args);
3927c8ea8731SJohn Baldwin ATF_TC_BODY(ptrace__syscall_args, tc)
3928c8ea8731SJohn Baldwin {
3929c8ea8731SJohn Baldwin 	struct ptrace_lwpinfo pl;
393032451fb9SJohn Baldwin 	struct ptrace_sc_ret psr;
3931c8ea8731SJohn Baldwin 	pid_t fpid, wpid;
3932c8ea8731SJohn Baldwin 	register_t args[2];
3933c8ea8731SJohn Baldwin 	int events, status;
3934c8ea8731SJohn Baldwin 
3935c8ea8731SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3936c8ea8731SJohn Baldwin 	if (fpid == 0) {
3937c8ea8731SJohn Baldwin 		trace_me();
3938c8ea8731SJohn Baldwin 		kill(getpid(), 0);
393932451fb9SJohn Baldwin 		close(3);
3940c8ea8731SJohn Baldwin 		exit(1);
3941c8ea8731SJohn Baldwin 	}
3942c8ea8731SJohn Baldwin 
3943c8ea8731SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3944c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3945c8ea8731SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3946c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3947c8ea8731SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3948c8ea8731SJohn Baldwin 
3949c8ea8731SJohn Baldwin 	/*
3950c8ea8731SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
395132451fb9SJohn Baldwin 	 * syscall traps.
3952c8ea8731SJohn Baldwin 	 */
395332451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
3954c8ea8731SJohn Baldwin 
3955c8ea8731SJohn Baldwin 	/*
3956c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from getpid().
3957c8ea8731SJohn Baldwin 	 */
3958c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3959c8ea8731SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3960c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3961c8ea8731SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3962c8ea8731SJohn Baldwin 
3963c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3964c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
3965c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_syscall_code == SYS_getpid);
3966c8ea8731SJohn Baldwin 
3967c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3968c8ea8731SJohn Baldwin 
3969c8ea8731SJohn Baldwin 	/*
397032451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from getpid().
397132451fb9SJohn Baldwin 	 */
397232451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
397332451fb9SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
397432451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
397532451fb9SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
397632451fb9SJohn Baldwin 
397732451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
397832451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
397932451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_syscall_code == SYS_getpid);
398032451fb9SJohn Baldwin 
398132451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
398232451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
398332451fb9SJohn Baldwin 	ATF_REQUIRE(psr.sr_error == 0);
398432451fb9SJohn Baldwin 	ATF_REQUIRE(psr.sr_retval[0] == wpid);
398532451fb9SJohn Baldwin 
398632451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
398732451fb9SJohn Baldwin 
398832451fb9SJohn Baldwin 	/*
3989c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from kill().
3990c8ea8731SJohn Baldwin 	 */
3991c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3992c8ea8731SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
3993c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
3994c8ea8731SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
3995c8ea8731SJohn Baldwin 
3996c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3997c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
3998c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_syscall_code == SYS_kill);
3999c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_syscall_narg == 2);
4000c8ea8731SJohn Baldwin 
4001c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
4002c8ea8731SJohn Baldwin 	    sizeof(args)) != -1);
4003c8ea8731SJohn Baldwin 	ATF_REQUIRE(args[0] == wpid);
4004c8ea8731SJohn Baldwin 	ATF_REQUIRE(args[1] == 0);
4005c8ea8731SJohn Baldwin 
400632451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
400732451fb9SJohn Baldwin 
400832451fb9SJohn Baldwin 	/*
400932451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from kill().
401032451fb9SJohn Baldwin 	 */
401132451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
401232451fb9SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
401332451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
401432451fb9SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
401532451fb9SJohn Baldwin 
401632451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
401732451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
401832451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_syscall_code == SYS_kill);
401932451fb9SJohn Baldwin 
402032451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
402132451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
402232451fb9SJohn Baldwin 	ATF_REQUIRE(psr.sr_error == 0);
402332451fb9SJohn Baldwin 
402432451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
402532451fb9SJohn Baldwin 
402632451fb9SJohn Baldwin 	/*
402732451fb9SJohn Baldwin 	 * The next stop should be the syscall entry from close().
402832451fb9SJohn Baldwin 	 */
402932451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
403032451fb9SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
403132451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
403232451fb9SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
403332451fb9SJohn Baldwin 
403432451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
403532451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
403632451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_syscall_code == SYS_close);
403732451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_syscall_narg == 1);
403832451fb9SJohn Baldwin 
403932451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
404032451fb9SJohn Baldwin 	    sizeof(args)) != -1);
404132451fb9SJohn Baldwin 	ATF_REQUIRE(args[0] == 3);
404232451fb9SJohn Baldwin 
404332451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
404432451fb9SJohn Baldwin 
404532451fb9SJohn Baldwin 	/*
404632451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from close().
404732451fb9SJohn Baldwin 	 */
404832451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
404932451fb9SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
405032451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
405132451fb9SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
405232451fb9SJohn Baldwin 
405332451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
405432451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
405532451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_syscall_code == SYS_close);
405632451fb9SJohn Baldwin 
405732451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
405832451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
405932451fb9SJohn Baldwin 	ATF_REQUIRE(psr.sr_error == EBADF);
406032451fb9SJohn Baldwin 
4061c8ea8731SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
4062c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
4063c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
4064c8ea8731SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
4065c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
4066c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
4067c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
4068c8ea8731SJohn Baldwin 
4069c8ea8731SJohn Baldwin 	/* The last event should be for the child process's exit. */
4070c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4071c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
4072c8ea8731SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
4073c8ea8731SJohn Baldwin 
4074c8ea8731SJohn Baldwin 	wpid = wait(&status);
4075c8ea8731SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
4076c8ea8731SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
4077c8ea8731SJohn Baldwin }
4078c8ea8731SJohn Baldwin 
4079*fd631bcdSMariusz Zaborski /*
4080*fd631bcdSMariusz Zaborski  * Verify that when the process is traced that it isn't reparent
4081*fd631bcdSMariusz Zaborski  * to the init process when we close all process descriptors.
4082*fd631bcdSMariusz Zaborski  */
4083*fd631bcdSMariusz Zaborski ATF_TC(ptrace__proc_reparent);
4084*fd631bcdSMariusz Zaborski ATF_TC_HEAD(ptrace__proc_reparent, tc)
4085*fd631bcdSMariusz Zaborski {
4086*fd631bcdSMariusz Zaborski 
4087*fd631bcdSMariusz Zaborski 	atf_tc_set_md_var(tc, "timeout", "2");
4088*fd631bcdSMariusz Zaborski }
4089*fd631bcdSMariusz Zaborski ATF_TC_BODY(ptrace__proc_reparent, tc)
4090*fd631bcdSMariusz Zaborski {
4091*fd631bcdSMariusz Zaborski 	pid_t traced, debuger, wpid;
4092*fd631bcdSMariusz Zaborski 	int pd, status;
4093*fd631bcdSMariusz Zaborski 
4094*fd631bcdSMariusz Zaborski 	traced = pdfork(&pd, 0);
4095*fd631bcdSMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
4096*fd631bcdSMariusz Zaborski 	if (traced == 0) {
4097*fd631bcdSMariusz Zaborski 		raise(SIGSTOP);
4098*fd631bcdSMariusz Zaborski 		exit(0);
4099*fd631bcdSMariusz Zaborski 	}
4100*fd631bcdSMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
4101*fd631bcdSMariusz Zaborski 
4102*fd631bcdSMariusz Zaborski 	debuger = fork();
4103*fd631bcdSMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
4104*fd631bcdSMariusz Zaborski 	if (debuger == 0) {
4105*fd631bcdSMariusz Zaborski 		/* The traced process is reparented to debuger. */
4106*fd631bcdSMariusz Zaborski 		ATF_REQUIRE(ptrace(PT_ATTACH, traced, 0, 0) == 0);
4107*fd631bcdSMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
4108*fd631bcdSMariusz Zaborski 		ATF_REQUIRE(wpid == traced);
4109*fd631bcdSMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
4110*fd631bcdSMariusz Zaborski 		ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
4111*fd631bcdSMariusz Zaborski 		ATF_REQUIRE(close(pd) == 0);
4112*fd631bcdSMariusz Zaborski 		ATF_REQUIRE(ptrace(PT_DETACH, traced, (caddr_t)1, 0) == 0);
4113*fd631bcdSMariusz Zaborski 
4114*fd631bcdSMariusz Zaborski 		/* We closed pd so we should not have any child. */
4115*fd631bcdSMariusz Zaborski 		wpid = wait(&status);
4116*fd631bcdSMariusz Zaborski 		ATF_REQUIRE(wpid == -1);
4117*fd631bcdSMariusz Zaborski 		ATF_REQUIRE(errno == ECHILD);
4118*fd631bcdSMariusz Zaborski 
4119*fd631bcdSMariusz Zaborski 		exit(0);
4120*fd631bcdSMariusz Zaborski 	}
4121*fd631bcdSMariusz Zaborski 
4122*fd631bcdSMariusz Zaborski 	ATF_REQUIRE(close(pd) == 0);
4123*fd631bcdSMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
4124*fd631bcdSMariusz Zaborski 	ATF_REQUIRE(wpid == debuger);
4125*fd631bcdSMariusz Zaborski 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
4126*fd631bcdSMariusz Zaborski 
4127*fd631bcdSMariusz Zaborski 	/* Check if we still have any child. */
4128*fd631bcdSMariusz Zaborski 	wpid = wait(&status);
4129*fd631bcdSMariusz Zaborski 	ATF_REQUIRE(wpid == -1);
4130*fd631bcdSMariusz Zaborski 	ATF_REQUIRE(errno == ECHILD);
4131*fd631bcdSMariusz Zaborski }
4132*fd631bcdSMariusz Zaborski 
4133c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
4134c209e3e2SJohn Baldwin {
4135c209e3e2SJohn Baldwin 
4136c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
4137c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
413857c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
413957c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
4140128c9bc0SMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
414198685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
414298685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
414398685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
414498685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
414598685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
414698685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
414798685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
414898685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
4149368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
4150189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
4151189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
4152189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
41535fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
41545fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
41553340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
41568d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
41578d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
41588d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
4159fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
4160fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
4161403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
416282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
4163e2ebfbbfSEric Badger #endif
416482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
416582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
416682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
416782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
416882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
416982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
417082a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
417182a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
417282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
4173753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
417482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
417582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
417682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
417782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
4178753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
4179753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
418082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
4181b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
4182b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
4183b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
4184d74da94cSMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
418554cfb29eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
4186643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
4187643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo);
4188643ce7deSJohn Baldwin #endif
4189643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__step_siginfo);
4190403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
4191e012fe34SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
4192e012fe34SJohn Baldwin #endif
4193c5786670SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
4194c8ea8731SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__syscall_args);
4195*fd631bcdSMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__proc_reparent);
4196c209e3e2SJohn Baldwin 
4197c209e3e2SJohn Baldwin 	return (atf_no_error());
4198c209e3e2SJohn Baldwin }
4199