xref: /freebsd/tests/sys/kern/ptrace_test.c (revision 526becbf6e42331e3680d55fe1e9a82e1b56a735)
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/types.h>
2782a4538fSEric Badger #include <sys/cpuset.h>
28548a2ec4SAndrew Turner #include <sys/elf.h>
2982a4538fSEric Badger #include <sys/event.h>
30d74da94cSMark Johnston #include <sys/file.h>
3182a4538fSEric Badger #include <sys/time.h>
32b38bd91fSEric Badger #include <sys/procctl.h>
33fd631bcdSMariusz Zaborski #include <sys/procdesc.h>
34c209e3e2SJohn Baldwin #include <sys/ptrace.h>
35548a2ec4SAndrew Turner #include <sys/procfs.h>
36bc2be1d3SEric Badger #include <sys/queue.h>
37bc2be1d3SEric Badger #include <sys/runq.h>
38189ac973SJohn Baldwin #include <sys/syscall.h>
3957c74f5bSJohn Baldwin #include <sys/sysctl.h>
4057c74f5bSJohn Baldwin #include <sys/user.h>
41c209e3e2SJohn Baldwin #include <sys/wait.h>
42c209e3e2SJohn Baldwin #include <errno.h>
439e0d1159SEric Badger #include <machine/cpufunc.h>
44189ac973SJohn Baldwin #include <pthread.h>
45bc2be1d3SEric Badger #include <sched.h>
4682a4538fSEric Badger #include <semaphore.h>
47c209e3e2SJohn Baldwin #include <signal.h>
4896a9e50eSAlex Richardson #include <stdarg.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__) ||	\
58185efcc3SEd Maste     defined(__i386__) || defined(__riscv)
59403e331dSJohn Baldwin #define	HAVE_BREAKPOINT
60403e331dSJohn Baldwin #endif
61403e331dSJohn Baldwin 
62403e331dSJohn Baldwin /*
63403e331dSJohn Baldwin  * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap.
64403e331dSJohn Baldwin  */
65403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
66a9c91abdSJohn Baldwin #if defined(__aarch64__)
67a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->elr += 4)
68a9c91abdSJohn Baldwin #elif defined(__amd64__) || defined(__i386__)
69403e331dSJohn Baldwin #define	SKIP_BREAK(reg)
70a9c91abdSJohn Baldwin #elif defined(__arm__)
71a9c91abdSJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->r_pc += 4)
72ca75fa17SJohn Baldwin #elif defined(__riscv)
73ca75fa17SJohn Baldwin #define	SKIP_BREAK(reg)	((reg)->sepc += 4)
74403e331dSJohn Baldwin #endif
75403e331dSJohn Baldwin #endif
76403e331dSJohn Baldwin 
77403e331dSJohn Baldwin /*
78dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
79dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
80dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
81dfa8ba12SJohn Baldwin  */
82dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {				\
83dfa8ba12SJohn Baldwin 	if (!(exp))					\
84dfa8ba12SJohn Baldwin 		child_fail_require(__FILE__, __LINE__,	\
8596a9e50eSAlex Richardson 		    #exp " not met\n");			\
8696a9e50eSAlex Richardson } while (0)
8796a9e50eSAlex Richardson 
8896a9e50eSAlex Richardson #define	CHILD_REQUIRE_EQ(actual, expected) do {			\
8996a9e50eSAlex Richardson 	__typeof__(expected) _e = expected;			\
9096a9e50eSAlex Richardson 	__typeof__(actual) _a = actual;				\
9196a9e50eSAlex Richardson 	if (_e != _a)						\
9296a9e50eSAlex Richardson 		child_fail_require(__FILE__, __LINE__, #actual	\
9396a9e50eSAlex Richardson 		    " (%jd) == " #expected " (%jd) not met\n",	\
9496a9e50eSAlex Richardson 		    (intmax_t)_a, (intmax_t)_e);		\
95dfa8ba12SJohn Baldwin } while (0)
96dfa8ba12SJohn Baldwin 
9798685dc8SJohn Baldwin static __dead2 void
child_fail_require(const char * file,int line,const char * fmt,...)9896a9e50eSAlex Richardson child_fail_require(const char *file, int line, const char *fmt, ...)
99dfa8ba12SJohn Baldwin {
10096a9e50eSAlex Richardson 	va_list ap;
10196a9e50eSAlex Richardson 	char buf[1024];
102dfa8ba12SJohn Baldwin 
10396a9e50eSAlex Richardson 	/* Use write() not fprintf() to avoid possible duplicate output. */
10496a9e50eSAlex Richardson 	snprintf(buf, sizeof(buf), "%s:%d: ", file, line);
10596a9e50eSAlex Richardson 	write(STDERR_FILENO, buf, strlen(buf));
10696a9e50eSAlex Richardson 	va_start(ap, fmt);
10796a9e50eSAlex Richardson 	vsnprintf(buf, sizeof(buf), fmt, ap);
10896a9e50eSAlex Richardson 	write(STDERR_FILENO, buf, strlen(buf));
10996a9e50eSAlex Richardson 	va_end(ap);
11096a9e50eSAlex Richardson 
111dfa8ba12SJohn Baldwin 	_exit(32);
112dfa8ba12SJohn Baldwin }
113dfa8ba12SJohn Baldwin 
11496a9e50eSAlex Richardson #define	REQUIRE_EQ(actual, expected) do {				\
11596a9e50eSAlex Richardson 	__typeof__(expected) _e = expected;				\
11696a9e50eSAlex Richardson 	__typeof__(actual) _a = actual;					\
11796a9e50eSAlex Richardson 	ATF_REQUIRE_MSG(_e == _a, #actual " (%jd) == "			\
11896a9e50eSAlex Richardson 	    #expected " (%jd) not met", (intmax_t)_a, (intmax_t)_e);	\
11996a9e50eSAlex Richardson } while (0)
12096a9e50eSAlex Richardson 
12198685dc8SJohn Baldwin static void
trace_me(void)12298685dc8SJohn Baldwin trace_me(void)
12398685dc8SJohn Baldwin {
12498685dc8SJohn Baldwin 
12598685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
12698685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12798685dc8SJohn Baldwin 
12898685dc8SJohn Baldwin 	/* Trigger a stop. */
12998685dc8SJohn Baldwin 	raise(SIGSTOP);
13098685dc8SJohn Baldwin }
13198685dc8SJohn Baldwin 
13298685dc8SJohn Baldwin static void
attach_child(pid_t pid)13398685dc8SJohn Baldwin attach_child(pid_t pid)
13498685dc8SJohn Baldwin {
13598685dc8SJohn Baldwin 	pid_t wpid;
13698685dc8SJohn Baldwin 	int status;
13798685dc8SJohn Baldwin 
13896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, pid, NULL, 0), 0);
13998685dc8SJohn Baldwin 
14098685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
14196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, pid);
14298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
14498685dc8SJohn Baldwin }
14598685dc8SJohn Baldwin 
14698685dc8SJohn Baldwin static void
wait_for_zombie(pid_t pid)14798685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
14898685dc8SJohn Baldwin {
14998685dc8SJohn Baldwin 
15098685dc8SJohn Baldwin 	/*
15198685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
15298685dc8SJohn Baldwin 	 * there is not a better way.
1533a014c56SJohn Baldwin 	 *
1543a014c56SJohn Baldwin 	 * Prior to r325719, the kern.proc.pid.<pid> sysctl failed
1553a014c56SJohn Baldwin 	 * with ESRCH.  After that change, a valid struct kinfo_proc
1563a014c56SJohn Baldwin 	 * is returned for zombies with ki_stat set to SZOMB.
15798685dc8SJohn Baldwin 	 */
15898685dc8SJohn Baldwin 	for (;;) {
15998685dc8SJohn Baldwin 		struct kinfo_proc kp;
16098685dc8SJohn Baldwin 		size_t len;
16198685dc8SJohn Baldwin 		int mib[4];
16298685dc8SJohn Baldwin 
16398685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
16498685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
16598685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
16698685dc8SJohn Baldwin 		mib[3] = pid;
16798685dc8SJohn Baldwin 		len = sizeof(kp);
16898685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
16996a9e50eSAlex Richardson 			REQUIRE_EQ(errno, ESRCH);
17098685dc8SJohn Baldwin 			break;
17198685dc8SJohn Baldwin 		}
1723a014c56SJohn Baldwin 		if (kp.ki_stat == SZOMB)
1733a014c56SJohn Baldwin 			break;
17498685dc8SJohn Baldwin 		usleep(5000);
17598685dc8SJohn Baldwin 	}
17698685dc8SJohn Baldwin }
17798685dc8SJohn Baldwin 
178dfa8ba12SJohn Baldwin /*
179c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
180c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
181c209e3e2SJohn Baldwin  */
182c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
ATF_TC_BODY(ptrace__parent_wait_after_trace_me,tc)183c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
184c209e3e2SJohn Baldwin {
185c209e3e2SJohn Baldwin 	pid_t child, wpid;
186c209e3e2SJohn Baldwin 	int status;
187c209e3e2SJohn Baldwin 
188c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
189c209e3e2SJohn Baldwin 	if (child == 0) {
190c209e3e2SJohn Baldwin 		/* Child process. */
19198685dc8SJohn Baldwin 		trace_me();
192c209e3e2SJohn Baldwin 
193b98cb919SJohn Baldwin 		_exit(1);
194c209e3e2SJohn Baldwin 	}
195c209e3e2SJohn Baldwin 
196c209e3e2SJohn Baldwin 	/* Parent process. */
197c209e3e2SJohn Baldwin 
198c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
199c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
20096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
201c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
20296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
203c209e3e2SJohn Baldwin 
204c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
205c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
206c209e3e2SJohn Baldwin 
207c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
208c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
20996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
210c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
21196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
212c209e3e2SJohn Baldwin 
213c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
214c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
21596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
21696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
217c209e3e2SJohn Baldwin }
218c209e3e2SJohn Baldwin 
219c209e3e2SJohn Baldwin /*
220c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
221c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
222c209e3e2SJohn Baldwin  */
223c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
ATF_TC_BODY(ptrace__parent_wait_after_attach,tc)224c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
225c209e3e2SJohn Baldwin {
226c209e3e2SJohn Baldwin 	pid_t child, wpid;
227c209e3e2SJohn Baldwin 	int cpipe[2], status;
228c209e3e2SJohn Baldwin 	char c;
229c209e3e2SJohn Baldwin 
23096a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
231c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
232c209e3e2SJohn Baldwin 	if (child == 0) {
233c209e3e2SJohn Baldwin 		/* Child process. */
234c209e3e2SJohn Baldwin 		close(cpipe[0]);
235c209e3e2SJohn Baldwin 
236c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
23796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(0, read(cpipe[1], &c, sizeof(c)));
238c209e3e2SJohn Baldwin 
239b98cb919SJohn Baldwin 		_exit(1);
240c209e3e2SJohn Baldwin 	}
241c209e3e2SJohn Baldwin 	close(cpipe[1]);
242c209e3e2SJohn Baldwin 
243c209e3e2SJohn Baldwin 	/* Parent process. */
244c209e3e2SJohn Baldwin 
245c209e3e2SJohn Baldwin 	/* Attach to the child process. */
24698685dc8SJohn Baldwin 	attach_child(child);
247c209e3e2SJohn Baldwin 
248c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
249c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
250c209e3e2SJohn Baldwin 
251c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
252c209e3e2SJohn Baldwin 	close(cpipe[0]);
253c209e3e2SJohn Baldwin 
254c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
255c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
25696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
257c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
25896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
259c209e3e2SJohn Baldwin 
260c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
261c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
26296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
26396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
264c209e3e2SJohn Baldwin }
265c209e3e2SJohn Baldwin 
26657c74f5bSJohn Baldwin /*
26757c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
26857c74f5bSJohn Baldwin  * after the debugger has seen it.
26957c74f5bSJohn Baldwin  */
27057c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger,tc)27157c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
27257c74f5bSJohn Baldwin {
27357c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
27457c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
27557c74f5bSJohn Baldwin 	char c;
27657c74f5bSJohn Baldwin 
27796a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
27857c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
27957c74f5bSJohn Baldwin 
28057c74f5bSJohn Baldwin 	if (child == 0) {
28157c74f5bSJohn Baldwin 		/* Child process. */
28257c74f5bSJohn Baldwin 		close(cpipe[0]);
28357c74f5bSJohn Baldwin 
28457c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
2851fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
2861fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
28757c74f5bSJohn Baldwin 
288b98cb919SJohn Baldwin 		_exit(1);
28957c74f5bSJohn Baldwin 	}
29057c74f5bSJohn Baldwin 	close(cpipe[1]);
29157c74f5bSJohn Baldwin 
29296a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
29357c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
29457c74f5bSJohn Baldwin 
29557c74f5bSJohn Baldwin 	if (debugger == 0) {
29657c74f5bSJohn Baldwin 		/* Debugger process. */
29757c74f5bSJohn Baldwin 		close(dpipe[0]);
29857c74f5bSJohn Baldwin 
299dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
30057c74f5bSJohn Baldwin 
30157c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
30296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
303dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
30496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
30557c74f5bSJohn Baldwin 
306dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
30757c74f5bSJohn Baldwin 
30857c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
3091fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
3101fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
31157c74f5bSJohn Baldwin 
31257c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
31396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(read(dpipe[1], &c, sizeof(c)), 0);
31457c74f5bSJohn Baldwin 
31557c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
31696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
317dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
31896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
31957c74f5bSJohn Baldwin 
320b98cb919SJohn Baldwin 		_exit(0);
32157c74f5bSJohn Baldwin 	}
32257c74f5bSJohn Baldwin 	close(dpipe[1]);
32357c74f5bSJohn Baldwin 
32457c74f5bSJohn Baldwin 	/* Parent process. */
32557c74f5bSJohn Baldwin 
32657c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
3271fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
32857c74f5bSJohn Baldwin 
32957c74f5bSJohn Baldwin 	/* Release the child. */
3301fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
33196a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &c, sizeof(c)), 0);
33257c74f5bSJohn Baldwin 	close(cpipe[0]);
33357c74f5bSJohn Baldwin 
33498685dc8SJohn Baldwin 	wait_for_zombie(child);
33557c74f5bSJohn Baldwin 
33657c74f5bSJohn Baldwin 	/*
3372f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3382f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3392f021998SJohn Baldwin 	 * until the debugger sees the exit.
34057c74f5bSJohn Baldwin 	 */
34157c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
34296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
34357c74f5bSJohn Baldwin 
34457c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
34557c74f5bSJohn Baldwin 	close(dpipe[0]);
34657c74f5bSJohn Baldwin 
34757c74f5bSJohn Baldwin 	/* Wait for the debugger. */
34857c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
34996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
35057c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
35196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
35257c74f5bSJohn Baldwin 
35357c74f5bSJohn Baldwin 	/* The child process should now be ready. */
35457c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
35596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
35657c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
35796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
35857c74f5bSJohn Baldwin }
35957c74f5bSJohn Baldwin 
36057c74f5bSJohn Baldwin /*
36157c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
36257c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
36357c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
36457c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
36557c74f5bSJohn Baldwin  */
36657c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger,tc)36757c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
36857c74f5bSJohn Baldwin {
36957c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
37057c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
37157c74f5bSJohn Baldwin 	char c;
37257c74f5bSJohn Baldwin 
37396a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
37457c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
37557c74f5bSJohn Baldwin 
37657c74f5bSJohn Baldwin 	if (child == 0) {
37757c74f5bSJohn Baldwin 		/* Child process. */
37857c74f5bSJohn Baldwin 		close(cpipe[0]);
37957c74f5bSJohn Baldwin 
38057c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
3811fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
3821fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
38357c74f5bSJohn Baldwin 
384b98cb919SJohn Baldwin 		_exit(1);
38557c74f5bSJohn Baldwin 	}
38657c74f5bSJohn Baldwin 	close(cpipe[1]);
38757c74f5bSJohn Baldwin 
38896a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
38957c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
39057c74f5bSJohn Baldwin 
39157c74f5bSJohn Baldwin 	if (debugger == 0) {
39257c74f5bSJohn Baldwin 		/* Debugger parent. */
39357c74f5bSJohn Baldwin 
39457c74f5bSJohn Baldwin 		/*
39557c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
39657c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
39757c74f5bSJohn Baldwin 		 */
398dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
39957c74f5bSJohn Baldwin 		if (fpid != 0)
400b98cb919SJohn Baldwin 			_exit(2);
40157c74f5bSJohn Baldwin 
40257c74f5bSJohn Baldwin 		/* Debugger process. */
40357c74f5bSJohn Baldwin 		close(dpipe[0]);
40457c74f5bSJohn Baldwin 
405dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
40657c74f5bSJohn Baldwin 
40757c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
40896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
409dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
41096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
41157c74f5bSJohn Baldwin 
412dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
41357c74f5bSJohn Baldwin 
41457c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
4151fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
4161fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
41757c74f5bSJohn Baldwin 
41857c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
4191fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(dpipe[1], &c, sizeof(c)),
4201fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
42157c74f5bSJohn Baldwin 
42257c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
42396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
424dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
42596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
42657c74f5bSJohn Baldwin 
427b98cb919SJohn Baldwin 		_exit(0);
42857c74f5bSJohn Baldwin 	}
429eddb85c6SJohn Baldwin 	close(dpipe[1]);
43057c74f5bSJohn Baldwin 
43157c74f5bSJohn Baldwin 	/* Parent process. */
43257c74f5bSJohn Baldwin 
43357c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
43457c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
43596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
43657c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
43796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
43857c74f5bSJohn Baldwin 
43957c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
44057c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
44196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
44257c74f5bSJohn Baldwin 
44357c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
4441fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
44557c74f5bSJohn Baldwin 
44657c74f5bSJohn Baldwin 	/* Release the child. */
4471fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
44896a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &c, sizeof(c)), 0);
44957c74f5bSJohn Baldwin 	close(cpipe[0]);
45057c74f5bSJohn Baldwin 
45198685dc8SJohn Baldwin 	wait_for_zombie(child);
45257c74f5bSJohn Baldwin 
45357c74f5bSJohn Baldwin 	/*
4542f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
4552f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
4562f021998SJohn Baldwin 	 * until the debugger sees the exit.
45757c74f5bSJohn Baldwin 	 */
45857c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
45996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, 0);
46057c74f5bSJohn Baldwin 
46157c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
4621fcbddecSAlex Richardson 	REQUIRE_EQ(write(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
46357c74f5bSJohn Baldwin 
46457c74f5bSJohn Baldwin 	/* Wait for the debugger. */
46596a9e50eSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), 0);
466eddb85c6SJohn Baldwin 	close(dpipe[0]);
46757c74f5bSJohn Baldwin 
46857c74f5bSJohn Baldwin 	/* The child process should now be ready. */
46957c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
47096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
47157c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
47296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
47357c74f5bSJohn Baldwin }
47457c74f5bSJohn Baldwin 
47598685dc8SJohn Baldwin /*
476128c9bc0SMark Johnston  * Make sure that we can collect the exit status of an orphaned process.
477128c9bc0SMark Johnston  */
478128c9bc0SMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
ATF_TC_BODY(ptrace__parent_exits_before_child,tc)479128c9bc0SMark Johnston ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
480128c9bc0SMark Johnston {
481128c9bc0SMark Johnston 	ssize_t n;
482128c9bc0SMark Johnston 	int cpipe1[2], cpipe2[2], gcpipe[2], status;
483128c9bc0SMark Johnston 	pid_t child, gchild;
484128c9bc0SMark Johnston 
48596a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe1), 0);
48696a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe2), 0);
48796a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(gcpipe), 0);
488128c9bc0SMark Johnston 
48996a9e50eSAlex Richardson 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
490128c9bc0SMark Johnston 
491128c9bc0SMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
492128c9bc0SMark Johnston 	if (child == 0) {
493128c9bc0SMark Johnston 		CHILD_REQUIRE((gchild = fork()) != -1);
494128c9bc0SMark Johnston 		if (gchild == 0) {
495128c9bc0SMark Johnston 			status = 1;
496128c9bc0SMark Johnston 			do {
497128c9bc0SMark Johnston 				n = read(gcpipe[0], &status, sizeof(status));
498128c9bc0SMark Johnston 			} while (n == -1 && errno == EINTR);
499128c9bc0SMark Johnston 			_exit(status);
500128c9bc0SMark Johnston 		}
501128c9bc0SMark Johnston 
5021fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(cpipe1[1], &gchild, sizeof(gchild)),
5031fcbddecSAlex Richardson 		    (ssize_t)sizeof(gchild));
5041fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe2[0], &status, sizeof(status)),
5051fcbddecSAlex Richardson 		    (ssize_t)sizeof(status));
506128c9bc0SMark Johnston 		_exit(status);
507128c9bc0SMark Johnston 	}
508128c9bc0SMark Johnston 
5091fcbddecSAlex Richardson 	REQUIRE_EQ(read(cpipe1[0], &gchild, sizeof(gchild)),
5101fcbddecSAlex Richardson 	    (ssize_t)sizeof(gchild));
511128c9bc0SMark Johnston 
51296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, gchild, NULL, 0), 0);
513128c9bc0SMark Johnston 
514128c9bc0SMark Johnston 	status = 0;
5151fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe2[1], &status, sizeof(status)),
5161fcbddecSAlex Richardson 	    (ssize_t)sizeof(status));
51796a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(child, &status, 0), child);
51896a9e50eSAlex Richardson 	ATF_REQUIRE(WIFEXITED(status));
51996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
520128c9bc0SMark Johnston 
521128c9bc0SMark Johnston 	status = 0;
5221fcbddecSAlex Richardson 	REQUIRE_EQ(write(gcpipe[1], &status, sizeof(status)),
5231fcbddecSAlex Richardson 	    (ssize_t)sizeof(status));
52496a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(gchild, &status, 0), gchild);
525128c9bc0SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
52696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_DETACH, gchild, (caddr_t)1, 0), 0);
52796a9e50eSAlex Richardson 	REQUIRE_EQ(waitpid(gchild, &status, 0), gchild);
52896a9e50eSAlex Richardson 	ATF_REQUIRE(WIFEXITED(status));
52996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
530128c9bc0SMark Johnston 
53196a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe1[0]), 0);
53296a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe1[1]), 0);
53396a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe2[0]), 0);
53496a9e50eSAlex Richardson 	REQUIRE_EQ(close(cpipe2[1]), 0);
53596a9e50eSAlex Richardson 	REQUIRE_EQ(close(gcpipe[0]), 0);
53696a9e50eSAlex Richardson 	REQUIRE_EQ(close(gcpipe[1]), 0);
537128c9bc0SMark Johnston }
538128c9bc0SMark Johnston 
539128c9bc0SMark Johnston /*
54098685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
54198685dc8SJohn Baldwin  * debugger is attached to it.
54298685dc8SJohn Baldwin  */
54398685dc8SJohn Baldwin static __dead2 void
follow_fork_parent(bool use_vfork)544189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
54598685dc8SJohn Baldwin {
54698685dc8SJohn Baldwin 	pid_t fpid, wpid;
54798685dc8SJohn Baldwin 	int status;
54898685dc8SJohn Baldwin 
549189ac973SJohn Baldwin 	if (use_vfork)
550189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
551189ac973SJohn Baldwin 	else
55298685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
55398685dc8SJohn Baldwin 
55498685dc8SJohn Baldwin 	if (fpid == 0)
55598685dc8SJohn Baldwin 		/* Child */
556b98cb919SJohn Baldwin 		_exit(2);
55798685dc8SJohn Baldwin 
55898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
55996a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(wpid, fpid);
56098685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
56196a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(WEXITSTATUS(status), 2);
56298685dc8SJohn Baldwin 
563b98cb919SJohn Baldwin 	_exit(1);
56498685dc8SJohn Baldwin }
56598685dc8SJohn Baldwin 
56698685dc8SJohn Baldwin /*
56798685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
56898685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
56998685dc8SJohn Baldwin  * child process.
57098685dc8SJohn Baldwin  */
57198685dc8SJohn Baldwin static pid_t
handle_fork_events(pid_t parent,struct ptrace_lwpinfo * ppl)572189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
57398685dc8SJohn Baldwin {
57498685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
57598685dc8SJohn Baldwin 	bool fork_reported[2];
57698685dc8SJohn Baldwin 	pid_t child, wpid;
57798685dc8SJohn Baldwin 	int i, status;
57898685dc8SJohn Baldwin 
57998685dc8SJohn Baldwin 	fork_reported[0] = false;
58098685dc8SJohn Baldwin 	fork_reported[1] = false;
58198685dc8SJohn Baldwin 	child = -1;
58298685dc8SJohn Baldwin 
58398685dc8SJohn Baldwin 	/*
58498685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
58598685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
58698685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
58798685dc8SJohn Baldwin 	 */
58898685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
58998685dc8SJohn Baldwin 		wpid = wait(&status);
59098685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
59198685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
59298685dc8SJohn Baldwin 
59398685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
59498685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
59598685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
59698685dc8SJohn Baldwin 		    0);
59798685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
59898685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
59998685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
60098685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
60196a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
60298685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
60398685dc8SJohn Baldwin 			if (child == -1)
60498685dc8SJohn Baldwin 				child = wpid;
60598685dc8SJohn Baldwin 			else
60696a9e50eSAlex Richardson 				REQUIRE_EQ(child, wpid);
607189ac973SJohn Baldwin 			if (ppl != NULL)
608189ac973SJohn Baldwin 				ppl[1] = pl;
60998685dc8SJohn Baldwin 			fork_reported[1] = true;
61098685dc8SJohn Baldwin 		} else {
61196a9e50eSAlex Richardson 			REQUIRE_EQ(wpid, parent);
61296a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
61398685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
61498685dc8SJohn Baldwin 			if (child == -1)
61598685dc8SJohn Baldwin 				child = pl.pl_child_pid;
61698685dc8SJohn Baldwin 			else
61796a9e50eSAlex Richardson 				REQUIRE_EQ(child, pl.pl_child_pid);
618189ac973SJohn Baldwin 			if (ppl != NULL)
619189ac973SJohn Baldwin 				ppl[0] = pl;
62098685dc8SJohn Baldwin 			fork_reported[0] = true;
62198685dc8SJohn Baldwin 		}
62298685dc8SJohn Baldwin 	}
62398685dc8SJohn Baldwin 
62498685dc8SJohn Baldwin 	return (child);
62598685dc8SJohn Baldwin }
62698685dc8SJohn Baldwin 
62798685dc8SJohn Baldwin /*
62898685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
62998685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
63098685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
63198685dc8SJohn Baldwin  */
63298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
ATF_TC_BODY(ptrace__follow_fork_both_attached,tc)63398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
63498685dc8SJohn Baldwin {
635479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
63698685dc8SJohn Baldwin 	int status;
63798685dc8SJohn Baldwin 
63898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
63998685dc8SJohn Baldwin 	if (fpid == 0) {
64098685dc8SJohn Baldwin 		trace_me();
641189ac973SJohn Baldwin 		follow_fork_parent(false);
64298685dc8SJohn Baldwin 	}
64398685dc8SJohn Baldwin 
64498685dc8SJohn Baldwin 	/* Parent process. */
64598685dc8SJohn Baldwin 	children[0] = fpid;
64698685dc8SJohn Baldwin 
64798685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
64898685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
64996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
65098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
65196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
65298685dc8SJohn Baldwin 
65398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
65498685dc8SJohn Baldwin 
65598685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
65698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
65798685dc8SJohn Baldwin 
658189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
65998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
66098685dc8SJohn Baldwin 
66198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
66298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
66398685dc8SJohn Baldwin 
66498685dc8SJohn Baldwin 	/*
66598685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
66698685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
66798685dc8SJohn Baldwin 	 */
66898685dc8SJohn Baldwin 	wpid = wait(&status);
66996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
67098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
67196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
67298685dc8SJohn Baldwin 
67398685dc8SJohn Baldwin 	wpid = wait(&status);
67496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
67598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
67696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
67798685dc8SJohn Baldwin 
67898685dc8SJohn Baldwin 	wpid = wait(&status);
67996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
68096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
68198685dc8SJohn Baldwin }
68298685dc8SJohn Baldwin 
68398685dc8SJohn Baldwin /*
68498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
68598685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
68698685dc8SJohn Baldwin  * child process is detached after it reports its fork.
68798685dc8SJohn Baldwin  */
68898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
ATF_TC_BODY(ptrace__follow_fork_child_detached,tc)68998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
69098685dc8SJohn Baldwin {
691479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
69298685dc8SJohn Baldwin 	int status;
69398685dc8SJohn Baldwin 
69498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
69598685dc8SJohn Baldwin 	if (fpid == 0) {
69698685dc8SJohn Baldwin 		trace_me();
697189ac973SJohn Baldwin 		follow_fork_parent(false);
69898685dc8SJohn Baldwin 	}
69998685dc8SJohn Baldwin 
70098685dc8SJohn Baldwin 	/* Parent process. */
70198685dc8SJohn Baldwin 	children[0] = fpid;
70298685dc8SJohn Baldwin 
70398685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
70498685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
70596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
70698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
70796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
70898685dc8SJohn Baldwin 
70998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
71098685dc8SJohn Baldwin 
71198685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
71298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
71398685dc8SJohn Baldwin 
714189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
71598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
71698685dc8SJohn Baldwin 
71798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
71898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
71998685dc8SJohn Baldwin 
72098685dc8SJohn Baldwin 	/*
72198685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
72298685dc8SJohn Baldwin 	 * child.
72398685dc8SJohn Baldwin 	 */
72498685dc8SJohn Baldwin 	wpid = wait(&status);
72596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
72698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
72796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
72898685dc8SJohn Baldwin 
72998685dc8SJohn Baldwin 	wpid = wait(&status);
73096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
73196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
73298685dc8SJohn Baldwin }
73398685dc8SJohn Baldwin 
73498685dc8SJohn Baldwin /*
73598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
73698685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
73798685dc8SJohn Baldwin  * traced parent is detached after the fork.
73898685dc8SJohn Baldwin  */
73998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
ATF_TC_BODY(ptrace__follow_fork_parent_detached,tc)74098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
74198685dc8SJohn Baldwin {
742479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
74398685dc8SJohn Baldwin 	int status;
74498685dc8SJohn Baldwin 
74598685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
74698685dc8SJohn Baldwin 	if (fpid == 0) {
74798685dc8SJohn Baldwin 		trace_me();
748189ac973SJohn Baldwin 		follow_fork_parent(false);
74998685dc8SJohn Baldwin 	}
75098685dc8SJohn Baldwin 
75198685dc8SJohn Baldwin 	/* Parent process. */
75298685dc8SJohn Baldwin 	children[0] = fpid;
75398685dc8SJohn Baldwin 
75498685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
75598685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
75696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
75798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
75896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
75998685dc8SJohn Baldwin 
76098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
76198685dc8SJohn Baldwin 
76298685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
76398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
76498685dc8SJohn Baldwin 
765189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
76698685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
76798685dc8SJohn Baldwin 
76898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
76998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
77098685dc8SJohn Baldwin 
77198685dc8SJohn Baldwin 	/*
77298685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
77398685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
77498685dc8SJohn Baldwin 	 *
77598685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
77698685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
77798685dc8SJohn Baldwin 	 * after the grandchild.
77898685dc8SJohn Baldwin 	 */
77998685dc8SJohn Baldwin 	wpid = wait(&status);
78096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
78198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
78296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
78398685dc8SJohn Baldwin 
78498685dc8SJohn Baldwin 	wpid = wait(&status);
78596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
78698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
78796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
78898685dc8SJohn Baldwin 
78998685dc8SJohn Baldwin 	wpid = wait(&status);
79096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
79196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
79298685dc8SJohn Baldwin }
79398685dc8SJohn Baldwin 
79498685dc8SJohn Baldwin static void
attach_fork_parent(int cpipe[2])79598685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
79698685dc8SJohn Baldwin {
79798685dc8SJohn Baldwin 	pid_t fpid;
79898685dc8SJohn Baldwin 
79998685dc8SJohn Baldwin 	close(cpipe[0]);
80098685dc8SJohn Baldwin 
80198685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
80298685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
80398685dc8SJohn Baldwin 	if (fpid != 0)
804b98cb919SJohn Baldwin 		_exit(3);
80598685dc8SJohn Baldwin 
80698685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
80798685dc8SJohn Baldwin 	fpid = getpid();
8081fcbddecSAlex Richardson 	CHILD_REQUIRE_EQ(write(cpipe[1], &fpid, sizeof(fpid)),
8091fcbddecSAlex Richardson 	    (ssize_t)sizeof(fpid));
81098685dc8SJohn Baldwin 
81198685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
81296a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(read(cpipe[1], &fpid, sizeof(fpid)), 0);
81398685dc8SJohn Baldwin }
81498685dc8SJohn Baldwin 
81598685dc8SJohn Baldwin /*
81698685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
81798685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
81898685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
81998685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
82098685dc8SJohn Baldwin  */
82198685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger,tc)82298685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
82398685dc8SJohn Baldwin {
824479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
82598685dc8SJohn Baldwin 	int cpipe[2], status;
82698685dc8SJohn Baldwin 
82796a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
82898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
82998685dc8SJohn Baldwin 	if (fpid == 0) {
83098685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
831189ac973SJohn Baldwin 		follow_fork_parent(false);
83298685dc8SJohn Baldwin 	}
83398685dc8SJohn Baldwin 
83498685dc8SJohn Baldwin 	/* Parent process. */
83598685dc8SJohn Baldwin 	close(cpipe[1]);
83698685dc8SJohn Baldwin 
83798685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
83898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
83996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
84098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
84196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
84298685dc8SJohn Baldwin 
84398685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
84496a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
8451fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
84698685dc8SJohn Baldwin 
84798685dc8SJohn Baldwin 	/* Attach to the fork parent. */
84898685dc8SJohn Baldwin 	attach_child(children[0]);
84998685dc8SJohn Baldwin 
85098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
85198685dc8SJohn Baldwin 
85298685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
85398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
85498685dc8SJohn Baldwin 
85598685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
85698685dc8SJohn Baldwin 	close(cpipe[0]);
85798685dc8SJohn Baldwin 
858189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
85998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
86098685dc8SJohn Baldwin 
86198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
86298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
86398685dc8SJohn Baldwin 
86498685dc8SJohn Baldwin 	/*
86598685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
86698685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
86798685dc8SJohn Baldwin 	 */
86898685dc8SJohn Baldwin 	wpid = wait(&status);
86996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
87098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
87196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
87298685dc8SJohn Baldwin 
87398685dc8SJohn Baldwin 	wpid = wait(&status);
87496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
87598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
87696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
87798685dc8SJohn Baldwin 
87898685dc8SJohn Baldwin 	wpid = wait(&status);
87996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
88096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
88198685dc8SJohn Baldwin }
88298685dc8SJohn Baldwin 
88398685dc8SJohn Baldwin /*
88498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
88598685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
88698685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
88798685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
88898685dc8SJohn Baldwin  */
88998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger,tc)89098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
89198685dc8SJohn Baldwin {
892479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
89398685dc8SJohn Baldwin 	int cpipe[2], status;
89498685dc8SJohn Baldwin 
89596a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
89698685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
89798685dc8SJohn Baldwin 	if (fpid == 0) {
89898685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
899189ac973SJohn Baldwin 		follow_fork_parent(false);
90098685dc8SJohn Baldwin 	}
90198685dc8SJohn Baldwin 
90298685dc8SJohn Baldwin 	/* Parent process. */
90398685dc8SJohn Baldwin 	close(cpipe[1]);
90498685dc8SJohn Baldwin 
90598685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
90698685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
90796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
90898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
90996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
91098685dc8SJohn Baldwin 
91198685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
91296a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
9131fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
91498685dc8SJohn Baldwin 
91598685dc8SJohn Baldwin 	/* Attach to the fork parent. */
91698685dc8SJohn Baldwin 	attach_child(children[0]);
91798685dc8SJohn Baldwin 
91898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
91998685dc8SJohn Baldwin 
92098685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
92198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
92298685dc8SJohn Baldwin 
92398685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
92498685dc8SJohn Baldwin 	close(cpipe[0]);
92598685dc8SJohn Baldwin 
926189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
92798685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
92898685dc8SJohn Baldwin 
92998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
93098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
93198685dc8SJohn Baldwin 
93298685dc8SJohn Baldwin 	/*
93398685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
93498685dc8SJohn Baldwin 	 * parent.
93598685dc8SJohn Baldwin 	 */
93698685dc8SJohn Baldwin 	wpid = wait(&status);
93796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
93898685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
93996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
94098685dc8SJohn Baldwin 
94198685dc8SJohn Baldwin 	wpid = wait(&status);
94296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
94396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
94498685dc8SJohn Baldwin }
94598685dc8SJohn Baldwin 
94698685dc8SJohn Baldwin /*
94798685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
94898685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
94998685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
95098685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
95198685dc8SJohn Baldwin  */
95298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger,tc)95398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
95498685dc8SJohn Baldwin {
955479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
95698685dc8SJohn Baldwin 	int cpipe[2], status;
95798685dc8SJohn Baldwin 
95896a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
95998685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
96098685dc8SJohn Baldwin 	if (fpid == 0) {
96198685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
962189ac973SJohn Baldwin 		follow_fork_parent(false);
96398685dc8SJohn Baldwin 	}
96498685dc8SJohn Baldwin 
96598685dc8SJohn Baldwin 	/* Parent process. */
96698685dc8SJohn Baldwin 	close(cpipe[1]);
96798685dc8SJohn Baldwin 
96898685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
96998685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
97096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
97198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
97296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 3);
97398685dc8SJohn Baldwin 
97498685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
97596a9e50eSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &children[0], sizeof(children[0])),
9761fcbddecSAlex Richardson 	    (ssize_t)sizeof(children[0]));
97798685dc8SJohn Baldwin 
97898685dc8SJohn Baldwin 	/* Attach to the fork parent. */
97998685dc8SJohn Baldwin 	attach_child(children[0]);
98098685dc8SJohn Baldwin 
98198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
98298685dc8SJohn Baldwin 
98398685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
98498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
98598685dc8SJohn Baldwin 
98698685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
98798685dc8SJohn Baldwin 	close(cpipe[0]);
98898685dc8SJohn Baldwin 
989189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
99098685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
99198685dc8SJohn Baldwin 
99298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
99398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
99498685dc8SJohn Baldwin 
99598685dc8SJohn Baldwin 	/*
99698685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
99798685dc8SJohn Baldwin 	 * the child.
99898685dc8SJohn Baldwin 	 */
99998685dc8SJohn Baldwin 	wpid = wait(&status);
100096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
100198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
100296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
100398685dc8SJohn Baldwin 
100498685dc8SJohn Baldwin 	wpid = wait(&status);
100596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
100696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
100798685dc8SJohn Baldwin }
100898685dc8SJohn Baldwin 
1009368b2b1cSJohn Baldwin /*
1010368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
1011368b2b1cSJohn Baldwin  * parent but sees its original parent process.
1012368b2b1cSJohn Baldwin  */
1013368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
ATF_TC_BODY(ptrace__getppid,tc)1014368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
1015368b2b1cSJohn Baldwin {
1016368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
1017368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
1018368b2b1cSJohn Baldwin 	char c;
1019368b2b1cSJohn Baldwin 
102096a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(cpipe), 0);
1021368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
1022368b2b1cSJohn Baldwin 
1023368b2b1cSJohn Baldwin 	if (child == 0) {
1024368b2b1cSJohn Baldwin 		/* Child process. */
1025368b2b1cSJohn Baldwin 		close(cpipe[0]);
1026368b2b1cSJohn Baldwin 
1027368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
10281fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(read(cpipe[1], &c, sizeof(c)),
10291fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
1030368b2b1cSJohn Baldwin 
1031368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
1032368b2b1cSJohn Baldwin 		ppid = getppid();
10331fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(cpipe[1], &ppid, sizeof(ppid)),
10341fcbddecSAlex Richardson 		    (ssize_t)sizeof(ppid));
1035368b2b1cSJohn Baldwin 
1036368b2b1cSJohn Baldwin 		_exit(1);
1037368b2b1cSJohn Baldwin 	}
1038368b2b1cSJohn Baldwin 	close(cpipe[1]);
1039368b2b1cSJohn Baldwin 
104096a9e50eSAlex Richardson 	REQUIRE_EQ(pipe(dpipe), 0);
1041368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
1042368b2b1cSJohn Baldwin 
1043368b2b1cSJohn Baldwin 	if (debugger == 0) {
1044368b2b1cSJohn Baldwin 		/* Debugger process. */
1045368b2b1cSJohn Baldwin 		close(dpipe[0]);
1046368b2b1cSJohn Baldwin 
1047368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
1048368b2b1cSJohn Baldwin 
1049368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
105096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
1051368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
105296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1053368b2b1cSJohn Baldwin 
1054368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
1055368b2b1cSJohn Baldwin 
1056368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
10571fcbddecSAlex Richardson 		CHILD_REQUIRE_EQ(write(dpipe[1], &c, sizeof(c)),
10581fcbddecSAlex Richardson 		    (ssize_t)sizeof(c));
1059368b2b1cSJohn Baldwin 
1060368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
1061368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
106296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, child);
1063368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
106496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WEXITSTATUS(status), 1);
1065368b2b1cSJohn Baldwin 
1066368b2b1cSJohn Baldwin 		_exit(0);
1067368b2b1cSJohn Baldwin 	}
1068368b2b1cSJohn Baldwin 	close(dpipe[1]);
1069368b2b1cSJohn Baldwin 
1070368b2b1cSJohn Baldwin 	/* Parent process. */
1071368b2b1cSJohn Baldwin 
1072368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
10731fcbddecSAlex Richardson 	REQUIRE_EQ(read(dpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
1074368b2b1cSJohn Baldwin 
1075368b2b1cSJohn Baldwin 	/* Release the child. */
10761fcbddecSAlex Richardson 	REQUIRE_EQ(write(cpipe[0], &c, sizeof(c)), (ssize_t)sizeof(c));
1077368b2b1cSJohn Baldwin 
1078368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
10791fcbddecSAlex Richardson 	REQUIRE_EQ(read(cpipe[0], &ppid, sizeof(ppid)), (ssize_t)sizeof(ppid));
1080368b2b1cSJohn Baldwin 	close(cpipe[0]);
1081368b2b1cSJohn Baldwin 
108296a9e50eSAlex Richardson 	REQUIRE_EQ(ppid, getpid());
1083368b2b1cSJohn Baldwin 
1084368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
1085368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
108696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debugger);
1087368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
108896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
1089368b2b1cSJohn Baldwin 
1090368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
1091368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
109296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
1093368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
109496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1095368b2b1cSJohn Baldwin }
1096368b2b1cSJohn Baldwin 
1097189ac973SJohn Baldwin /*
1098189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1099189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
1100189ac973SJohn Baldwin  */
1101189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork,tc)1102189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
1103189ac973SJohn Baldwin {
1104189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1105189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1106189ac973SJohn Baldwin 	int status;
1107189ac973SJohn Baldwin 
1108189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1109189ac973SJohn Baldwin 	if (fpid == 0) {
1110189ac973SJohn Baldwin 		trace_me();
1111189ac973SJohn Baldwin 		follow_fork_parent(false);
1112189ac973SJohn Baldwin 	}
1113189ac973SJohn Baldwin 
1114189ac973SJohn Baldwin 	/* Parent process. */
1115189ac973SJohn Baldwin 	children[0] = fpid;
1116189ac973SJohn Baldwin 
1117189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1118189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
111996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1120189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
112196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1122189ac973SJohn Baldwin 
1123189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1124189ac973SJohn Baldwin 
1125189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1126189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1127189ac973SJohn Baldwin 
1128189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1129189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1130189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1131189ac973SJohn Baldwin 
1132189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1133189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
11341fcbddecSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, (unsigned)SYS_fork);
113596a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, pl[1].pl_syscall_code);
113696a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_narg, pl[1].pl_syscall_narg);
1137189ac973SJohn Baldwin 
1138189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1139189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1140189ac973SJohn Baldwin 
1141189ac973SJohn Baldwin 	/*
1142189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1143189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1144189ac973SJohn Baldwin 	 */
1145189ac973SJohn Baldwin 	wpid = wait(&status);
114696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1147189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
114896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1149189ac973SJohn Baldwin 
1150189ac973SJohn Baldwin 	wpid = wait(&status);
115196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1152189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
115396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1154189ac973SJohn Baldwin 
1155189ac973SJohn Baldwin 	wpid = wait(&status);
115696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
115796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1158189ac973SJohn Baldwin }
1159189ac973SJohn Baldwin 
1160189ac973SJohn Baldwin /*
1161189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1162189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1163189ac973SJohn Baldwin  */
1164189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork,tc)1165189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1166189ac973SJohn Baldwin {
1167189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1168189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1169189ac973SJohn Baldwin 	int status;
1170189ac973SJohn Baldwin 
1171189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1172189ac973SJohn Baldwin 	if (fpid == 0) {
1173189ac973SJohn Baldwin 		trace_me();
1174189ac973SJohn Baldwin 		follow_fork_parent(true);
1175189ac973SJohn Baldwin 	}
1176189ac973SJohn Baldwin 
1177189ac973SJohn Baldwin 	/* Parent process. */
1178189ac973SJohn Baldwin 	children[0] = fpid;
1179189ac973SJohn Baldwin 
1180189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1181189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
118296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1183189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
118496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1185189ac973SJohn Baldwin 
1186189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1187189ac973SJohn Baldwin 
1188189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1189189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1190189ac973SJohn Baldwin 
1191189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1192189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1193189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1194189ac973SJohn Baldwin 
1195189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1196189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
11971fcbddecSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, (unsigned)SYS_vfork);
119896a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_code, pl[1].pl_syscall_code);
119996a9e50eSAlex Richardson 	REQUIRE_EQ(pl[0].pl_syscall_narg, pl[1].pl_syscall_narg);
1200189ac973SJohn Baldwin 
1201189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1202189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1203189ac973SJohn Baldwin 
1204189ac973SJohn Baldwin 	/*
1205189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1206189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1207189ac973SJohn Baldwin 	 */
1208189ac973SJohn Baldwin 	wpid = wait(&status);
120996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1210189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
121196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1212189ac973SJohn Baldwin 
1213189ac973SJohn Baldwin 	wpid = wait(&status);
121496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1215189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
121696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1217189ac973SJohn Baldwin 
1218189ac973SJohn Baldwin 	wpid = wait(&status);
121996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
122096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1221189ac973SJohn Baldwin }
1222189ac973SJohn Baldwin 
1223189ac973SJohn Baldwin static void *
simple_thread(void * arg __unused)1224189ac973SJohn Baldwin simple_thread(void *arg __unused)
1225189ac973SJohn Baldwin {
1226189ac973SJohn Baldwin 
1227189ac973SJohn Baldwin 	pthread_exit(NULL);
1228189ac973SJohn Baldwin }
1229189ac973SJohn Baldwin 
12305fcfab6eSJohn Baldwin static __dead2 void
simple_thread_main(void)12315fcfab6eSJohn Baldwin simple_thread_main(void)
12325fcfab6eSJohn Baldwin {
12335fcfab6eSJohn Baldwin 	pthread_t thread;
12345fcfab6eSJohn Baldwin 
123596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_create(&thread, NULL, simple_thread, NULL), 0);
123696a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(thread, NULL), 0);
12375fcfab6eSJohn Baldwin 	exit(1);
12385fcfab6eSJohn Baldwin }
12395fcfab6eSJohn Baldwin 
1240189ac973SJohn Baldwin /*
1241189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1242189ac973SJohn Baldwin  * thread reports the correct value.
1243189ac973SJohn Baldwin  */
1244189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread,tc)1245189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1246189ac973SJohn Baldwin {
1247189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1248189ac973SJohn Baldwin 	pid_t fpid, wpid;
1249e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1250189ac973SJohn Baldwin 	int status;
1251189ac973SJohn Baldwin 
1252189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1253189ac973SJohn Baldwin 	if (fpid == 0) {
1254189ac973SJohn Baldwin 		trace_me();
12555fcfab6eSJohn Baldwin 		simple_thread_main();
1256189ac973SJohn Baldwin 	}
1257189ac973SJohn Baldwin 
1258189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1259189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
126096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1261189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
126296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1263189ac973SJohn Baldwin 
1264189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1265189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1266e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1267189ac973SJohn Baldwin 
1268189ac973SJohn Baldwin 	/*
1269189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1270189ac973SJohn Baldwin 	 * system call exits.
1271189ac973SJohn Baldwin 	 */
1272189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1273189ac973SJohn Baldwin 
1274189ac973SJohn Baldwin 	/*
1275189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1276189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1277189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1278189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1279189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1280189ac973SJohn Baldwin 	 */
1281189ac973SJohn Baldwin 	for (;;) {
1282189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
128396a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
1284189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
128596a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1286189ac973SJohn Baldwin 
1287189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1288189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1289189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1290189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1291e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1292189ac973SJohn Baldwin 			/* New thread seen. */
1293189ac973SJohn Baldwin 			break;
1294189ac973SJohn Baldwin 
129596a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1296189ac973SJohn Baldwin 	}
1297189ac973SJohn Baldwin 
1298189ac973SJohn Baldwin 	/* Wait for the child to exit. */
129996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1300189ac973SJohn Baldwin 	for (;;) {
1301189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
130296a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
1303189ac973SJohn Baldwin 		if (WIFEXITED(status))
1304189ac973SJohn Baldwin 			break;
1305189ac973SJohn Baldwin 
1306189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
130796a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
130896a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
1309189ac973SJohn Baldwin 	}
1310189ac973SJohn Baldwin 
131196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1312189ac973SJohn Baldwin 
1313189ac973SJohn Baldwin 	wpid = wait(&status);
131496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
131596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1316189ac973SJohn Baldwin }
1317189ac973SJohn Baldwin 
13185fcfab6eSJohn Baldwin /*
13195fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
13205fcfab6eSJohn Baldwin  */
13215fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
ATF_TC_BODY(ptrace__lwp_events,tc)13225fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
13235fcfab6eSJohn Baldwin {
13245fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
13255fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
13265fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
13275fcfab6eSJohn Baldwin 	int status;
13285fcfab6eSJohn Baldwin 
13295fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13305fcfab6eSJohn Baldwin 	if (fpid == 0) {
13315fcfab6eSJohn Baldwin 		trace_me();
13325fcfab6eSJohn Baldwin 		simple_thread_main();
13335fcfab6eSJohn Baldwin 	}
13345fcfab6eSJohn Baldwin 
13355fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13365fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
133796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13385fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
133996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
13405fcfab6eSJohn Baldwin 
13415fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13425fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13435fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13445fcfab6eSJohn Baldwin 
134596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
13465fcfab6eSJohn Baldwin 
13475fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
134896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13495fcfab6eSJohn Baldwin 
13505fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13515fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
135296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13535fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
135496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
13555fcfab6eSJohn Baldwin 
13565fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
135796a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
13585fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13595fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13605fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13615fcfab6eSJohn Baldwin 
136296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13635fcfab6eSJohn Baldwin 
13645fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
13655fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
136696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
13675fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
136896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
13695fcfab6eSJohn Baldwin 
13705fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
137196a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)),
13725fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
137396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[1]);
13745fcfab6eSJohn Baldwin 
137596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
13765fcfab6eSJohn Baldwin 
13775fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13785fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13795fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
138096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
13815fcfab6eSJohn Baldwin 
13825fcfab6eSJohn Baldwin 	wpid = wait(&status);
138396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
138496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
13855fcfab6eSJohn Baldwin }
13865fcfab6eSJohn Baldwin 
13875fcfab6eSJohn Baldwin static void *
exec_thread(void * arg __unused)13885fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
13895fcfab6eSJohn Baldwin {
13905fcfab6eSJohn Baldwin 
13915fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
13925fcfab6eSJohn Baldwin 	exit(127);
13935fcfab6eSJohn Baldwin }
13945fcfab6eSJohn Baldwin 
13955fcfab6eSJohn Baldwin static __dead2 void
exec_thread_main(void)13965fcfab6eSJohn Baldwin exec_thread_main(void)
13975fcfab6eSJohn Baldwin {
13985fcfab6eSJohn Baldwin 	pthread_t thread;
13995fcfab6eSJohn Baldwin 
140096a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_create(&thread, NULL, exec_thread, NULL), 0);
14015fcfab6eSJohn Baldwin 	for (;;)
14025fcfab6eSJohn Baldwin 		sleep(60);
14035fcfab6eSJohn Baldwin 	exit(1);
14045fcfab6eSJohn Baldwin }
14055fcfab6eSJohn Baldwin 
14065fcfab6eSJohn Baldwin /*
14075fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
14085fcfab6eSJohn Baldwin  * process that calls execve(2).
14095fcfab6eSJohn Baldwin  */
14105fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
ATF_TC_BODY(ptrace__lwp_events_exec,tc)14115fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
14125fcfab6eSJohn Baldwin {
14135fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
14145fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
14155fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
14165fcfab6eSJohn Baldwin 	int status;
14175fcfab6eSJohn Baldwin 
14185fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14195fcfab6eSJohn Baldwin 	if (fpid == 0) {
14205fcfab6eSJohn Baldwin 		trace_me();
14215fcfab6eSJohn Baldwin 		exec_thread_main();
14225fcfab6eSJohn Baldwin 	}
14235fcfab6eSJohn Baldwin 
14245fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14255fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
142696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14275fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
142896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
14295fcfab6eSJohn Baldwin 
14305fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
14315fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
14325fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
14335fcfab6eSJohn Baldwin 
143496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
14355fcfab6eSJohn Baldwin 
14365fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
143796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14385fcfab6eSJohn Baldwin 
14395fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
14405fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
144196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14425fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
144396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14445fcfab6eSJohn Baldwin 
14455fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
144696a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
14475fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
14485fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
14495fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
14505fcfab6eSJohn Baldwin 
145196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14525fcfab6eSJohn Baldwin 
14535fcfab6eSJohn Baldwin 	/*
14545fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
14555fcfab6eSJohn Baldwin 	 * single threading from execve().
14565fcfab6eSJohn Baldwin 	 */
14575fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
145896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
14595fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
146096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14615fcfab6eSJohn Baldwin 
14625fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
146396a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)),
14645fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
146596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[0]);
14665fcfab6eSJohn Baldwin 
146796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14685fcfab6eSJohn Baldwin 
14695fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
14705fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14715fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
147296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
14735fcfab6eSJohn Baldwin 
14745fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
147596a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)),
14765fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
147796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, lwps[1]);
14785fcfab6eSJohn Baldwin 
147996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
14805fcfab6eSJohn Baldwin 
14815fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
14825fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14835fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
148496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
14855fcfab6eSJohn Baldwin 
14865fcfab6eSJohn Baldwin 	wpid = wait(&status);
148796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
148896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
14895fcfab6eSJohn Baldwin }
14905fcfab6eSJohn Baldwin 
14913340c45bSJohn Baldwin static void
handler(int sig __unused)14923340c45bSJohn Baldwin handler(int sig __unused)
14933340c45bSJohn Baldwin {
14943340c45bSJohn Baldwin }
14953340c45bSJohn Baldwin 
14963340c45bSJohn Baldwin static void
signal_main(void)14973340c45bSJohn Baldwin signal_main(void)
14983340c45bSJohn Baldwin {
14993340c45bSJohn Baldwin 
15003340c45bSJohn Baldwin 	signal(SIGINFO, handler);
15013340c45bSJohn Baldwin 	raise(SIGINFO);
15023340c45bSJohn Baldwin 	exit(0);
15033340c45bSJohn Baldwin }
15043340c45bSJohn Baldwin 
15053340c45bSJohn Baldwin /*
15063340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
15073340c45bSJohn Baldwin  */
15083340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
ATF_TC_BODY(ptrace__siginfo,tc)15093340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
15103340c45bSJohn Baldwin {
15113340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
15123340c45bSJohn Baldwin 	pid_t fpid, wpid;
15133340c45bSJohn Baldwin 	int status;
15143340c45bSJohn Baldwin 
15153340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15163340c45bSJohn Baldwin 	if (fpid == 0) {
15173340c45bSJohn Baldwin 		trace_me();
15183340c45bSJohn Baldwin 		signal_main();
15193340c45bSJohn Baldwin 	}
15203340c45bSJohn Baldwin 
15213340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15223340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
152396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
15243340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
152596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15263340c45bSJohn Baldwin 
152796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15283340c45bSJohn Baldwin 
15293340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
15303340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15313340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
153296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGINFO);
15333340c45bSJohn Baldwin 
15343340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
153596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
15363340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
153796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, SI_LWP);
153896a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_pid, wpid);
15393340c45bSJohn Baldwin 
154096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15413340c45bSJohn Baldwin 
15423340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
15433340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15443340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
154596a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
15463340c45bSJohn Baldwin 
15473340c45bSJohn Baldwin 	wpid = wait(&status);
154896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
154996a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15503340c45bSJohn Baldwin }
15513340c45bSJohn Baldwin 
15528d570f64SJohn Baldwin /*
15538d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
15548d570f64SJohn Baldwin  */
15558d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
ATF_TC_BODY(ptrace__ptrace_exec_disable,tc)15568d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
15578d570f64SJohn Baldwin {
15588d570f64SJohn Baldwin 	pid_t fpid, wpid;
15598d570f64SJohn Baldwin 	int events, status;
15608d570f64SJohn Baldwin 
15618d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15628d570f64SJohn Baldwin 	if (fpid == 0) {
15638d570f64SJohn Baldwin 		trace_me();
15648d570f64SJohn Baldwin 		exec_thread(NULL);
15658d570f64SJohn Baldwin 	}
15668d570f64SJohn Baldwin 
15678d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15688d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
156996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
15708d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
157196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
15728d570f64SJohn Baldwin 
15738d570f64SJohn Baldwin 	events = 0;
15748d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
15758d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15768d570f64SJohn Baldwin 
157796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
15788d570f64SJohn Baldwin 
15798d570f64SJohn Baldwin 	/* Should get one event at exit. */
15808d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15818d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
158296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
15838d570f64SJohn Baldwin 
15848d570f64SJohn Baldwin 	wpid = wait(&status);
158596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
158696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
15878d570f64SJohn Baldwin }
15888d570f64SJohn Baldwin 
15898d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
ATF_TC_BODY(ptrace__ptrace_exec_enable,tc)15908d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
15918d570f64SJohn Baldwin {
15928d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
15938d570f64SJohn Baldwin 	pid_t fpid, wpid;
15948d570f64SJohn Baldwin 	int events, status;
15958d570f64SJohn Baldwin 
15968d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15978d570f64SJohn Baldwin 	if (fpid == 0) {
15988d570f64SJohn Baldwin 		trace_me();
15998d570f64SJohn Baldwin 		exec_thread(NULL);
16008d570f64SJohn Baldwin 	}
16018d570f64SJohn Baldwin 
16028d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16038d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
160496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
16058d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
160696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
16078d570f64SJohn Baldwin 
16088d570f64SJohn Baldwin 	events = PTRACE_EXEC;
16098d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
16108d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16118d570f64SJohn Baldwin 
161296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16138d570f64SJohn Baldwin 
16148d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
16158d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16168d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
161796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
16188d570f64SJohn Baldwin 
16198d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
162096a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)),
16218d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
16228d570f64SJohn Baldwin 
162396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16248d570f64SJohn Baldwin 
16258d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
16268d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16278d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
162896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16298d570f64SJohn Baldwin 
16308d570f64SJohn Baldwin 	wpid = wait(&status);
163196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
163296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
16338d570f64SJohn Baldwin }
16348d570f64SJohn Baldwin 
16358d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
ATF_TC_BODY(ptrace__event_mask,tc)16368d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
16378d570f64SJohn Baldwin {
16388d570f64SJohn Baldwin 	pid_t fpid, wpid;
16398d570f64SJohn Baldwin 	int events, status;
16408d570f64SJohn Baldwin 
16418d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
16428d570f64SJohn Baldwin 	if (fpid == 0) {
16438d570f64SJohn Baldwin 		trace_me();
16448d570f64SJohn Baldwin 		exit(0);
16458d570f64SJohn Baldwin 	}
16468d570f64SJohn Baldwin 
16478d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
16488d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
164996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
16508d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
165196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
16528d570f64SJohn Baldwin 
16538d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
16548d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -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_FORK);
16588d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
16598d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16608d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16618d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_FORK));
16628d570f64SJohn Baldwin 
16638d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
16648d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
16658d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16668d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16678d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_LWP);
16688d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
16698d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
16708d570f64SJohn Baldwin 	    sizeof(events)) == 0);
16718d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_LWP));
16728d570f64SJohn Baldwin 
167396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
16748d570f64SJohn Baldwin 
16758d570f64SJohn Baldwin 	/* Should get one event at exit. */
16768d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
16778d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
167896a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
16798d570f64SJohn Baldwin 
16808d570f64SJohn Baldwin 	wpid = wait(&status);
168196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
168296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
16838d570f64SJohn Baldwin }
16848d570f64SJohn Baldwin 
1685fc4f075aSJohn Baldwin /*
1686fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1687fc4f075aSJohn Baldwin  */
1688fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
ATF_TC_BODY(ptrace__ptrace_vfork,tc)1689fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1690fc4f075aSJohn Baldwin {
1691fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1692fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1693fc4f075aSJohn Baldwin 	int events, status;
1694fc4f075aSJohn Baldwin 
1695fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1696fc4f075aSJohn Baldwin 	if (fpid == 0) {
1697fc4f075aSJohn Baldwin 		trace_me();
1698fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1699fc4f075aSJohn Baldwin 	}
1700fc4f075aSJohn Baldwin 
1701fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1702fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
170396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1704fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
170596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1706fc4f075aSJohn Baldwin 
1707fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1708fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1709fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1710fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1711fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1712fc4f075aSJohn Baldwin 
1713fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1714fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1715fc4f075aSJohn Baldwin 
1716fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1717fc4f075aSJohn Baldwin 	wpid = wait(&status);
171896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1719fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
172096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1721fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1722fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1723fc4f075aSJohn Baldwin 
1724fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1725fc4f075aSJohn Baldwin 
1726fc4f075aSJohn Baldwin 	wpid = wait(&status);
172796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
1728fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
172996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1730fc4f075aSJohn Baldwin 
1731fc4f075aSJohn Baldwin 	wpid = wait(&status);
173296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
173396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1734fc4f075aSJohn Baldwin }
1735fc4f075aSJohn Baldwin 
1736fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
ATF_TC_BODY(ptrace__ptrace_vfork_follow,tc)1737fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1738fc4f075aSJohn Baldwin {
1739fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1740fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1741fc4f075aSJohn Baldwin 	int events, status;
1742fc4f075aSJohn Baldwin 
1743fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1744fc4f075aSJohn Baldwin 	if (fpid == 0) {
1745fc4f075aSJohn Baldwin 		trace_me();
1746fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1747fc4f075aSJohn Baldwin 	}
1748fc4f075aSJohn Baldwin 
1749fc4f075aSJohn Baldwin 	/* Parent process. */
1750fc4f075aSJohn Baldwin 	children[0] = fpid;
1751fc4f075aSJohn Baldwin 
1752fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1753fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
175496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1755fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
175696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
1757fc4f075aSJohn Baldwin 
1758fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1759fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1760fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1761fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1762fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1763fc4f075aSJohn Baldwin 
1764fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1765fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1766fc4f075aSJohn Baldwin 
1767fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1768fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1769fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1770fc4f075aSJohn Baldwin 
1771fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1772fc4f075aSJohn Baldwin 
1773fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1774fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1775fc4f075aSJohn Baldwin 
1776fc4f075aSJohn Baldwin 	/*
1777fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1778fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1779fc4f075aSJohn Baldwin 	 */
1780fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
178196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[1]);
1782fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
178396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 2);
1784fc4f075aSJohn Baldwin 
1785fc4f075aSJohn Baldwin 	/*
1786fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1787fc4f075aSJohn Baldwin 	 * exits.
1788fc4f075aSJohn Baldwin 	 */
1789fc4f075aSJohn Baldwin 	wpid = wait(&status);
179096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1791fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
179296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
1793fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1794fc4f075aSJohn Baldwin 	    -1);
1795fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1796fc4f075aSJohn Baldwin 
1797fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1798fc4f075aSJohn Baldwin 
1799fc4f075aSJohn Baldwin 	wpid = wait(&status);
180096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, children[0]);
1801fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
180296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
1803fc4f075aSJohn Baldwin 
1804fc4f075aSJohn Baldwin 	wpid = wait(&status);
180596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
180696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
1807fc4f075aSJohn Baldwin }
1808fc4f075aSJohn Baldwin 
1809403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
1810e2ebfbbfSEric Badger /*
181182a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
181282a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
181382a4538fSEric Badger  */
181482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
ATF_TC_BODY(ptrace__PT_KILL_breakpoint,tc)181582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
181682a4538fSEric Badger {
181782a4538fSEric Badger 	pid_t fpid, wpid;
181882a4538fSEric Badger 	int status;
181982a4538fSEric Badger 
182082a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
182182a4538fSEric Badger 	if (fpid == 0) {
182282a4538fSEric Badger 		trace_me();
18239e0d1159SEric Badger 		breakpoint();
182482a4538fSEric Badger 		exit(1);
182582a4538fSEric Badger 	}
182682a4538fSEric Badger 
182782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
182882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
182996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
183082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
183196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
183282a4538fSEric Badger 
183382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
183496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
183582a4538fSEric Badger 
183682a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
183782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
183896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
183982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
184096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
184182a4538fSEric Badger 
184282a4538fSEric Badger 	/* Kill the child process. */
184396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
184482a4538fSEric Badger 
184582a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
184682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
184796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
184882a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
184996a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
185082a4538fSEric Badger 
185182a4538fSEric Badger 	wpid = wait(&status);
185296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
185396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
185482a4538fSEric Badger }
1855403e331dSJohn Baldwin #endif /* HAVE_BREAKPOINT */
185682a4538fSEric Badger 
185782a4538fSEric Badger /*
185882a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
185982a4538fSEric Badger  * process exit when stopped inside of a system call.
186082a4538fSEric Badger  */
186182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
ATF_TC_BODY(ptrace__PT_KILL_system_call,tc)186282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
186382a4538fSEric Badger {
186482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
186582a4538fSEric Badger 	pid_t fpid, wpid;
186682a4538fSEric Badger 	int status;
186782a4538fSEric Badger 
186882a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
186982a4538fSEric Badger 	if (fpid == 0) {
187082a4538fSEric Badger 		trace_me();
187182a4538fSEric Badger 		getpid();
187282a4538fSEric Badger 		exit(1);
187382a4538fSEric Badger 	}
187482a4538fSEric Badger 
187582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
187682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
187796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
187882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
187996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
188082a4538fSEric Badger 
188182a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
188296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
188382a4538fSEric Badger 
188482a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
188582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
188696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
188782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
188896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
188982a4538fSEric Badger 
189082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
189182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
189282a4538fSEric Badger 
189382a4538fSEric Badger 	/* Kill the child process. */
189496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
189582a4538fSEric Badger 
189682a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
189782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
189896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
189982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
190096a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
190182a4538fSEric Badger 
190282a4538fSEric Badger 	wpid = wait(&status);
190396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
190496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
190582a4538fSEric Badger }
190682a4538fSEric Badger 
190782a4538fSEric Badger /*
190882a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
190982a4538fSEric Badger  * process exit when killing a multithreaded process.
191082a4538fSEric Badger  */
191182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
ATF_TC_BODY(ptrace__PT_KILL_threads,tc)191282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
191382a4538fSEric Badger {
191482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
191582a4538fSEric Badger 	pid_t fpid, wpid;
191682a4538fSEric Badger 	lwpid_t main_lwp;
191782a4538fSEric Badger 	int status;
191882a4538fSEric Badger 
191982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
192082a4538fSEric Badger 	if (fpid == 0) {
192182a4538fSEric Badger 		trace_me();
192282a4538fSEric Badger 		simple_thread_main();
192382a4538fSEric Badger 	}
192482a4538fSEric Badger 
192582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
192682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
192796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
192882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
192996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
193082a4538fSEric Badger 
193182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
193282a4538fSEric Badger 	    sizeof(pl)) != -1);
193382a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
193482a4538fSEric Badger 
193596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
193682a4538fSEric Badger 
193782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
193896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
193982a4538fSEric Badger 
194082a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
194182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
194296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
194382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
194496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
194582a4538fSEric Badger 
194682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
194796a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
194882a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
194982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
195082a4538fSEric Badger 
195182a4538fSEric Badger 	/* Kill the child process. */
195296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
195382a4538fSEric Badger 
195482a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
195582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
195696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
195782a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
195896a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
195982a4538fSEric Badger 
196082a4538fSEric Badger 	wpid = wait(&status);
196196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
196296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
196382a4538fSEric Badger }
196482a4538fSEric Badger 
196582a4538fSEric Badger static void *
mask_usr1_thread(void * arg)196682a4538fSEric Badger mask_usr1_thread(void *arg)
196782a4538fSEric Badger {
196882a4538fSEric Badger 	pthread_barrier_t *pbarrier;
196982a4538fSEric Badger 	sigset_t sigmask;
197082a4538fSEric Badger 
197182a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
197282a4538fSEric Badger 
197382a4538fSEric Badger 	sigemptyset(&sigmask);
197482a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
197596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
197682a4538fSEric Badger 
197782a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
197882a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
197982a4538fSEric Badger 
198082a4538fSEric Badger 	for (;;)
198182a4538fSEric Badger 		sleep(60);
198282a4538fSEric Badger 
198382a4538fSEric Badger 	return (NULL);
198482a4538fSEric Badger }
198582a4538fSEric Badger 
198682a4538fSEric Badger /*
198782a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
198882a4538fSEric Badger  * and prevents spurious stops due to those other signals.
198982a4538fSEric Badger  */
19903cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal);
ATF_TC_HEAD(ptrace__PT_KILL_competing_signal,tc)19913cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
19923cf56bb4SEnji Cooper {
19933cf56bb4SEnji Cooper 
19943cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
19953cf56bb4SEnji Cooper }
ATF_TC_BODY(ptrace__PT_KILL_competing_signal,tc)199682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
199782a4538fSEric Badger {
199882a4538fSEric Badger 	pid_t fpid, wpid;
199982a4538fSEric Badger 	int status;
200082a4538fSEric Badger 	cpuset_t setmask;
200182a4538fSEric Badger 	pthread_t t;
200282a4538fSEric Badger 	pthread_barrier_t barrier;
2003bc2be1d3SEric Badger 	struct sched_param sched_param;
200482a4538fSEric Badger 
200582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
200682a4538fSEric Badger 	if (fpid == 0) {
2007bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
200882a4538fSEric Badger 		CPU_ZERO(&setmask);
200982a4538fSEric Badger 		CPU_SET(0, &setmask);
201082a4538fSEric Badger 		cpusetid_t setid;
201196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(cpuset(&setid), 0);
201282a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
201382a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
201482a4538fSEric Badger 
201596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
201682a4538fSEric Badger 
201782a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
201882a4538fSEric Badger 		    (void*)&barrier) == 0);
201982a4538fSEric Badger 
2020bc2be1d3SEric Badger 		/*
2021bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2022bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2023bc2be1d3SEric Badger 		 * thread runs first.
2024bc2be1d3SEric Badger 		 */
2025bc2be1d3SEric Badger 		sched_param.sched_priority =
2026bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2027bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2028bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2029bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2030bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2031bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2032bc2be1d3SEric Badger 		    &sched_param) == 0);
2033bc2be1d3SEric Badger 
203482a4538fSEric Badger 		sigset_t sigmask;
203582a4538fSEric Badger 		sigemptyset(&sigmask);
203682a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
203796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
203882a4538fSEric Badger 
203982a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
204082a4538fSEric Badger 		pthread_barrier_wait(&barrier);
204182a4538fSEric Badger 
204282a4538fSEric Badger 		trace_me();
204382a4538fSEric Badger 
204482a4538fSEric Badger 		for (;;)
204582a4538fSEric Badger 			sleep(60);
204682a4538fSEric Badger 
204782a4538fSEric Badger 		exit(1);
204882a4538fSEric Badger 	}
204982a4538fSEric Badger 
205082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
205182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
205296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
205382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
205496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
205582a4538fSEric Badger 
205682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
205796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
205882a4538fSEric Badger 
205982a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
206096a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
206182a4538fSEric Badger 
206282a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
206382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
206496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
206582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
206696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
206782a4538fSEric Badger 
206882a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
206996a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
207082a4538fSEric Badger 
207182a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
207296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
207382a4538fSEric Badger 
207482a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
207582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
207696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
207782a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
207896a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
207982a4538fSEric Badger 
208082a4538fSEric Badger 	wpid = wait(&status);
208196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
208296a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
208382a4538fSEric Badger }
208482a4538fSEric Badger 
208582a4538fSEric Badger /*
208682a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
208782a4538fSEric Badger  * and prevents spurious stops caused by those events.
208882a4538fSEric Badger  */
20893cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop);
ATF_TC_HEAD(ptrace__PT_KILL_competing_stop,tc)20903cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc)
20913cf56bb4SEnji Cooper {
20923cf56bb4SEnji Cooper 
20933cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
20943cf56bb4SEnji Cooper }
ATF_TC_BODY(ptrace__PT_KILL_competing_stop,tc)209582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
209682a4538fSEric Badger {
209782a4538fSEric Badger 	pid_t fpid, wpid;
2098bc2be1d3SEric Badger 	int status;
209982a4538fSEric Badger 	cpuset_t setmask;
210082a4538fSEric Badger 	pthread_t t;
210182a4538fSEric Badger 	pthread_barrier_t barrier;
210282a4538fSEric Badger 	lwpid_t main_lwp;
210382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2104bc2be1d3SEric Badger 	struct sched_param sched_param;
210582a4538fSEric Badger 
210682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
210782a4538fSEric Badger 	if (fpid == 0) {
210882a4538fSEric Badger 		trace_me();
210982a4538fSEric Badger 
2110bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
211182a4538fSEric Badger 		CPU_ZERO(&setmask);
211282a4538fSEric Badger 		CPU_SET(0, &setmask);
211382a4538fSEric Badger 		cpusetid_t setid;
211496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(cpuset(&setid), 0);
211582a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
211682a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
211782a4538fSEric Badger 
211896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
211982a4538fSEric Badger 
212082a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
212182a4538fSEric Badger 		    (void*)&barrier) == 0);
212282a4538fSEric Badger 
2123bc2be1d3SEric Badger 		/*
2124bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2125bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2126bc2be1d3SEric Badger 		 * thread runs first.
2127bc2be1d3SEric Badger 		 */
2128bc2be1d3SEric Badger 		sched_param.sched_priority =
2129bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2130bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2131bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2132bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2133bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2134bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2135bc2be1d3SEric Badger 		    &sched_param) == 0);
2136bc2be1d3SEric Badger 
213782a4538fSEric Badger 		sigset_t sigmask;
213882a4538fSEric Badger 		sigemptyset(&sigmask);
213982a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
214096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
214182a4538fSEric Badger 
214282a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
214382a4538fSEric Badger 		pthread_barrier_wait(&barrier);
214482a4538fSEric Badger 
214582a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
214682a4538fSEric Badger 		raise(SIGSTOP);
214782a4538fSEric Badger 
214882a4538fSEric Badger 		getpid();
214982a4538fSEric Badger 		exit(1);
215082a4538fSEric Badger 	}
215182a4538fSEric Badger 
215282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
215382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
215496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
215582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
215696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
215782a4538fSEric Badger 
215882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
215982a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
216082a4538fSEric Badger 
216182a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
216296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
216382a4538fSEric Badger 
216482a4538fSEric Badger 	/*
216582a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
216682a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
216782a4538fSEric Badger 	 */
216882a4538fSEric Badger 	for (;;) {
216982a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
217096a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
217182a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
217282a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
217382a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
217482a4538fSEric Badger 			    sizeof(pl)) != -1);
217582a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
217682a4538fSEric Badger 		} else {
217796a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
217882a4538fSEric Badger 			break;
217982a4538fSEric Badger 		}
218096a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
218182a4538fSEric Badger 	}
218282a4538fSEric Badger 
2183bc2be1d3SEric Badger 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
218496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
218582a4538fSEric Badger 
218682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
218796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
218882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
218996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
219082a4538fSEric Badger 
219182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
219282a4538fSEric Badger 	    sizeof(pl)) != -1);
219396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_lwpid, main_lwp);
219482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
2195bc2be1d3SEric Badger 	/* Prevent the main thread from hitting its syscall exit for now. */
219696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SUSPEND, main_lwp, 0, 0), 0);
219782a4538fSEric Badger 
2198bc2be1d3SEric Badger 	/*
2199bc2be1d3SEric Badger 	 * Proceed, allowing second thread to hit syscall exit for
2200bc2be1d3SEric Badger 	 * pthread_barrier_wait().
2201bc2be1d3SEric Badger 	 */
220296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
2203bc2be1d3SEric Badger 
2204bc2be1d3SEric Badger 	wpid = waitpid(fpid, &status, 0);
220596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2206bc2be1d3SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
220796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
2208bc2be1d3SEric Badger 
2209bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
2210bc2be1d3SEric Badger 	    sizeof(pl)) != -1);
2211bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
2212bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
221382a4538fSEric Badger 
221482a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
221596a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
221682a4538fSEric Badger 
221796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
221882a4538fSEric Badger 
2219bc2be1d3SEric Badger 	/* The next wait() should report the SIGUSR2. */
222082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
222196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
222282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
222396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
222482a4538fSEric Badger 
222582a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
222696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_RESUME, main_lwp, 0, 0), 0);
222782a4538fSEric Badger 
222882a4538fSEric Badger 	/*
222982a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
2230bc2be1d3SEric Badger 	 * has been resumed. The second thread has taken a SIGUSR2 which will
2231bc2be1d3SEric Badger 	 * be replaced with a SIGKILL below. The main thread will get to run
2232bc2be1d3SEric Badger 	 * first. It should notice the kill request (even though the signal
2233bc2be1d3SEric Badger 	 * replacement occurred in the other thread) and exit accordingly.  It
2234bc2be1d3SEric Badger 	 * should not stop for the system call exit event.
223582a4538fSEric Badger 	 */
223682a4538fSEric Badger 
223782a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
223896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
223982a4538fSEric Badger 
224082a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
224182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
224296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
224382a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
224496a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
224582a4538fSEric Badger 
224682a4538fSEric Badger 	wpid = wait(&status);
224796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
224896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
224982a4538fSEric Badger }
225082a4538fSEric Badger 
225182a4538fSEric Badger static void
sigusr1_handler(int sig)225282a4538fSEric Badger sigusr1_handler(int sig)
225382a4538fSEric Badger {
225482a4538fSEric Badger 
225596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
225682a4538fSEric Badger 	_exit(2);
225782a4538fSEric Badger }
225882a4538fSEric Badger 
225982a4538fSEric Badger /*
226082a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
226182a4538fSEric Badger  * a PT_KILL will kill the process.
226282a4538fSEric Badger  */
226382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue,tc)226482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
226582a4538fSEric Badger {
226682a4538fSEric Badger 	pid_t fpid, wpid;
226782a4538fSEric Badger 	int status;
226882a4538fSEric Badger 	int max_pending_per_proc;
226982a4538fSEric Badger 	size_t len;
227082a4538fSEric Badger 	int i;
227182a4538fSEric Badger 
227282a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
227382a4538fSEric Badger 
227482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
227582a4538fSEric Badger 	if (fpid == 0) {
227682a4538fSEric Badger 		trace_me();
227782a4538fSEric Badger 		exit(1);
227882a4538fSEric Badger 	}
227982a4538fSEric Badger 
228082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
228182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
228296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
228382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
228496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
228582a4538fSEric Badger 
228682a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
228782a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
228882a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
228982a4538fSEric Badger 
229082a4538fSEric Badger 	/* Fill the signal queue. */
229182a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
229296a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
229382a4538fSEric Badger 
229482a4538fSEric Badger 	/* Kill the child process. */
229596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
229682a4538fSEric Badger 
229782a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
229882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
229996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
230082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
230196a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
230282a4538fSEric Badger 
230382a4538fSEric Badger 	wpid = wait(&status);
230496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
230596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
230682a4538fSEric Badger }
230782a4538fSEric Badger 
230882a4538fSEric Badger /*
230982a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
231082a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
231182a4538fSEric Badger  * call is complete.
231282a4538fSEric Badger  */
231382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry,tc)231482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
231582a4538fSEric Badger {
231682a4538fSEric Badger 	struct ptrace_lwpinfo pl;
231782a4538fSEric Badger 	pid_t fpid, wpid;
231882a4538fSEric Badger 	int status;
231982a4538fSEric Badger 
232082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
232182a4538fSEric Badger 
232282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
232382a4538fSEric Badger 	if (fpid == 0) {
232482a4538fSEric Badger 		trace_me();
232582a4538fSEric Badger 		getpid();
232682a4538fSEric Badger 		exit(1);
232782a4538fSEric Badger 	}
232882a4538fSEric Badger 
232982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
233082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
233196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
233282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
233396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
233482a4538fSEric Badger 
233582a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
233696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
233782a4538fSEric Badger 
233882a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
233982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
234096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
234182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
234296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
234382a4538fSEric Badger 
234482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
234582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
234682a4538fSEric Badger 
234782a4538fSEric Badger 	/* Continue the child process with a signal. */
234896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
234982a4538fSEric Badger 
235082a4538fSEric Badger 	for (;;) {
235182a4538fSEric Badger 		/*
235282a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
235382a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
235482a4538fSEric Badger 		 * past any syscall stops.
235582a4538fSEric Badger 		 */
235682a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
235796a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
235882a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
235982a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
236082a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
236196a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
236282a4538fSEric Badger 		} else {
236382a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
236496a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
236582a4538fSEric Badger 			break;
236682a4538fSEric Badger 		}
236782a4538fSEric Badger 	}
236882a4538fSEric Badger 
236982a4538fSEric Badger 	wpid = wait(&status);
237096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
237196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
237282a4538fSEric Badger }
237382a4538fSEric Badger 
237482a4538fSEric Badger static void
sigusr1_counting_handler(int sig)237582a4538fSEric Badger sigusr1_counting_handler(int sig)
237682a4538fSEric Badger {
237782a4538fSEric Badger 	static int counter = 0;
237882a4538fSEric Badger 
237996a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
238082a4538fSEric Badger 	counter++;
238182a4538fSEric Badger 	if (counter == 2)
238282a4538fSEric Badger 		_exit(2);
238382a4538fSEric Badger }
238482a4538fSEric Badger 
238582a4538fSEric Badger /*
238682a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
238782a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
238882a4538fSEric Badger  * the system call is complete.
238982a4538fSEric Badger  */
239082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit,tc)239182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
239282a4538fSEric Badger {
239382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
239482a4538fSEric Badger 	pid_t fpid, wpid;
239582a4538fSEric Badger 	int status;
239682a4538fSEric Badger 
239782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
239882a4538fSEric Badger 
239982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
240082a4538fSEric Badger 	if (fpid == 0) {
240182a4538fSEric Badger 		trace_me();
240282a4538fSEric Badger 		getpid();
240382a4538fSEric Badger 		exit(1);
240482a4538fSEric Badger 	}
240582a4538fSEric Badger 
240682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
240782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
240896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
240982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
241096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
241182a4538fSEric Badger 
241282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
241396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
241482a4538fSEric Badger 
241582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
241682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
241796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
241882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
241996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
242082a4538fSEric Badger 
242182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
242282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
242382a4538fSEric Badger 
242482a4538fSEric Badger 	/* Continue the child process with a signal. */
242596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
242682a4538fSEric Badger 
242782a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
242882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
242996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
243082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
243196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
243282a4538fSEric Badger 
243382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
243482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
243582a4538fSEric Badger 
243682a4538fSEric Badger 	/* Continue the child process with a signal. */
243796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
243882a4538fSEric Badger 
243982a4538fSEric Badger 	for (;;) {
244082a4538fSEric Badger 		/*
244182a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
244282a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
244382a4538fSEric Badger 		 * past any syscall stops.
244482a4538fSEric Badger 		 */
244582a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
244696a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
244782a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
244882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
244982a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
245096a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
245182a4538fSEric Badger 		} else {
245282a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
245396a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
245482a4538fSEric Badger 			break;
245582a4538fSEric Badger 		}
245682a4538fSEric Badger 	}
245782a4538fSEric Badger 
245882a4538fSEric Badger 	wpid = wait(&status);
245996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
246096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
246182a4538fSEric Badger }
246282a4538fSEric Badger 
246382a4538fSEric Badger /*
246482a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
246582a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
246682a4538fSEric Badger  */
246782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue,tc)246882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
246982a4538fSEric Badger {
247082a4538fSEric Badger 	pid_t fpid, wpid;
247182a4538fSEric Badger 	int status;
247282a4538fSEric Badger 	int max_pending_per_proc;
247382a4538fSEric Badger 	size_t len;
247482a4538fSEric Badger 	int i;
247582a4538fSEric Badger 
247682a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
247782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
247882a4538fSEric Badger 
247982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
248082a4538fSEric Badger 	if (fpid == 0) {
248182a4538fSEric Badger 		trace_me();
248282a4538fSEric Badger 		exit(1);
248382a4538fSEric Badger 	}
248482a4538fSEric Badger 
248582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
248682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
248796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
248882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
248996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
249082a4538fSEric Badger 
249182a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
249282a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
249382a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
249482a4538fSEric Badger 
249582a4538fSEric Badger 	/* Fill the signal queue. */
249682a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
249796a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
249882a4538fSEric Badger 
249982a4538fSEric Badger 	/* Continue with signal. */
250096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
250182a4538fSEric Badger 
250282a4538fSEric Badger 	for (;;) {
250382a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
250496a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
250582a4538fSEric Badger 		if (WIFSTOPPED(status)) {
250696a9e50eSAlex Richardson 			REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
250796a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
250882a4538fSEric Badger 		} else {
250982a4538fSEric Badger 			/*
251082a4538fSEric Badger 			 * The last wait() should report normal _exit from the
251182a4538fSEric Badger 			 * SIGUSR1 handler.
251282a4538fSEric Badger 			 */
251382a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
251496a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
251582a4538fSEric Badger 			break;
251682a4538fSEric Badger 		}
251782a4538fSEric Badger 	}
251882a4538fSEric Badger 
251982a4538fSEric Badger 	wpid = wait(&status);
252096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
252196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
252282a4538fSEric Badger }
252382a4538fSEric Badger 
2524753e2922SBryan Drewery static sem_t sigusr1_sem;
2525753e2922SBryan Drewery static int got_usr1;
2526753e2922SBryan Drewery 
2527753e2922SBryan Drewery static void
sigusr1_sempost_handler(int sig __unused)2528753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused)
2529753e2922SBryan Drewery {
2530753e2922SBryan Drewery 
2531753e2922SBryan Drewery 	got_usr1++;
253296a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sem_post(&sigusr1_sem), 0);
2533753e2922SBryan Drewery }
2534753e2922SBryan Drewery 
2535753e2922SBryan Drewery /*
2536753e2922SBryan Drewery  * Verify that even if the signal queue is full for a child process,
2537753e2922SBryan Drewery  * and the signal is masked, a PT_CONTINUE with a signal will not
2538753e2922SBryan Drewery  * result in loss of that signal.
2539753e2922SBryan Drewery  */
2540753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue,tc)2541753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
2542753e2922SBryan Drewery {
2543753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2544753e2922SBryan Drewery 	pid_t fpid, wpid;
2545753e2922SBryan Drewery 	int status, err;
2546753e2922SBryan Drewery 	int max_pending_per_proc;
2547753e2922SBryan Drewery 	size_t len;
2548753e2922SBryan Drewery 	int i;
2549753e2922SBryan Drewery 	sigset_t sigmask;
2550753e2922SBryan Drewery 
2551753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
255296a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
2553753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2554753e2922SBryan Drewery 
2555753e2922SBryan Drewery 	got_usr1 = 0;
2556753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2557753e2922SBryan Drewery 	if (fpid == 0) {
255896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
255996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
256096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
2561753e2922SBryan Drewery 
2562753e2922SBryan Drewery 		trace_me();
256396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
2564753e2922SBryan Drewery 
2565753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
256696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
2567753e2922SBryan Drewery 		/* Wait to receive the SIGUSR1. */
2568753e2922SBryan Drewery 		do {
2569753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2570753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2571753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
257296a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
2573753e2922SBryan Drewery 		exit(1);
2574753e2922SBryan Drewery 	}
2575753e2922SBryan Drewery 
2576753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2577753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
257896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2579753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
258096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
2581753e2922SBryan Drewery 
2582753e2922SBryan Drewery 	len = sizeof(max_pending_per_proc);
2583753e2922SBryan Drewery 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
2584753e2922SBryan Drewery 	    &max_pending_per_proc, &len, NULL, 0) == 0);
2585753e2922SBryan Drewery 
2586753e2922SBryan Drewery 	/* Fill the signal queue. */
2587753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i)
258896a9e50eSAlex Richardson 		REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
2589753e2922SBryan Drewery 
2590753e2922SBryan Drewery 	/* Continue with signal. */
259196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
2592753e2922SBryan Drewery 
2593753e2922SBryan Drewery 	/* Collect and ignore all of the SIGUSR2. */
2594753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i) {
2595753e2922SBryan Drewery 		wpid = waitpid(fpid, &status, 0);
259696a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
2597753e2922SBryan Drewery 		ATF_REQUIRE(WIFSTOPPED(status));
259896a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
259996a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2600753e2922SBryan Drewery 	}
2601753e2922SBryan Drewery 
2602753e2922SBryan Drewery 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
2603753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
260496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2605753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
260696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
2607753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
260896a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
2609753e2922SBryan Drewery 
2610753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
261196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2612753e2922SBryan Drewery 
2613753e2922SBryan Drewery 	/* The last wait() should report exit after receiving SIGUSR1. */
2614753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
261596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2616753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
261796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
2618753e2922SBryan Drewery 
2619753e2922SBryan Drewery 	wpid = wait(&status);
262096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
262196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
2622753e2922SBryan Drewery }
2623753e2922SBryan Drewery 
262482a4538fSEric Badger /*
262582a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
262682a4538fSEric Badger  * replaced with another signal.
262782a4538fSEric Badger  */
262882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig,tc)262982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
263082a4538fSEric Badger {
263182a4538fSEric Badger 	struct ptrace_lwpinfo pl;
263282a4538fSEric Badger 	pid_t fpid, wpid;
263382a4538fSEric Badger 	int status;
263482a4538fSEric Badger 
263582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
263682a4538fSEric Badger 	if (fpid == 0) {
263782a4538fSEric Badger 		trace_me();
263882a4538fSEric Badger 		sleep(20);
263982a4538fSEric Badger 		exit(1);
264082a4538fSEric Badger 	}
264182a4538fSEric Badger 
264282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
264382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
264496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
264582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
264696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
264782a4538fSEric Badger 
264896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
264982a4538fSEric Badger 
265082a4538fSEric Badger 	/* Send a signal without ptrace. */
265196a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGINT), 0);
265282a4538fSEric Badger 
265382a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
265482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
265596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
265682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
265796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGINT);
265882a4538fSEric Badger 
265982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
266082a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
266196a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGINT);
266282a4538fSEric Badger 
266382a4538fSEric Badger 	/* Continue the child process with a different signal. */
266496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM), 0);
266582a4538fSEric Badger 
266682a4538fSEric Badger 	/*
266782a4538fSEric Badger 	 * The last wait() should report having died due to the new
266882a4538fSEric Badger 	 * signal, SIGTERM.
266982a4538fSEric Badger 	 */
267082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
267196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
267282a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
267396a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGTERM);
267482a4538fSEric Badger 
267582a4538fSEric Badger 	wpid = wait(&status);
267696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
267796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
267882a4538fSEric Badger }
267982a4538fSEric Badger 
268082a4538fSEric Badger /*
268182a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
268282a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
268382a4538fSEric Badger  * invented for e.g, system call stops.
268482a4538fSEric Badger  */
268582a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry,tc)268682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
268782a4538fSEric Badger {
268882a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2689fc1e29dcSBryan Drewery 	struct rlimit rl;
269082a4538fSEric Badger 	pid_t fpid, wpid;
269182a4538fSEric Badger 	int status;
269282a4538fSEric Badger 
269382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
269482a4538fSEric Badger 	if (fpid == 0) {
269582a4538fSEric Badger 		trace_me();
2696fc1e29dcSBryan Drewery 		/* SIGTRAP expected to cause exit on syscall entry. */
2697fc1e29dcSBryan Drewery 		rl.rlim_cur = rl.rlim_max = 0;
269896a9e50eSAlex Richardson 		REQUIRE_EQ(setrlimit(RLIMIT_CORE, &rl), 0);
269982a4538fSEric Badger 		getpid();
270082a4538fSEric Badger 		exit(1);
270182a4538fSEric Badger 	}
270282a4538fSEric Badger 
270382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
270482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
270596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
270682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
270796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
270882a4538fSEric Badger 
270982a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
271096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
271182a4538fSEric Badger 
271282a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
271382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
271496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
271582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
271696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
271782a4538fSEric Badger 
271882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
271982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
272082a4538fSEric Badger 
272182a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
272296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP), 0);
272382a4538fSEric Badger 
272482a4538fSEric Badger 	for (;;) {
272582a4538fSEric Badger 		/*
272682a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
272782a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
272882a4538fSEric Badger 		 */
272982a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
273096a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
273182a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
273282a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
273382a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
273496a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
273582a4538fSEric Badger 		} else {
273682a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
273796a9e50eSAlex Richardson 			REQUIRE_EQ(WTERMSIG(status), SIGTRAP);
273882a4538fSEric Badger 			break;
273982a4538fSEric Badger 		}
274082a4538fSEric Badger 	}
274182a4538fSEric Badger 
274282a4538fSEric Badger 	wpid = wait(&status);
274396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
274496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
274582a4538fSEric Badger }
274682a4538fSEric Badger 
274782a4538fSEric Badger /*
274882a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
274982a4538fSEric Badger  */
275082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix,tc)275182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
275282a4538fSEric Badger {
275382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
275482a4538fSEric Badger 	pid_t fpid, wpid;
275582a4538fSEric Badger 	int status;
275682a4538fSEric Badger 
275782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
275882a4538fSEric Badger 
275982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
276082a4538fSEric Badger 	if (fpid == 0) {
276182a4538fSEric Badger 		trace_me();
276282a4538fSEric Badger 		getpid();
276382a4538fSEric Badger 		exit(1);
276482a4538fSEric Badger 	}
276582a4538fSEric Badger 
276682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
276782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
276896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
276982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
277096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
277182a4538fSEric Badger 
277282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
277396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
277482a4538fSEric Badger 
277582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
277682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
277796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
277882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
277996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
278082a4538fSEric Badger 
278182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
278282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
278382a4538fSEric Badger 
278482a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
278596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
278682a4538fSEric Badger 
278782a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
278882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
278996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
279082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
279196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
279282a4538fSEric Badger 
279382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
279482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
279582a4538fSEric Badger 
279682a4538fSEric Badger 	/* Send an ABRT without ptrace. */
279796a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGABRT), 0);
279882a4538fSEric Badger 
279982a4538fSEric Badger 	/* Continue normally. */
280096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
280182a4538fSEric Badger 
280282a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
280382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
280496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
280582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
280696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
280782a4538fSEric Badger 
280882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
280982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
281096a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
281182a4538fSEric Badger 
281282a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
281396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
281482a4538fSEric Badger 
281582a4538fSEric Badger 	for (;;) {
281682a4538fSEric Badger 		/*
281782a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
281882a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
281982a4538fSEric Badger 		 * past any syscall stops.
282082a4538fSEric Badger 		 */
282182a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
282296a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
282382a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
282482a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
282582a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
282696a9e50eSAlex Richardson 			REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
282782a4538fSEric Badger 		} else {
282882a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
282996a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 2);
283082a4538fSEric Badger 			break;
283182a4538fSEric Badger 		}
283282a4538fSEric Badger 	}
283382a4538fSEric Badger 
283482a4538fSEric Badger 	wpid = wait(&status);
283596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
283696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
283782a4538fSEric Badger }
283882a4538fSEric Badger 
283982a4538fSEric Badger /*
284082a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
284182a4538fSEric Badger  */
284282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue,tc)284382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
284482a4538fSEric Badger {
284582a4538fSEric Badger 	pid_t fpid, wpid;
284682a4538fSEric Badger 	int status, kq, nevents;
284782a4538fSEric Badger 	struct kevent kev;
284882a4538fSEric Badger 
284982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
285082a4538fSEric Badger 
285182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
285282a4538fSEric Badger 	if (fpid == 0) {
285382a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
285482a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
285596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(kevent(kq, &kev, 1, NULL, 0, NULL), 0);
285682a4538fSEric Badger 
285782a4538fSEric Badger 		trace_me();
285882a4538fSEric Badger 
285982a4538fSEric Badger 		for (;;) {
286082a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
286182a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
286282a4538fSEric Badger 				continue;
286382a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
286496a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(kev.filter, EVFILT_SIGNAL);
28651fcbddecSAlex Richardson 			CHILD_REQUIRE_EQ(kev.ident, (uintptr_t)SIGUSR1);
286682a4538fSEric Badger 			break;
286782a4538fSEric Badger 		}
286882a4538fSEric Badger 
286982a4538fSEric Badger 		exit(1);
287082a4538fSEric Badger 	}
287182a4538fSEric Badger 
287282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
287382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
287496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
287582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
287696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
287782a4538fSEric Badger 
287882a4538fSEric Badger 	/* Continue with the SIGUSR1. */
287996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
288082a4538fSEric Badger 
288182a4538fSEric Badger 	/*
288282a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
288382a4538fSEric Badger 	 */
288482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
288596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
288682a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
288796a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
288882a4538fSEric Badger 
288982a4538fSEric Badger 	wpid = wait(&status);
289096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
289196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
289282a4538fSEric Badger }
289382a4538fSEric Badger 
289482a4538fSEric Badger static void *
signal_thread(void * arg)289582a4538fSEric Badger signal_thread(void *arg)
289682a4538fSEric Badger {
289782a4538fSEric Badger 	int err;
289882a4538fSEric Badger 	sigset_t sigmask;
289982a4538fSEric Badger 
290082a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
290182a4538fSEric Badger 
290282a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
290382a4538fSEric Badger 	do {
290482a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
290582a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
290682a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
290782a4538fSEric Badger 
290882a4538fSEric Badger 	/* Free our companion thread from the barrier. */
290982a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
291082a4538fSEric Badger 
291182a4538fSEric Badger 	/*
291282a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
291382a4538fSEric Badger 	 * other thread.
291482a4538fSEric Badger 	 */
291596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
291696a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
291796a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
291882a4538fSEric Badger 
291982a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
292082a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
292182a4538fSEric Badger 
292282a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
292382a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
292482a4538fSEric Badger 
292582a4538fSEric Badger 	return (NULL);
292682a4538fSEric Badger }
292782a4538fSEric Badger 
292882a4538fSEric Badger /*
2929753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2930753e2922SBryan Drewery  * signal from kill() once unmasked.
2931753e2922SBryan Drewery  */
2932753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
ATF_TC_BODY(ptrace__killed_with_sigmask,tc)2933753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
2934753e2922SBryan Drewery {
2935753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2936753e2922SBryan Drewery 	pid_t fpid, wpid;
2937753e2922SBryan Drewery 	int status, err;
2938753e2922SBryan Drewery 	sigset_t sigmask;
2939753e2922SBryan Drewery 
294096a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
2941753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2942753e2922SBryan Drewery 	got_usr1 = 0;
2943753e2922SBryan Drewery 
2944753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2945753e2922SBryan Drewery 	if (fpid == 0) {
294696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
294796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
294896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
2949753e2922SBryan Drewery 
2950753e2922SBryan Drewery 		trace_me();
295196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
2952753e2922SBryan Drewery 
2953753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
295496a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
2955753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2956753e2922SBryan Drewery 		do {
2957753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2958753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2959753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
296096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
2961753e2922SBryan Drewery 		exit(1);
2962753e2922SBryan Drewery 	}
2963753e2922SBryan Drewery 
2964753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2965753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
296696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2967753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
296896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
2969753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
297096a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGSTOP);
2971753e2922SBryan Drewery 
2972753e2922SBryan Drewery 	/* Send blocked SIGUSR1 which should cause a stop. */
297396a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR1), 0);
2974753e2922SBryan Drewery 
2975753e2922SBryan Drewery 	/* Continue the child ignoring the SIGSTOP. */
297696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
2977753e2922SBryan Drewery 
2978753e2922SBryan Drewery 	/* The next wait() should report the kill(SIGUSR1) was received. */
2979753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
298096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2981753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
298296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
2983753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
298496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
2985753e2922SBryan Drewery 
2986753e2922SBryan Drewery 	/* Continue the child, allowing in the SIGUSR1. */
298796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
2988753e2922SBryan Drewery 
2989753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
2990753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
299196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
2992753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
299396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
2994753e2922SBryan Drewery 
2995753e2922SBryan Drewery 	wpid = wait(&status);
299696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
299796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
2998753e2922SBryan Drewery }
2999753e2922SBryan Drewery 
3000753e2922SBryan Drewery /*
3001753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
3002753e2922SBryan Drewery  * signal from PT_CONTINUE once unmasked.
3003753e2922SBryan Drewery  */
3004753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask,tc)3005753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
3006753e2922SBryan Drewery {
3007753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
3008753e2922SBryan Drewery 	pid_t fpid, wpid;
3009753e2922SBryan Drewery 	int status, err;
3010753e2922SBryan Drewery 	sigset_t sigmask;
3011753e2922SBryan Drewery 
301296a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
3013753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
3014753e2922SBryan Drewery 	got_usr1 = 0;
3015753e2922SBryan Drewery 
3016753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
3017753e2922SBryan Drewery 	if (fpid == 0) {
301896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
301996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
302096a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_BLOCK, &sigmask, NULL), 0);
3021753e2922SBryan Drewery 
3022753e2922SBryan Drewery 		trace_me();
302396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 0);
3024753e2922SBryan Drewery 
3025753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
302696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &sigmask, NULL), 0);
3027753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
3028753e2922SBryan Drewery 		do {
3029753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
3030753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
3031753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
3032753e2922SBryan Drewery 
303396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(got_usr1, 1);
3034753e2922SBryan Drewery 		exit(1);
3035753e2922SBryan Drewery 	}
3036753e2922SBryan Drewery 
3037753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
3038753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
303996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3040753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
304196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3042753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
304396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGSTOP);
3044753e2922SBryan Drewery 
3045753e2922SBryan Drewery 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
304696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
3047753e2922SBryan Drewery 
3048753e2922SBryan Drewery 	/* The next wait() should report the SIGUSR1 was received. */
3049753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
305096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3051753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
305296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR1);
3053753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
305496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGUSR1);
3055753e2922SBryan Drewery 
3056753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
305796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3058753e2922SBryan Drewery 
3059753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
3060753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
306196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3062753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
306396a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3064753e2922SBryan Drewery 
3065753e2922SBryan Drewery 	wpid = wait(&status);
306696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
306796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3068753e2922SBryan Drewery }
3069753e2922SBryan Drewery 
3070753e2922SBryan Drewery /*
307182a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
307282a4538fSEric Badger  * a different signal that the new signal is routed to a thread
307399144520SEitan Adler  * that can accept it, and that the thread is awakened by the signal
307482a4538fSEric Badger  * in a timely manner.
307582a4538fSEric Badger  */
307682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask,tc)307782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
307882a4538fSEric Badger {
307982a4538fSEric Badger 	pid_t fpid, wpid;
308082a4538fSEric Badger 	int status, err;
308182a4538fSEric Badger 	pthread_t t;
308282a4538fSEric Badger 	sigset_t sigmask;
308382a4538fSEric Badger 	pthread_barrier_t barrier;
308482a4538fSEric Badger 
308596a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrier_init(&barrier, NULL, 2), 0);
308696a9e50eSAlex Richardson 	REQUIRE_EQ(sem_init(&sigusr1_sem, 0, 0), 0);
308782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
308882a4538fSEric Badger 
308982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
309082a4538fSEric Badger 	if (fpid == 0) {
309196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_create(&t, NULL, signal_thread,
309296a9e50eSAlex Richardson 		    (void *)&barrier), 0);
309382a4538fSEric Badger 
309482a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
309596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigemptyset(&sigmask), 0);
309696a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(sigaddset(&sigmask, SIGUSR1), 0);
309796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_BLOCK, &sigmask, NULL), 0);
309882a4538fSEric Badger 
309982a4538fSEric Badger 		trace_me();
310082a4538fSEric Badger 
310182a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
310282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
310382a4538fSEric Badger 
310482a4538fSEric Badger 		/*
310582a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
310682a4538fSEric Badger 		 * thread.
310782a4538fSEric Badger 		 */
310896a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL),
310996a9e50eSAlex Richardson 		    0);
311082a4538fSEric Badger 
311182a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
311282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
311382a4538fSEric Badger 
311482a4538fSEric Badger 		/*
311582a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
311682a4538fSEric Badger 		 * now.
311782a4538fSEric Badger 		 */
311882a4538fSEric Badger 		raise(SIGSTOP);
311982a4538fSEric Badger 
312082a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
312182a4538fSEric Badger 		do {
312282a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
312382a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
312482a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
312582a4538fSEric Badger 
312682a4538fSEric Badger 		/* Free the other thread from the barrier. */
312782a4538fSEric Badger 		pthread_barrier_wait(&barrier);
312882a4538fSEric Badger 
312996a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(pthread_join(t, NULL), 0);
313082a4538fSEric Badger 
313182a4538fSEric Badger 		exit(1);
313282a4538fSEric Badger 	}
313382a4538fSEric Badger 
313482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
313582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
313696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
313782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
313896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
313982a4538fSEric Badger 
314082a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
314196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
314282a4538fSEric Badger 
314382a4538fSEric Badger 	/*
314482a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
314582a4538fSEric Badger 	 * in this case).
314682a4538fSEric Badger 	 */
314796a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
314882a4538fSEric Badger 
314982a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
315082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
315196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
315282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
315396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
315482a4538fSEric Badger 
315582a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
315696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
315782a4538fSEric Badger 
315882a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
315982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
316096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
316182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
316296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
316382a4538fSEric Badger 
316482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
316596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
316682a4538fSEric Badger 
316796a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGUSR2), 0);
316882a4538fSEric Badger 
316982a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
317082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
317196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
317282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
317396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGUSR2);
317482a4538fSEric Badger 
317582a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
317696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1), 0);
317782a4538fSEric Badger 
317882a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
317982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
318096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
318182a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
318296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
318382a4538fSEric Badger 
318482a4538fSEric Badger 	wpid = wait(&status);
318596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
318696a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
318782a4538fSEric Badger }
318882a4538fSEric Badger 
3189548a2ec4SAndrew Turner /*
3190548a2ec4SAndrew Turner  * Verify that PT_GETREGSET returns registers and PT_SETREGSET updates them.
3191548a2ec4SAndrew Turner  */
3192548a2ec4SAndrew Turner ATF_TC_WITHOUT_HEAD(ptrace__PT_REGSET);
ATF_TC_BODY(ptrace__PT_REGSET,tc)3193548a2ec4SAndrew Turner ATF_TC_BODY(ptrace__PT_REGSET, tc)
3194548a2ec4SAndrew Turner {
31956713be31SAndrew Turner #if defined(__aarch64__)
31966713be31SAndrew Turner 	struct arm64_addr_mask addr_mask;
31976713be31SAndrew Turner #endif
3198548a2ec4SAndrew Turner 	struct prstatus prstatus;
3199548a2ec4SAndrew Turner 	struct iovec vec;
3200548a2ec4SAndrew Turner 	pid_t child, wpid;
3201548a2ec4SAndrew Turner 	int status;
3202548a2ec4SAndrew Turner 
3203548a2ec4SAndrew Turner 	ATF_REQUIRE((child = fork()) != -1);
3204548a2ec4SAndrew Turner 	if (child == 0) {
3205548a2ec4SAndrew Turner 		trace_me();
3206548a2ec4SAndrew Turner 		exit(1);
3207548a2ec4SAndrew Turner 	}
3208548a2ec4SAndrew Turner 
3209548a2ec4SAndrew Turner 	/* The first wait() should report the stop from SIGSTOP. */
3210548a2ec4SAndrew Turner 	wpid = waitpid(child, &status, 0);
3211548a2ec4SAndrew Turner 	REQUIRE_EQ(wpid, child);
3212548a2ec4SAndrew Turner 	ATF_REQUIRE(WIFSTOPPED(status));
3213548a2ec4SAndrew Turner 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3214548a2ec4SAndrew Turner 
3215548a2ec4SAndrew Turner 	/* Check the size is returned when vec.iov_base is NULL */
3216548a2ec4SAndrew Turner 	vec.iov_base = NULL;
3217548a2ec4SAndrew Turner 	vec.iov_len = 0;
3218548a2ec4SAndrew Turner 	ATF_REQUIRE(ptrace(PT_GETREGSET, wpid, (caddr_t)&vec, NT_PRSTATUS) !=
3219548a2ec4SAndrew Turner 	    -1);
3220548a2ec4SAndrew Turner 	ATF_REQUIRE(vec.iov_len == sizeof(prstatus));
3221548a2ec4SAndrew Turner 	ATF_REQUIRE(vec.iov_base == NULL);
3222548a2ec4SAndrew Turner 
3223548a2ec4SAndrew Turner 	/* Read the registers. */
3224548a2ec4SAndrew Turner 	memset(&prstatus, 0, sizeof(prstatus));
3225548a2ec4SAndrew Turner 	vec.iov_base = &prstatus;
3226548a2ec4SAndrew Turner 	ATF_REQUIRE(ptrace(PT_GETREGSET, wpid, (caddr_t)&vec, NT_PRSTATUS) !=
3227548a2ec4SAndrew Turner 	    -1);
3228548a2ec4SAndrew Turner 	ATF_REQUIRE(vec.iov_len == sizeof(prstatus));
3229548a2ec4SAndrew Turner 	ATF_REQUIRE(vec.iov_base == &prstatus);
3230548a2ec4SAndrew Turner 	ATF_REQUIRE(prstatus.pr_statussz == sizeof(prstatus));
3231548a2ec4SAndrew Turner 
3232548a2ec4SAndrew Turner 	/* Write the registers back. */
3233548a2ec4SAndrew Turner 	ATF_REQUIRE(ptrace(PT_SETREGSET, wpid, (caddr_t)&vec, NT_PRSTATUS) !=
3234548a2ec4SAndrew Turner 	    -1);
3235548a2ec4SAndrew Turner 
32366713be31SAndrew Turner #if defined(__aarch64__)
32376713be31SAndrew Turner 	vec.iov_base = &addr_mask;
32386713be31SAndrew Turner 	vec.iov_len = sizeof(addr_mask);
32396713be31SAndrew Turner 	ATF_REQUIRE(ptrace(PT_GETREGSET, wpid, (caddr_t)&vec,
32406713be31SAndrew Turner 	    NT_ARM_ADDR_MASK) != -1);
32416713be31SAndrew Turner 	REQUIRE_EQ(addr_mask.code, addr_mask.data);
32426713be31SAndrew Turner 	ATF_REQUIRE(addr_mask.code == 0 ||
32436713be31SAndrew Turner 	    addr_mask.code == 0xff7f000000000000UL);
32446713be31SAndrew Turner #endif
32456713be31SAndrew Turner 
3246548a2ec4SAndrew Turner 	REQUIRE_EQ(ptrace(PT_CONTINUE, child, (caddr_t)1, 0), 0);
3247548a2ec4SAndrew Turner 
3248548a2ec4SAndrew Turner 	/* The second wait() should report the exit status. */
3249548a2ec4SAndrew Turner 	wpid = waitpid(child, &status, 0);
3250548a2ec4SAndrew Turner 	REQUIRE_EQ(wpid, child);
3251548a2ec4SAndrew Turner 	ATF_REQUIRE(WIFEXITED(status));
3252548a2ec4SAndrew Turner 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3253548a2ec4SAndrew Turner 
3254548a2ec4SAndrew Turner 	/* The child should no longer exist. */
3255548a2ec4SAndrew Turner 	wpid = waitpid(child, &status, 0);
3256548a2ec4SAndrew Turner 	REQUIRE_EQ(wpid, -1);
3257548a2ec4SAndrew Turner 	REQUIRE_EQ(errno, ECHILD);
3258548a2ec4SAndrew Turner }
3259548a2ec4SAndrew Turner 
3260b38bd91fSEric Badger static void *
raise_sigstop_thread(void * arg __unused)3261b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
3262b38bd91fSEric Badger {
3263b38bd91fSEric Badger 
3264b38bd91fSEric Badger 	raise(SIGSTOP);
3265b38bd91fSEric Badger 	return NULL;
3266b38bd91fSEric Badger }
3267b38bd91fSEric Badger 
3268b38bd91fSEric Badger static void *
sleep_thread(void * arg __unused)3269b38bd91fSEric Badger sleep_thread(void *arg __unused)
3270b38bd91fSEric Badger {
3271b38bd91fSEric Badger 
3272b38bd91fSEric Badger 	sleep(60);
3273b38bd91fSEric Badger 	return NULL;
3274b38bd91fSEric Badger }
3275b38bd91fSEric Badger 
3276b38bd91fSEric Badger static void
terminate_with_pending_sigstop(bool sigstop_from_main_thread)3277b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
3278b38bd91fSEric Badger {
3279b38bd91fSEric Badger 	pid_t fpid, wpid;
3280b38bd91fSEric Badger 	int status, i;
3281b38bd91fSEric Badger 	cpuset_t setmask;
3282b38bd91fSEric Badger 	cpusetid_t setid;
3283b38bd91fSEric Badger 	pthread_t t;
3284b38bd91fSEric Badger 
3285b38bd91fSEric Badger 	/*
3286b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
3287b38bd91fSEric Badger 	 * that both child and grandchild have died.
3288b38bd91fSEric Badger 	 */
328996a9e50eSAlex Richardson 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
3290b38bd91fSEric Badger 
3291b38bd91fSEric Badger 	fpid = fork();
3292b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
3293b38bd91fSEric Badger 	if (fpid == 0) {
3294b38bd91fSEric Badger 		fpid = fork();
3295b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
3296b38bd91fSEric Badger 		if (fpid == 0) {
3297b38bd91fSEric Badger 			trace_me();
3298b38bd91fSEric Badger 
3299b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
3300b38bd91fSEric Badger 			CPU_ZERO(&setmask);
3301b38bd91fSEric Badger 			CPU_SET(0, &setmask);
330296a9e50eSAlex Richardson 			CHILD_REQUIRE_EQ(cpuset(&setid), 0);
3303b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
3304b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
3305b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
3306b38bd91fSEric Badger 
3307b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
3308b38bd91fSEric Badger 				/*
3309b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
3310b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
3311b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
3312b38bd91fSEric Badger 				 * threads compete.
3313b38bd91fSEric Badger 				 */
3314b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3315b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
3316b38bd91fSEric Badger 				raise(SIGSTOP);
3317b38bd91fSEric Badger 			} else {
3318b38bd91fSEric Badger 				/*
3319b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
3320b38bd91fSEric Badger 				 * this thread. After creating the new thread,
3321b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
3322b38bd91fSEric Badger 				 * raise the SIGSTOP.
3323b38bd91fSEric Badger 				 */
3324b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3325b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
3326b38bd91fSEric Badger 				sleep(60);
3327b38bd91fSEric Badger 			}
3328b38bd91fSEric Badger 
3329b38bd91fSEric Badger 			exit(0);
3330b38bd91fSEric Badger 		}
3331b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
3332b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
333396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, fpid);
3334b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
333596a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3336b38bd91fSEric Badger 
333796a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3338b38bd91fSEric Badger 
3339b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
3340b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
334196a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(wpid, fpid);
3342b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
334396a9e50eSAlex Richardson 		CHILD_REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3344b38bd91fSEric Badger 
3345b38bd91fSEric Badger 		/*
3346b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
3347b38bd91fSEric Badger 		 * should be killed.
3348b38bd91fSEric Badger 		 */
3349b38bd91fSEric Badger 		exit(0);
3350b38bd91fSEric Badger 	}
3351b38bd91fSEric Badger 
3352b38bd91fSEric Badger 	/*
3353b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
3354b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
3355b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
3356b38bd91fSEric Badger 	 * left dangling when its parent died.
3357b38bd91fSEric Badger 	 */
3358b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
3359b38bd91fSEric Badger 		wpid = wait(&status);
336096a9e50eSAlex Richardson 		if (wpid == fpid) {
336196a9e50eSAlex Richardson 			ATF_REQUIRE(WIFEXITED(status));
336296a9e50eSAlex Richardson 			REQUIRE_EQ(WEXITSTATUS(status), 0);
336396a9e50eSAlex Richardson 		} else {
336496a9e50eSAlex Richardson 			ATF_REQUIRE(WIFSIGNALED(status));
336596a9e50eSAlex Richardson 			REQUIRE_EQ(WTERMSIG(status), SIGKILL);
336696a9e50eSAlex Richardson 		}
3367b38bd91fSEric Badger 	}
3368b38bd91fSEric Badger }
3369b38bd91fSEric Badger 
3370b38bd91fSEric Badger /*
3371b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
3372b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
3373b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
3374b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
3375b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
3376b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
3377b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
3378b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
3379b38bd91fSEric Badger  * past, so make no assumption.
3380b38bd91fSEric Badger  */
33813cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1,tc)33823cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
33833cf56bb4SEnji Cooper {
33843cf56bb4SEnji Cooper 
33853cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33863cf56bb4SEnji Cooper }
ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1,tc)3387b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
3388b38bd91fSEric Badger {
3389b38bd91fSEric Badger 
3390b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
3391b38bd91fSEric Badger }
33923cf56bb4SEnji Cooper 
33933cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2,tc)33943cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
33953cf56bb4SEnji Cooper {
33963cf56bb4SEnji Cooper 
33973cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
33983cf56bb4SEnji Cooper }
ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2,tc)3399b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
3400b38bd91fSEric Badger {
3401b38bd91fSEric Badger 
3402b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
3403b38bd91fSEric Badger }
3404b38bd91fSEric Badger 
3405b4d33259SEric Badger /*
3406b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
3407b4d33259SEric Badger  * is not modified.
3408b4d33259SEric Badger  */
3409b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
ATF_TC_BODY(ptrace__event_mask_sigkill_discard,tc)3410b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
3411b4d33259SEric Badger {
3412b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
3413b4d33259SEric Badger 	pid_t fpid, wpid;
3414b4d33259SEric Badger 	int status, event_mask, new_event_mask;
3415b4d33259SEric Badger 
3416b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
3417b4d33259SEric Badger 	if (fpid == 0) {
3418b4d33259SEric Badger 		trace_me();
3419b4d33259SEric Badger 		raise(SIGSTOP);
3420b4d33259SEric Badger 		exit(0);
3421b4d33259SEric Badger 	}
3422b4d33259SEric Badger 
3423b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
3424b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
342596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3426b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
342796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3428b4d33259SEric Badger 
3429b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
3430b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
3431b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
3432b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
3433b4d33259SEric Badger 
3434b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
343596a9e50eSAlex Richardson 	REQUIRE_EQ(kill(fpid, SIGKILL), 0);
3436b4d33259SEric Badger 
3437b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
343896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3439b4d33259SEric Badger 
3440b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
3441b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
344296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3443b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
344496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGKILL);
3445b4d33259SEric Badger 
3446b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3447b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
344896a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGKILL);
3449b4d33259SEric Badger 
3450b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
345196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3452b4d33259SEric Badger 
3453b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
3454b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
345596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3456b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
345796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3458b4d33259SEric Badger 
3459b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
3460b4d33259SEric Badger 	new_event_mask = 0;
3461b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
3462b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
346396a9e50eSAlex Richardson 	REQUIRE_EQ(event_mask, new_event_mask);
3464b4d33259SEric Badger 
3465b4d33259SEric Badger 	/* Continue the child to let it exit. */
346696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3467b4d33259SEric Badger 
3468b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
3469b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3470b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
347196a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
3472b4d33259SEric Badger 
3473b4d33259SEric Badger 	wpid = wait(&status);
347496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
347596a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3476b4d33259SEric Badger }
3477b4d33259SEric Badger 
3478d74da94cSMark Johnston static void *
flock_thread(void * arg)3479d74da94cSMark Johnston flock_thread(void *arg)
3480d74da94cSMark Johnston {
3481d74da94cSMark Johnston 	int fd;
3482d74da94cSMark Johnston 
3483d74da94cSMark Johnston 	fd = *(int *)arg;
3484d74da94cSMark Johnston 	(void)flock(fd, LOCK_EX);
3485d74da94cSMark Johnston 	(void)flock(fd, LOCK_UN);
3486d74da94cSMark Johnston 	return (NULL);
3487d74da94cSMark Johnston }
3488d74da94cSMark Johnston 
3489d74da94cSMark Johnston /*
3490d74da94cSMark Johnston  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
3491d74da94cSMark Johnston  * We rely on the fact that the lockf implementation sets SBDRY before blocking
3492d74da94cSMark Johnston  * on a lock. This is a regression test for r318191.
3493d74da94cSMark Johnston  */
3494d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread,tc)3495d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
3496d74da94cSMark Johnston {
3497d74da94cSMark Johnston 	pthread_barrier_t barrier;
3498d74da94cSMark Johnston 	pthread_barrierattr_t battr;
3499d74da94cSMark Johnston 	char tmpfile[64];
3500d74da94cSMark Johnston 	pid_t child, wpid;
3501d74da94cSMark Johnston 	int error, fd, i, status;
3502d74da94cSMark Johnston 
350396a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrierattr_init(&battr), 0);
3504d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
3505d74da94cSMark Johnston 	    PTHREAD_PROCESS_SHARED) == 0);
350696a9e50eSAlex Richardson 	REQUIRE_EQ(pthread_barrier_init(&barrier, &battr, 2), 0);
3507d74da94cSMark Johnston 
3508d74da94cSMark Johnston 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
3509d74da94cSMark Johnston 	fd = mkstemp(tmpfile);
3510d74da94cSMark Johnston 	ATF_REQUIRE(fd >= 0);
3511d74da94cSMark Johnston 
3512d74da94cSMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
3513d74da94cSMark Johnston 	if (child == 0) {
3514d74da94cSMark Johnston 		pthread_t t[2];
351596437391SBryan Drewery 		int cfd;
3516d74da94cSMark Johnston 
3517d74da94cSMark Johnston 		error = pthread_barrier_wait(&barrier);
3518d74da94cSMark Johnston 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
3519d74da94cSMark Johnston 			_exit(1);
3520d74da94cSMark Johnston 
3521d74da94cSMark Johnston 		cfd = open(tmpfile, O_RDONLY);
3522d74da94cSMark Johnston 		if (cfd < 0)
3523d74da94cSMark Johnston 			_exit(1);
3524d74da94cSMark Johnston 
3525d74da94cSMark Johnston 		/*
3526d74da94cSMark Johnston 		 * We want at least two threads blocked on the file lock since
3527d74da94cSMark Johnston 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
3528d74da94cSMark Johnston 		 * sleep.
3529d74da94cSMark Johnston 		 */
3530d74da94cSMark Johnston 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
3531d74da94cSMark Johnston 			_exit(1);
3532d74da94cSMark Johnston 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
3533d74da94cSMark Johnston 			_exit(1);
3534d74da94cSMark Johnston 		if (pthread_join(t[0], NULL) != 0)
3535d74da94cSMark Johnston 			_exit(1);
3536d74da94cSMark Johnston 		if (pthread_join(t[1], NULL) != 0)
3537d74da94cSMark Johnston 			_exit(1);
3538d74da94cSMark Johnston 		_exit(0);
3539d74da94cSMark Johnston 	}
3540d74da94cSMark Johnston 
354196a9e50eSAlex Richardson 	REQUIRE_EQ(flock(fd, LOCK_EX), 0);
3542d74da94cSMark Johnston 
3543d74da94cSMark Johnston 	error = pthread_barrier_wait(&barrier);
3544d74da94cSMark Johnston 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
3545d74da94cSMark Johnston 
3546d74da94cSMark Johnston 	/*
3547d74da94cSMark Johnston 	 * Give the child some time to block. Is there a better way to do this?
3548d74da94cSMark Johnston 	 */
3549d74da94cSMark Johnston 	sleep(1);
3550d74da94cSMark Johnston 
3551d74da94cSMark Johnston 	/*
3552d74da94cSMark Johnston 	 * Attach and give the child 3 seconds to stop.
3553d74da94cSMark Johnston 	 */
355496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_ATTACH, child, NULL, 0), 0);
3555d74da94cSMark Johnston 	for (i = 0; i < 3; i++) {
3556d74da94cSMark Johnston 		wpid = waitpid(child, &status, WNOHANG);
3557d74da94cSMark Johnston 		if (wpid == child && WIFSTOPPED(status) &&
3558d74da94cSMark Johnston 		    WSTOPSIG(status) == SIGSTOP)
3559d74da94cSMark Johnston 			break;
3560d74da94cSMark Johnston 		sleep(1);
3561d74da94cSMark Johnston 	}
3562d74da94cSMark Johnston 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
3563d74da94cSMark Johnston 
356496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_DETACH, child, NULL, 0), 0);
3565d74da94cSMark Johnston 
356696a9e50eSAlex Richardson 	REQUIRE_EQ(flock(fd, LOCK_UN), 0);
356796a9e50eSAlex Richardson 	REQUIRE_EQ(unlink(tmpfile), 0);
356896a9e50eSAlex Richardson 	REQUIRE_EQ(close(fd), 0);
3569d74da94cSMark Johnston }
3570d74da94cSMark Johnston 
357154cfb29eSJohn Baldwin static void
sigusr1_step_handler(int sig)357254cfb29eSJohn Baldwin sigusr1_step_handler(int sig)
357354cfb29eSJohn Baldwin {
357454cfb29eSJohn Baldwin 
357596a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(sig, SIGUSR1);
357654cfb29eSJohn Baldwin 	raise(SIGABRT);
357754cfb29eSJohn Baldwin }
357854cfb29eSJohn Baldwin 
357954cfb29eSJohn Baldwin /*
358054cfb29eSJohn Baldwin  * Verify that PT_STEP with a signal invokes the signal before
358154cfb29eSJohn Baldwin  * stepping the next instruction (and that the next instruction is
358254cfb29eSJohn Baldwin  * stepped correctly).
358354cfb29eSJohn Baldwin  */
358454cfb29eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal);
ATF_TC_BODY(ptrace__PT_STEP_with_signal,tc)358554cfb29eSJohn Baldwin ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
358654cfb29eSJohn Baldwin {
358754cfb29eSJohn Baldwin 	struct ptrace_lwpinfo pl;
358854cfb29eSJohn Baldwin 	pid_t fpid, wpid;
358954cfb29eSJohn Baldwin 	int status;
359054cfb29eSJohn Baldwin 
359154cfb29eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
359254cfb29eSJohn Baldwin 	if (fpid == 0) {
359354cfb29eSJohn Baldwin 		trace_me();
359454cfb29eSJohn Baldwin 		signal(SIGUSR1, sigusr1_step_handler);
359554cfb29eSJohn Baldwin 		raise(SIGABRT);
359654cfb29eSJohn Baldwin 		exit(1);
359754cfb29eSJohn Baldwin 	}
359854cfb29eSJohn Baldwin 
359954cfb29eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
360054cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
360196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
360254cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
360396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
360454cfb29eSJohn Baldwin 
360596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
360654cfb29eSJohn Baldwin 
360754cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
360854cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
360996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
361054cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
361196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
361254cfb29eSJohn Baldwin 
361354cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
361454cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
361596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
361654cfb29eSJohn Baldwin 
361754cfb29eSJohn Baldwin 	/* Step the child process inserting SIGUSR1. */
361896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1), 0);
361954cfb29eSJohn Baldwin 
362054cfb29eSJohn Baldwin 	/* The next stop should report the SIGABRT in the signal handler. */
362154cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
362296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
362354cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
362496a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
362554cfb29eSJohn Baldwin 
362654cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
362754cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
362896a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
362954cfb29eSJohn Baldwin 
363054cfb29eSJohn Baldwin 	/* Continue the child process discarding the signal. */
363196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
363254cfb29eSJohn Baldwin 
363354cfb29eSJohn Baldwin 	/* The next stop should report a trace trap from PT_STEP. */
363454cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
363596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
363654cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
363796a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
363854cfb29eSJohn Baldwin 
363954cfb29eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
364054cfb29eSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
364196a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
364296a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_TRACE);
364354cfb29eSJohn Baldwin 
364454cfb29eSJohn Baldwin 	/* Continue the child to let it exit. */
364596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
364654cfb29eSJohn Baldwin 
364754cfb29eSJohn Baldwin 	/* The last event should be for the child process's exit. */
364854cfb29eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
364954cfb29eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
365096a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
365154cfb29eSJohn Baldwin 
365254cfb29eSJohn Baldwin 	wpid = wait(&status);
365396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
365496a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
365554cfb29eSJohn Baldwin }
365654cfb29eSJohn Baldwin 
3657643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
3658643ce7deSJohn Baldwin /*
3659643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported
3660643ce7deSJohn Baldwin  * for a breakpoint trap.
3661643ce7deSJohn Baldwin  */
3662643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo);
ATF_TC_BODY(ptrace__breakpoint_siginfo,tc)3663643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__breakpoint_siginfo, tc)
3664643ce7deSJohn Baldwin {
3665643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3666643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3667643ce7deSJohn Baldwin 	int status;
3668643ce7deSJohn Baldwin 
3669643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3670643ce7deSJohn Baldwin 	if (fpid == 0) {
3671643ce7deSJohn Baldwin 		trace_me();
3672643ce7deSJohn Baldwin 		breakpoint();
3673643ce7deSJohn Baldwin 		exit(1);
3674643ce7deSJohn Baldwin 	}
3675643ce7deSJohn Baldwin 
3676643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3677643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
367896a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3679643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
368096a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3681643ce7deSJohn Baldwin 
3682643ce7deSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
368396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3684643ce7deSJohn Baldwin 
3685643ce7deSJohn Baldwin 	/* The second wait() should report hitting the breakpoint. */
3686643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
368796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3688643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
368996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3690643ce7deSJohn Baldwin 
3691643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3692643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
369396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
369496a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3695643ce7deSJohn Baldwin 
3696643ce7deSJohn Baldwin 	/* Kill the child process. */
369796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_KILL, fpid, 0, 0), 0);
3698643ce7deSJohn Baldwin 
3699643ce7deSJohn Baldwin 	/* The last wait() should report the SIGKILL. */
3700643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
370196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3702643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSIGNALED(status));
370396a9e50eSAlex Richardson 	REQUIRE_EQ(WTERMSIG(status), SIGKILL);
3704643ce7deSJohn Baldwin 
3705643ce7deSJohn Baldwin 	wpid = wait(&status);
370696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
370796a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3708643ce7deSJohn Baldwin }
3709643ce7deSJohn Baldwin #endif /* HAVE_BREAKPOINT */
3710643ce7deSJohn Baldwin 
3711643ce7deSJohn Baldwin /*
3712643ce7deSJohn Baldwin  * Verify that a SIGTRAP event with the TRAP_TRACE code is reported
3713643ce7deSJohn Baldwin  * for a single-step trap from PT_STEP.
3714643ce7deSJohn Baldwin  */
3715643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo);
ATF_TC_BODY(ptrace__step_siginfo,tc)3716643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__step_siginfo, tc)
3717643ce7deSJohn Baldwin {
3718643ce7deSJohn Baldwin 	struct ptrace_lwpinfo pl;
3719643ce7deSJohn Baldwin 	pid_t fpid, wpid;
3720643ce7deSJohn Baldwin 	int status;
3721643ce7deSJohn Baldwin 
3722643ce7deSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3723643ce7deSJohn Baldwin 	if (fpid == 0) {
3724643ce7deSJohn Baldwin 		trace_me();
3725643ce7deSJohn Baldwin 		exit(1);
3726643ce7deSJohn Baldwin 	}
3727643ce7deSJohn Baldwin 
3728643ce7deSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3729643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
373096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3731643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
373296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3733643ce7deSJohn Baldwin 
3734643ce7deSJohn Baldwin 	/* Step the child ignoring the SIGSTOP. */
373596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, 0), 0);
3736643ce7deSJohn Baldwin 
3737643ce7deSJohn Baldwin 	/* The second wait() should report a single-step trap. */
3738643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
373996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3740643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
374196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3742643ce7deSJohn Baldwin 
3743643ce7deSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3744643ce7deSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
374596a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
374696a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_TRACE);
3747643ce7deSJohn Baldwin 
3748643ce7deSJohn Baldwin 	/* Continue the child process. */
374996a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3750643ce7deSJohn Baldwin 
3751643ce7deSJohn Baldwin 	/* The last event should be for the child process's exit. */
3752643ce7deSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3753643ce7deSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
375496a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3755643ce7deSJohn Baldwin 
3756643ce7deSJohn Baldwin 	wpid = wait(&status);
375796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
375896a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3759643ce7deSJohn Baldwin }
3760643ce7deSJohn Baldwin 
3761403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
3762e012fe34SJohn Baldwin static void *
continue_thread(void * arg __unused)3763e0a40f30SJohn Baldwin continue_thread(void *arg __unused)
3764e012fe34SJohn Baldwin {
3765e012fe34SJohn Baldwin 	breakpoint();
3766e012fe34SJohn Baldwin 	return (NULL);
3767e012fe34SJohn Baldwin }
3768e012fe34SJohn Baldwin 
3769e012fe34SJohn Baldwin static __dead2 void
continue_thread_main(void)3770e012fe34SJohn Baldwin continue_thread_main(void)
3771e012fe34SJohn Baldwin {
3772e012fe34SJohn Baldwin 	pthread_t threads[2];
3773e012fe34SJohn Baldwin 
3774e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
3775e012fe34SJohn Baldwin 	    NULL) == 0);
3776e012fe34SJohn Baldwin 	CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
3777e012fe34SJohn Baldwin 	    NULL) == 0);
377896a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(threads[0], NULL), 0);
377996a9e50eSAlex Richardson 	CHILD_REQUIRE_EQ(pthread_join(threads[1], NULL), 0);
3780e012fe34SJohn Baldwin 	exit(1);
3781e012fe34SJohn Baldwin }
3782e012fe34SJohn Baldwin 
3783e012fe34SJohn Baldwin /*
3784e012fe34SJohn Baldwin  * Ensure that PT_CONTINUE clears the status of the thread that
3785e012fe34SJohn Baldwin  * triggered the stop even if a different thread's LWP was passed to
3786e012fe34SJohn Baldwin  * PT_CONTINUE.
3787e012fe34SJohn Baldwin  */
3788e012fe34SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread,tc)3789e012fe34SJohn Baldwin ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
3790e012fe34SJohn Baldwin {
3791e012fe34SJohn Baldwin 	struct ptrace_lwpinfo pl;
3792e012fe34SJohn Baldwin 	pid_t fpid, wpid;
3793e012fe34SJohn Baldwin 	lwpid_t lwps[2];
3794e012fe34SJohn Baldwin 	bool hit_break[2];
3795403e331dSJohn Baldwin 	struct reg reg;
3796e012fe34SJohn Baldwin 	int i, j, status;
3797e012fe34SJohn Baldwin 
3798e012fe34SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3799e012fe34SJohn Baldwin 	if (fpid == 0) {
3800e012fe34SJohn Baldwin 		trace_me();
3801e012fe34SJohn Baldwin 		continue_thread_main();
3802e012fe34SJohn Baldwin 	}
3803e012fe34SJohn Baldwin 
3804e012fe34SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3805e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
380696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3807e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
380896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3809e012fe34SJohn Baldwin 
3810e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3811e012fe34SJohn Baldwin 	    sizeof(pl)) != -1);
3812e012fe34SJohn Baldwin 
381396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_LWP_EVENTS, wpid, NULL, 1), 0);
3814e012fe34SJohn Baldwin 
3815e012fe34SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
381696a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3817e012fe34SJohn Baldwin 
3818e012fe34SJohn Baldwin 	/* One of the new threads should report it's birth. */
3819e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
382096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3821e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
382296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3823e012fe34SJohn Baldwin 
3824e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
382596a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
3826e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3827e012fe34SJohn Baldwin 	lwps[0] = pl.pl_lwpid;
3828e012fe34SJohn Baldwin 
3829e012fe34SJohn Baldwin 	/*
3830e012fe34SJohn Baldwin 	 * Suspend this thread to ensure both threads are alive before
3831e012fe34SJohn Baldwin 	 * hitting the breakpoint.
3832e012fe34SJohn Baldwin 	 */
3833e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
3834e012fe34SJohn Baldwin 
383596a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3836e012fe34SJohn Baldwin 
3837e012fe34SJohn Baldwin 	/* Second thread should report it's birth. */
3838e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
383996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3840e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
384196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3842e012fe34SJohn Baldwin 
3843e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
384496a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)),
3845e012fe34SJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
3846e012fe34SJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
3847e012fe34SJohn Baldwin 	lwps[1] = pl.pl_lwpid;
3848e012fe34SJohn Baldwin 
3849e012fe34SJohn Baldwin 	/* Resume both threads waiting for breakpoint events. */
3850e012fe34SJohn Baldwin 	hit_break[0] = hit_break[1] = false;
3851e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
385296a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3853e012fe34SJohn Baldwin 
3854e012fe34SJohn Baldwin 	/* One thread should report a breakpoint. */
3855e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
385696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3857e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
385896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3859e012fe34SJohn Baldwin 
3860e012fe34SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3861e012fe34SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
386296a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
386396a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3864e012fe34SJohn Baldwin 	if (pl.pl_lwpid == lwps[0])
3865e012fe34SJohn Baldwin 		i = 0;
3866e012fe34SJohn Baldwin 	else
3867e012fe34SJohn Baldwin 		i = 1;
3868e012fe34SJohn Baldwin 	hit_break[i] = true;
3869403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3870403e331dSJohn Baldwin 	SKIP_BREAK(&reg);
3871403e331dSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
3872e012fe34SJohn Baldwin 
3873e012fe34SJohn Baldwin 	/*
3874e012fe34SJohn Baldwin 	 * Resume both threads but pass the other thread's LWPID to
3875e012fe34SJohn Baldwin 	 * PT_CONTINUE.
3876e012fe34SJohn Baldwin 	 */
387796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0), 0);
3878e012fe34SJohn Baldwin 
3879e012fe34SJohn Baldwin 	/*
3880e012fe34SJohn Baldwin 	 * Will now get two thread exit events and one more breakpoint
3881e012fe34SJohn Baldwin 	 * event.
3882e012fe34SJohn Baldwin 	 */
3883e012fe34SJohn Baldwin 	for (j = 0; j < 3; j++) {
3884e012fe34SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
388596a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, fpid);
3886e012fe34SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
388796a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3888e012fe34SJohn Baldwin 
3889e012fe34SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
3890e012fe34SJohn Baldwin 		    sizeof(pl)) != -1);
3891e012fe34SJohn Baldwin 
3892e012fe34SJohn Baldwin 		if (pl.pl_lwpid == lwps[0])
3893e012fe34SJohn Baldwin 			i = 0;
3894e012fe34SJohn Baldwin 		else
3895e012fe34SJohn Baldwin 			i = 1;
3896e012fe34SJohn Baldwin 
3897e012fe34SJohn Baldwin 		ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
3898e012fe34SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_EXITED) {
3899e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(hit_break[i],
3900e012fe34SJohn Baldwin 			    "exited thread did not report breakpoint");
3901e012fe34SJohn Baldwin 			lwps[i] = 0;
3902e012fe34SJohn Baldwin 		} else {
3903e012fe34SJohn Baldwin 			ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
390496a9e50eSAlex Richardson 			REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGTRAP);
390596a9e50eSAlex Richardson 			REQUIRE_EQ(pl.pl_siginfo.si_code, TRAP_BRKPT);
3906e012fe34SJohn Baldwin 			ATF_REQUIRE_MSG(!hit_break[i],
3907e012fe34SJohn Baldwin 			    "double breakpoint event");
3908e012fe34SJohn Baldwin 			hit_break[i] = true;
3909403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
3910403e331dSJohn Baldwin 			    0) != -1);
3911403e331dSJohn Baldwin 			SKIP_BREAK(&reg);
3912403e331dSJohn Baldwin 			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
3913403e331dSJohn Baldwin 			    0) != -1);
3914e012fe34SJohn Baldwin 		}
3915e012fe34SJohn Baldwin 
391696a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3917e012fe34SJohn Baldwin 	}
3918e012fe34SJohn Baldwin 
3919e012fe34SJohn Baldwin 	/* Both threads should have exited. */
392096a9e50eSAlex Richardson 	REQUIRE_EQ(lwps[0], 0);
392196a9e50eSAlex Richardson 	REQUIRE_EQ(lwps[1], 0);
3922e012fe34SJohn Baldwin 
3923e012fe34SJohn Baldwin 	/* The last event should be for the child process's exit. */
3924e012fe34SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3925e012fe34SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
392696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
3927e012fe34SJohn Baldwin 
3928e012fe34SJohn Baldwin 	wpid = wait(&status);
392996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
393096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
3931e012fe34SJohn Baldwin }
3932e012fe34SJohn Baldwin #endif
3933e012fe34SJohn Baldwin 
3934c5786670SJohn Baldwin /*
3935c5786670SJohn Baldwin  * Verify that PT_LWPINFO doesn't return stale siginfo.
3936c5786670SJohn Baldwin  */
3937c5786670SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_LWPINFO_stale_siginfo);
ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo,tc)3938c5786670SJohn Baldwin ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo, tc)
3939c5786670SJohn Baldwin {
3940c5786670SJohn Baldwin 	struct ptrace_lwpinfo pl;
3941c5786670SJohn Baldwin 	pid_t fpid, wpid;
3942c5786670SJohn Baldwin 	int events, status;
3943c5786670SJohn Baldwin 
3944c5786670SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
3945c5786670SJohn Baldwin 	if (fpid == 0) {
3946c5786670SJohn Baldwin 		trace_me();
3947c5786670SJohn Baldwin 		raise(SIGABRT);
3948c5786670SJohn Baldwin 		exit(1);
3949c5786670SJohn Baldwin 	}
3950c5786670SJohn Baldwin 
3951c5786670SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
3952c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
395396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3954c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
395596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
3956c5786670SJohn Baldwin 
395796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3958c5786670SJohn Baldwin 
3959c5786670SJohn Baldwin 	/* The next stop should report the SIGABRT in the child body. */
3960c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
396196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3962c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
396396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGABRT);
3964c5786670SJohn Baldwin 
3965c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3966c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
396796a9e50eSAlex Richardson 	REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT);
3968c5786670SJohn Baldwin 
3969c5786670SJohn Baldwin 	/*
3970c5786670SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
3971c5786670SJohn Baldwin 	 * syscall traps.
3972c5786670SJohn Baldwin 	 */
397396a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
3974c5786670SJohn Baldwin 
3975c5786670SJohn Baldwin 	/*
3976c5786670SJohn Baldwin 	 * The next stop should report a system call entry from
3977c5786670SJohn Baldwin 	 * exit().  PL_FLAGS_SI should not be set.
3978c5786670SJohn Baldwin 	 */
3979c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
398096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
3981c5786670SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
398296a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
3983c5786670SJohn Baldwin 
3984c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3985c5786670SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
398696a9e50eSAlex Richardson 	REQUIRE_EQ((pl.pl_flags & PL_FLAG_SI), 0);
3987c5786670SJohn Baldwin 
3988c5786670SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
3989c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
3990c5786670SJohn Baldwin 	    sizeof(events)) == 0);
3991c5786670SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
3992c5786670SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
3993c5786670SJohn Baldwin 	    sizeof(events)) == 0);
399496a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
3995c5786670SJohn Baldwin 
3996c5786670SJohn Baldwin 	/* The last event should be for the child process's exit. */
3997c5786670SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
3998c5786670SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
399996a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
4000c5786670SJohn Baldwin 
4001c5786670SJohn Baldwin 	wpid = wait(&status);
400296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
400396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4004c5786670SJohn Baldwin }
4005c5786670SJohn Baldwin 
4006c8ea8731SJohn Baldwin /*
400732451fb9SJohn Baldwin  * A simple test of PT_GET_SC_ARGS and PT_GET_SC_RET.
4008c8ea8731SJohn Baldwin  */
4009c8ea8731SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__syscall_args);
ATF_TC_BODY(ptrace__syscall_args,tc)4010c8ea8731SJohn Baldwin ATF_TC_BODY(ptrace__syscall_args, tc)
4011c8ea8731SJohn Baldwin {
4012c8ea8731SJohn Baldwin 	struct ptrace_lwpinfo pl;
401332451fb9SJohn Baldwin 	struct ptrace_sc_ret psr;
4014c8ea8731SJohn Baldwin 	pid_t fpid, wpid;
4015c8ea8731SJohn Baldwin 	register_t args[2];
4016c8ea8731SJohn Baldwin 	int events, status;
4017c8ea8731SJohn Baldwin 
4018c8ea8731SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
4019c8ea8731SJohn Baldwin 	if (fpid == 0) {
4020c8ea8731SJohn Baldwin 		trace_me();
4021c8ea8731SJohn Baldwin 		kill(getpid(), 0);
402217cc2009SAlex Richardson 		/* Close a fd that should not exist. */
402317cc2009SAlex Richardson 		close(12345);
4024c8ea8731SJohn Baldwin 		exit(1);
4025c8ea8731SJohn Baldwin 	}
4026c8ea8731SJohn Baldwin 
4027c8ea8731SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
4028c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
402996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
4030c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
403196a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
4032c8ea8731SJohn Baldwin 
4033c8ea8731SJohn Baldwin 	/*
4034c8ea8731SJohn Baldwin 	 * Continue the process ignoring the signal, but enabling
403532451fb9SJohn Baldwin 	 * syscall traps.
4036c8ea8731SJohn Baldwin 	 */
403796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0), 0);
4038c8ea8731SJohn Baldwin 
4039c8ea8731SJohn Baldwin 	/*
4040c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from getpid().
4041c8ea8731SJohn Baldwin 	 */
4042c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
404396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
4044c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
404596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
4046c8ea8731SJohn Baldwin 
4047c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
4048c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
40491fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_getpid);
4050c8ea8731SJohn Baldwin 
405196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
4052c8ea8731SJohn Baldwin 
4053c8ea8731SJohn Baldwin 	/*
405432451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from getpid().
405532451fb9SJohn Baldwin 	 */
405632451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
405796a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
405832451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
405996a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
406032451fb9SJohn Baldwin 
406132451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
406232451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
40631fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_getpid);
406432451fb9SJohn Baldwin 
406532451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
406632451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
406796a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, 0);
406896a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_retval[0], wpid);
406932451fb9SJohn Baldwin 
407096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
407132451fb9SJohn Baldwin 
407232451fb9SJohn Baldwin 	/*
4073c8ea8731SJohn Baldwin 	 * The next stop should be the syscall entry from kill().
4074c8ea8731SJohn Baldwin 	 */
4075c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
407696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
4077c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
407896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
4079c8ea8731SJohn Baldwin 
4080c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
4081c8ea8731SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
40821fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_kill);
40831fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_narg, 2u);
4084c8ea8731SJohn Baldwin 
4085c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
4086c8ea8731SJohn Baldwin 	    sizeof(args)) != -1);
408796a9e50eSAlex Richardson 	REQUIRE_EQ(args[0], wpid);
408896a9e50eSAlex Richardson 	REQUIRE_EQ(args[1], 0);
4089c8ea8731SJohn Baldwin 
409096a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
409132451fb9SJohn Baldwin 
409232451fb9SJohn Baldwin 	/*
409332451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from kill().
409432451fb9SJohn Baldwin 	 */
409532451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
409696a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
409732451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
409896a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
409932451fb9SJohn Baldwin 
410032451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
410132451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
41021fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_kill);
410332451fb9SJohn Baldwin 
410432451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
410532451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
410696a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, 0);
410732451fb9SJohn Baldwin 
410896a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
410932451fb9SJohn Baldwin 
411032451fb9SJohn Baldwin 	/*
411132451fb9SJohn Baldwin 	 * The next stop should be the syscall entry from close().
411232451fb9SJohn Baldwin 	 */
411332451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
411496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
411532451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
411696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
411732451fb9SJohn Baldwin 
411832451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
411932451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
41201fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_close);
41211fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_narg, 1u);
412232451fb9SJohn Baldwin 
412332451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_ARGS, wpid, (caddr_t)args,
412432451fb9SJohn Baldwin 	    sizeof(args)) != -1);
412517cc2009SAlex Richardson 	REQUIRE_EQ(args[0], 12345);
412632451fb9SJohn Baldwin 
412796a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
412832451fb9SJohn Baldwin 
412932451fb9SJohn Baldwin 	/*
413032451fb9SJohn Baldwin 	 * The next stop should be the syscall exit from close().
413132451fb9SJohn Baldwin 	 */
413232451fb9SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
413396a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, fpid);
413432451fb9SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
413596a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGTRAP);
413632451fb9SJohn Baldwin 
413732451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
413832451fb9SJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
41391fcbddecSAlex Richardson 	REQUIRE_EQ(pl.pl_syscall_code, (unsigned)SYS_close);
414032451fb9SJohn Baldwin 
414132451fb9SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_SC_RET, wpid, (caddr_t)&psr,
414232451fb9SJohn Baldwin 	    sizeof(psr)) != -1);
414396a9e50eSAlex Richardson 	REQUIRE_EQ(psr.sr_error, EBADF);
414432451fb9SJohn Baldwin 
4145c8ea8731SJohn Baldwin 	/* Disable syscall tracing and continue the child to let it exit. */
4146c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
4147c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
4148c8ea8731SJohn Baldwin 	events &= ~PTRACE_SYSCALL;
4149c8ea8731SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
4150c8ea8731SJohn Baldwin 	    sizeof(events)) == 0);
415196a9e50eSAlex Richardson 	REQUIRE_EQ(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0), 0);
4152c8ea8731SJohn Baldwin 
4153c8ea8731SJohn Baldwin 	/* The last event should be for the child process's exit. */
4154c8ea8731SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
4155c8ea8731SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
415696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 1);
4157c8ea8731SJohn Baldwin 
4158c8ea8731SJohn Baldwin 	wpid = wait(&status);
415996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
416096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4161c8ea8731SJohn Baldwin }
4162c8ea8731SJohn Baldwin 
4163fd631bcdSMariusz Zaborski /*
4164*526becbfSKonstantin Belousov  * Check that syscall info is available whenever kernel has valid td_sa.
4165*526becbfSKonstantin Belousov  * Assumes that libc nanosleep(2) is the plain syscall wrapper.
4166*526becbfSKonstantin Belousov  */
4167*526becbfSKonstantin Belousov ATF_TC_WITHOUT_HEAD(ptrace__syscall_args_anywhere);
ATF_TC_BODY(ptrace__syscall_args_anywhere,tc)4168*526becbfSKonstantin Belousov ATF_TC_BODY(ptrace__syscall_args_anywhere, tc)
4169*526becbfSKonstantin Belousov {
4170*526becbfSKonstantin Belousov 	struct timespec rqt;
4171*526becbfSKonstantin Belousov 	struct ptrace_lwpinfo lwpi;
4172*526becbfSKonstantin Belousov 	register_t args[8];
4173*526becbfSKonstantin Belousov 	pid_t debuggee, wpid;
4174*526becbfSKonstantin Belousov 	int error, status;
4175*526becbfSKonstantin Belousov 
4176*526becbfSKonstantin Belousov 	debuggee = fork();
4177*526becbfSKonstantin Belousov 	ATF_REQUIRE(debuggee >= 0);
4178*526becbfSKonstantin Belousov 	if (debuggee == 0) {
4179*526becbfSKonstantin Belousov 		rqt.tv_sec = 100000;
4180*526becbfSKonstantin Belousov 		rqt.tv_nsec = 0;
4181*526becbfSKonstantin Belousov 		for (;;)
4182*526becbfSKonstantin Belousov 			nanosleep(&rqt, NULL);
4183*526becbfSKonstantin Belousov 		_exit(0);
4184*526becbfSKonstantin Belousov 	}
4185*526becbfSKonstantin Belousov 
4186*526becbfSKonstantin Belousov 	/* Give the debuggee some time to go to sleep. */
4187*526becbfSKonstantin Belousov 	sleep(2);
4188*526becbfSKonstantin Belousov 	error = ptrace(PT_ATTACH, debuggee, 0, 0);
4189*526becbfSKonstantin Belousov 	ATF_REQUIRE(error == 0);
4190*526becbfSKonstantin Belousov 	wpid = waitpid(debuggee, &status, 0);
4191*526becbfSKonstantin Belousov 	REQUIRE_EQ(wpid, debuggee);
4192*526becbfSKonstantin Belousov 	ATF_REQUIRE(WIFSTOPPED(status));
4193*526becbfSKonstantin Belousov 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
4194*526becbfSKonstantin Belousov 
4195*526becbfSKonstantin Belousov 	error = ptrace(PT_LWPINFO, debuggee, (caddr_t)&lwpi, sizeof(lwpi));
4196*526becbfSKonstantin Belousov 	ATF_REQUIRE(error == 0);
4197*526becbfSKonstantin Belousov 	ATF_REQUIRE(lwpi.pl_syscall_code == SYS_nanosleep);
4198*526becbfSKonstantin Belousov 	ATF_REQUIRE(lwpi.pl_syscall_narg == 2);
4199*526becbfSKonstantin Belousov 	error = ptrace(PT_GET_SC_ARGS, debuggee, (caddr_t)&args[0],
4200*526becbfSKonstantin Belousov 	    lwpi.pl_syscall_narg * sizeof(register_t));
4201*526becbfSKonstantin Belousov 	ATF_REQUIRE(error == 0);
4202*526becbfSKonstantin Belousov 	ATF_REQUIRE(args[0] == (register_t)&rqt);
4203*526becbfSKonstantin Belousov 	ATF_REQUIRE(args[1] == 0);
4204*526becbfSKonstantin Belousov 
4205*526becbfSKonstantin Belousov 	error = ptrace(PT_DETACH, debuggee, 0, 0);
4206*526becbfSKonstantin Belousov 	ATF_REQUIRE(error == 0);
4207*526becbfSKonstantin Belousov 	kill(SIGKILL, debuggee);
4208*526becbfSKonstantin Belousov }
4209*526becbfSKonstantin Belousov 
4210*526becbfSKonstantin Belousov /*
4211fd631bcdSMariusz Zaborski  * Verify that when the process is traced that it isn't reparent
4212fd631bcdSMariusz Zaborski  * to the init process when we close all process descriptors.
4213fd631bcdSMariusz Zaborski  */
4214fd631bcdSMariusz Zaborski ATF_TC(ptrace__proc_reparent);
ATF_TC_HEAD(ptrace__proc_reparent,tc)4215fd631bcdSMariusz Zaborski ATF_TC_HEAD(ptrace__proc_reparent, tc)
4216fd631bcdSMariusz Zaborski {
4217fd631bcdSMariusz Zaborski 
4218fd631bcdSMariusz Zaborski 	atf_tc_set_md_var(tc, "timeout", "2");
4219fd631bcdSMariusz Zaborski }
ATF_TC_BODY(ptrace__proc_reparent,tc)4220fd631bcdSMariusz Zaborski ATF_TC_BODY(ptrace__proc_reparent, tc)
4221fd631bcdSMariusz Zaborski {
4222fd631bcdSMariusz Zaborski 	pid_t traced, debuger, wpid;
4223fd631bcdSMariusz Zaborski 	int pd, status;
4224fd631bcdSMariusz Zaborski 
4225fd631bcdSMariusz Zaborski 	traced = pdfork(&pd, 0);
4226fd631bcdSMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
4227fd631bcdSMariusz Zaborski 	if (traced == 0) {
4228fd631bcdSMariusz Zaborski 		raise(SIGSTOP);
4229fd631bcdSMariusz Zaborski 		exit(0);
4230fd631bcdSMariusz Zaborski 	}
4231fd631bcdSMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
4232fd631bcdSMariusz Zaborski 
4233fd631bcdSMariusz Zaborski 	debuger = fork();
4234fd631bcdSMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
4235fd631bcdSMariusz Zaborski 	if (debuger == 0) {
4236fd631bcdSMariusz Zaborski 		/* The traced process is reparented to debuger. */
423796a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_ATTACH, traced, 0, 0), 0);
4238fd631bcdSMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
423996a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
4240fd631bcdSMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
424196a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
424296a9e50eSAlex Richardson 		REQUIRE_EQ(close(pd), 0);
424396a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_DETACH, traced, (caddr_t)1, 0), 0);
4244fd631bcdSMariusz Zaborski 
4245fd631bcdSMariusz Zaborski 		/* We closed pd so we should not have any child. */
4246fd631bcdSMariusz Zaborski 		wpid = wait(&status);
424796a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, -1);
424896a9e50eSAlex Richardson 		REQUIRE_EQ(errno, ECHILD);
4249fd631bcdSMariusz Zaborski 
4250fd631bcdSMariusz Zaborski 		exit(0);
4251fd631bcdSMariusz Zaborski 	}
4252fd631bcdSMariusz Zaborski 
425396a9e50eSAlex Richardson 	REQUIRE_EQ(close(pd), 0);
4254fd631bcdSMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
425596a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debuger);
425696a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
4257fd631bcdSMariusz Zaborski 
4258fd631bcdSMariusz Zaborski 	/* Check if we still have any child. */
4259fd631bcdSMariusz Zaborski 	wpid = wait(&status);
426096a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
426196a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
4262fd631bcdSMariusz Zaborski }
4263fd631bcdSMariusz Zaborski 
42648e493611SMariusz Zaborski /*
42658e493611SMariusz Zaborski  * Ensure that traced processes created with pdfork(2) are visible to
42668e493611SMariusz Zaborski  * waitid(P_ALL).
42678e493611SMariusz Zaborski  */
42688e493611SMariusz Zaborski ATF_TC_WITHOUT_HEAD(ptrace__procdesc_wait_child);
ATF_TC_BODY(ptrace__procdesc_wait_child,tc)42698e493611SMariusz Zaborski ATF_TC_BODY(ptrace__procdesc_wait_child, tc)
42708e493611SMariusz Zaborski {
42718e493611SMariusz Zaborski 	pid_t child, wpid;
42728e493611SMariusz Zaborski 	int pd, status;
42738e493611SMariusz Zaborski 
42748e493611SMariusz Zaborski 	child = pdfork(&pd, 0);
42758e493611SMariusz Zaborski 	ATF_REQUIRE(child >= 0);
42768e493611SMariusz Zaborski 
42778e493611SMariusz Zaborski 	if (child == 0) {
42788e493611SMariusz Zaborski 		trace_me();
42798e493611SMariusz Zaborski 		(void)raise(SIGSTOP);
42808e493611SMariusz Zaborski 		exit(0);
42818e493611SMariusz Zaborski 	}
42828e493611SMariusz Zaborski 
42838e493611SMariusz Zaborski 	wpid = waitpid(child, &status, 0);
428496a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
42858e493611SMariusz Zaborski 	ATF_REQUIRE(WIFSTOPPED(status));
428696a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42878e493611SMariusz Zaborski 
42888e493611SMariusz Zaborski 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
42898e493611SMariusz Zaborski 
42908e493611SMariusz Zaborski 	wpid = wait(&status);
429196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, child);
42928e493611SMariusz Zaborski 	ATF_REQUIRE(WIFSTOPPED(status));
429396a9e50eSAlex Richardson 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
42948e493611SMariusz Zaborski 
42958e493611SMariusz Zaborski 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
42968e493611SMariusz Zaborski 
42978e493611SMariusz Zaborski 	/*
42988e493611SMariusz Zaborski 	 * If process was created by pdfork, the return code have to
42998e493611SMariusz Zaborski 	 * be collected through process descriptor.
43008e493611SMariusz Zaborski 	 */
43018e493611SMariusz Zaborski 	wpid = wait(&status);
430296a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
430396a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
43048e493611SMariusz Zaborski 
43058e493611SMariusz Zaborski 	ATF_REQUIRE(close(pd) != -1);
43068e493611SMariusz Zaborski }
43078e493611SMariusz Zaborski 
43088e493611SMariusz Zaborski /*
43098e493611SMariusz Zaborski  * Ensure that traced processes created with pdfork(2) are not visible
43108e493611SMariusz Zaborski  * after returning to parent - waitid(P_ALL).
43118e493611SMariusz Zaborski  */
43128e493611SMariusz Zaborski ATF_TC_WITHOUT_HEAD(ptrace__procdesc_reparent_wait_child);
ATF_TC_BODY(ptrace__procdesc_reparent_wait_child,tc)43138e493611SMariusz Zaborski ATF_TC_BODY(ptrace__procdesc_reparent_wait_child, tc)
43148e493611SMariusz Zaborski {
43158e493611SMariusz Zaborski 	pid_t traced, debuger, wpid;
43168e493611SMariusz Zaborski 	int pd, status;
43178e493611SMariusz Zaborski 
43188e493611SMariusz Zaborski 	traced = pdfork(&pd, 0);
43198e493611SMariusz Zaborski 	ATF_REQUIRE(traced >= 0);
43208e493611SMariusz Zaborski 	if (traced == 0) {
43218e493611SMariusz Zaborski 		raise(SIGSTOP);
43228e493611SMariusz Zaborski 		exit(0);
43238e493611SMariusz Zaborski 	}
43248e493611SMariusz Zaborski 	ATF_REQUIRE(pd >= 0);
43258e493611SMariusz Zaborski 
432610321314SAlex Richardson 	/* Wait until the child process has stopped before fork()ing again. */
432710321314SAlex Richardson 	REQUIRE_EQ(traced, waitpid(traced, &status, WSTOPPED));
43288e493611SMariusz Zaborski 	debuger = fork();
43298e493611SMariusz Zaborski 	ATF_REQUIRE(debuger >= 0);
43308e493611SMariusz Zaborski 	if (debuger == 0) {
43318e493611SMariusz Zaborski 		/* The traced process is reparented to debuger. */
433296a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_ATTACH, traced, 0, 0), 0);
43338e493611SMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
433496a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
43358e493611SMariusz Zaborski 		ATF_REQUIRE(WIFSTOPPED(status));
433696a9e50eSAlex Richardson 		REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
43378e493611SMariusz Zaborski 
43388e493611SMariusz Zaborski 		/* Allow process to die. */
433996a9e50eSAlex Richardson 		REQUIRE_EQ(ptrace(PT_CONTINUE, traced, (caddr_t)1, 0), 0);
43408e493611SMariusz Zaborski 		wpid = waitpid(traced, &status, 0);
434196a9e50eSAlex Richardson 		REQUIRE_EQ(wpid, traced);
43428e493611SMariusz Zaborski 		ATF_REQUIRE(WIFEXITED(status));
434396a9e50eSAlex Richardson 		REQUIRE_EQ(WEXITSTATUS(status), 0);
43448e493611SMariusz Zaborski 
43458e493611SMariusz Zaborski 		/* Reparent back to the orginal process. */
434696a9e50eSAlex Richardson 		REQUIRE_EQ(close(pd), 0);
43478e493611SMariusz Zaborski 		exit(0);
43488e493611SMariusz Zaborski 	}
43498e493611SMariusz Zaborski 
43508e493611SMariusz Zaborski 	wpid = waitpid(debuger, &status, 0);
435196a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, debuger);
435296a9e50eSAlex Richardson 	REQUIRE_EQ(WEXITSTATUS(status), 0);
43538e493611SMariusz Zaborski 
43548e493611SMariusz Zaborski 	/*
43558e493611SMariusz Zaborski 	 * We have a child but it has a process descriptori
43568e493611SMariusz Zaborski 	 * so we should not be able to collect it process.
43578e493611SMariusz Zaborski 	 */
43588e493611SMariusz Zaborski 	wpid = wait(&status);
435996a9e50eSAlex Richardson 	REQUIRE_EQ(wpid, -1);
436096a9e50eSAlex Richardson 	REQUIRE_EQ(errno, ECHILD);
43618e493611SMariusz Zaborski 
436296a9e50eSAlex Richardson 	REQUIRE_EQ(close(pd), 0);
43638e493611SMariusz Zaborski }
43648e493611SMariusz Zaborski 
436584494288SMark Johnston /*
436684494288SMark Johnston  * Try using PT_SC_REMOTE to get the PID of a traced child process.
436784494288SMark Johnston  */
436884494288SMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_SC_REMOTE_getpid);
ATF_TC_BODY(ptrace__PT_SC_REMOTE_getpid,tc)436984494288SMark Johnston ATF_TC_BODY(ptrace__PT_SC_REMOTE_getpid, tc)
437084494288SMark Johnston {
437184494288SMark Johnston 	struct ptrace_sc_remote pscr;
437284494288SMark Johnston 	pid_t fpid, wpid;
437384494288SMark Johnston 	int status;
437484494288SMark Johnston 
437584494288SMark Johnston 	ATF_REQUIRE((fpid = fork()) != -1);
437684494288SMark Johnston 	if (fpid == 0) {
437784494288SMark Johnston 		trace_me();
437884494288SMark Johnston 		exit(0);
437984494288SMark Johnston 	}
438084494288SMark Johnston 
438184494288SMark Johnston 	attach_child(fpid);
438284494288SMark Johnston 
438384494288SMark Johnston 	pscr.pscr_syscall = SYS_getpid;
438484494288SMark Johnston 	pscr.pscr_nargs = 0;
438584494288SMark Johnston 	pscr.pscr_args = NULL;
438684494288SMark Johnston 	ATF_REQUIRE(ptrace(PT_SC_REMOTE, fpid, (caddr_t)&pscr, sizeof(pscr)) !=
438784494288SMark Johnston 	    -1);
438884494288SMark Johnston 	ATF_REQUIRE_MSG(pscr.pscr_ret.sr_error == 0,
438984494288SMark Johnston 	    "remote getpid failed with error %d", pscr.pscr_ret.sr_error);
439084494288SMark Johnston 	ATF_REQUIRE_MSG(pscr.pscr_ret.sr_retval[0] == fpid,
4391da8c3d21SMark Johnston 	    "unexpected return value %jd instead of %d",
4392da8c3d21SMark Johnston 	    (intmax_t)pscr.pscr_ret.sr_retval[0], fpid);
439384494288SMark Johnston 
439484494288SMark Johnston 	wpid = waitpid(fpid, &status, 0);
439584494288SMark Johnston 	REQUIRE_EQ(wpid, fpid);
439684494288SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
439784494288SMark Johnston 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
439884494288SMark Johnston 
439984494288SMark Johnston 	pscr.pscr_syscall = SYS_getppid;
440084494288SMark Johnston 	pscr.pscr_nargs = 0;
440184494288SMark Johnston 	pscr.pscr_args = NULL;
440284494288SMark Johnston 	ATF_REQUIRE(ptrace(PT_SC_REMOTE, fpid, (caddr_t)&pscr, sizeof(pscr)) !=
440384494288SMark Johnston 	    -1);
440484494288SMark Johnston 	ATF_REQUIRE_MSG(pscr.pscr_ret.sr_error == 0,
440584494288SMark Johnston 	    "remote getppid failed with error %d", pscr.pscr_ret.sr_error);
440684494288SMark Johnston 	ATF_REQUIRE_MSG(pscr.pscr_ret.sr_retval[0] == getpid(),
4407da8c3d21SMark Johnston 	    "unexpected return value %jd instead of %d",
4408da8c3d21SMark Johnston 	    (intmax_t)pscr.pscr_ret.sr_retval[0], fpid);
440984494288SMark Johnston 
441084494288SMark Johnston 	wpid = waitpid(fpid, &status, 0);
441184494288SMark Johnston 	REQUIRE_EQ(wpid, fpid);
441284494288SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
441384494288SMark Johnston 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
441484494288SMark Johnston 
441584494288SMark Johnston 	ATF_REQUIRE(ptrace(PT_DETACH, fpid, (caddr_t)1, 0) != -1);
441684494288SMark Johnston }
441784494288SMark Johnston 
441843b4da44SMark Johnston /*
441943b4da44SMark Johnston  * Ensure that procctl(PROC_REAP_KILL) won't block forever waiting for a target
442043b4da44SMark Johnston  * process that stopped to report its status to a debugger.
442143b4da44SMark Johnston  */
442243b4da44SMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__reap_kill_stopped);
ATF_TC_BODY(ptrace__reap_kill_stopped,tc)442343b4da44SMark Johnston ATF_TC_BODY(ptrace__reap_kill_stopped, tc)
442443b4da44SMark Johnston {
442543b4da44SMark Johnston 	struct procctl_reaper_kill prk;
442643b4da44SMark Johnston 	pid_t debuggee, wpid;
442743b4da44SMark Johnston 	int error, status;
442843b4da44SMark Johnston 
442943b4da44SMark Johnston 	REQUIRE_EQ(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL), 0);
443043b4da44SMark Johnston 
443143b4da44SMark Johnston 	debuggee = fork();
443243b4da44SMark Johnston 	ATF_REQUIRE(debuggee >= 0);
443343b4da44SMark Johnston 	if (debuggee == 0) {
443443b4da44SMark Johnston 		trace_me();
443543b4da44SMark Johnston 		for (;;)
443643b4da44SMark Johnston 			sleep(10);
443743b4da44SMark Johnston 		_exit(0);
443843b4da44SMark Johnston 	}
443943b4da44SMark Johnston 	wpid = waitpid(debuggee, &status, 0);
444043b4da44SMark Johnston 	REQUIRE_EQ(wpid, debuggee);
444143b4da44SMark Johnston 	ATF_REQUIRE(WIFSTOPPED(status));
444243b4da44SMark Johnston 	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
444343b4da44SMark Johnston 
444443b4da44SMark Johnston 	/* Resume the child and ask it to stop during syscall exits. */
444543b4da44SMark Johnston 	ATF_REQUIRE(ptrace(PT_TO_SCX, debuggee, (caddr_t)1, 0) != -1);
444643b4da44SMark Johnston 
444743b4da44SMark Johnston 	/* Give the debuggee some time to go to sleep. */
444843b4da44SMark Johnston 	usleep(100000);
444943b4da44SMark Johnston 
445043b4da44SMark Johnston 	/*
445143b4da44SMark Johnston 	 * Kill the child process.  procctl() may attempt to stop the target
445243b4da44SMark Johnston 	 * process to prevent it from adding new children to the reaper subtree,
445343b4da44SMark Johnston 	 * and this should not conflict with the child stopping itself for the
445443b4da44SMark Johnston 	 * debugger.
445543b4da44SMark Johnston 	 */
445643b4da44SMark Johnston 	memset(&prk, 0, sizeof(prk));
445743b4da44SMark Johnston 	prk.rk_sig = SIGTERM;
445843b4da44SMark Johnston 	error = procctl(P_PID, getpid(), PROC_REAP_KILL, &prk);
445943b4da44SMark Johnston 	REQUIRE_EQ(error, 0);
446077c3e564SMark Johnston 	REQUIRE_EQ(1u, prk.rk_killed);
446143b4da44SMark Johnston 	REQUIRE_EQ(-1, prk.rk_fpid);
446243b4da44SMark Johnston }
446343b4da44SMark Johnston 
ATF_TP_ADD_TCS(tp)4464c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
4465c209e3e2SJohn Baldwin {
4466c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
4467c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
446857c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
446957c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
4470128c9bc0SMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
447198685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
447298685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
447398685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
447498685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
447598685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
447698685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
447798685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
447898685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
4479368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
4480189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
4481189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
4482189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
44835fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
44845fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
44853340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
44868d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
44878d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
44888d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
4489fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
4490fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
4491403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT
449282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
4493e2ebfbbfSEric Badger #endif
449482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
449582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
449682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
449782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
449882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
449982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
450082a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
450182a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
450282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
4503753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
450482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
450582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
450682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
450782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
4508753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
4509753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
451082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
4511548a2ec4SAndrew Turner 	ATF_TP_ADD_TC(tp, ptrace__PT_REGSET);
4512b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
4513b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
4514b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
4515d74da94cSMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
451654cfb29eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
4517643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT
4518643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo);
4519643ce7deSJohn Baldwin #endif
4520643ce7deSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__step_siginfo);
4521403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
4522e012fe34SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
4523e012fe34SJohn Baldwin #endif
4524c5786670SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
4525c8ea8731SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__syscall_args);
4526*526becbfSKonstantin Belousov 	ATF_TP_ADD_TC(tp, ptrace__syscall_args_anywhere);
4527fd631bcdSMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__proc_reparent);
45288e493611SMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__procdesc_wait_child);
45298e493611SMariusz Zaborski 	ATF_TP_ADD_TC(tp, ptrace__procdesc_reparent_wait_child);
453084494288SMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_SC_REMOTE_getpid);
453143b4da44SMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__reap_kill_stopped);
4532c209e3e2SJohn Baldwin 
4533c209e3e2SJohn Baldwin 	return (atf_no_error());
4534c209e3e2SJohn Baldwin }
4535