xref: /freebsd/tests/sys/kern/ptrace_test.c (revision 753e292217c103661d546d2b92b2bbd6f2e458bd)
1c209e3e2SJohn Baldwin /*-
2c209e3e2SJohn Baldwin  * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
3c209e3e2SJohn Baldwin  * All rights reserved.
4c209e3e2SJohn Baldwin  *
5c209e3e2SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
6c209e3e2SJohn Baldwin  * modification, are permitted provided that the following conditions
7c209e3e2SJohn Baldwin  * are met:
8c209e3e2SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
9c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
10c209e3e2SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
11c209e3e2SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
12c209e3e2SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
13c209e3e2SJohn Baldwin  *
14c209e3e2SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15c209e3e2SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16c209e3e2SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c209e3e2SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18c209e3e2SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c209e3e2SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c209e3e2SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c209e3e2SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c209e3e2SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c209e3e2SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24c209e3e2SJohn Baldwin  * SUCH DAMAGE.
25c209e3e2SJohn Baldwin  */
26c209e3e2SJohn Baldwin 
27c209e3e2SJohn Baldwin #include <sys/cdefs.h>
28c209e3e2SJohn Baldwin __FBSDID("$FreeBSD$");
29c209e3e2SJohn Baldwin 
30c209e3e2SJohn Baldwin #include <sys/types.h>
3182a4538fSEric Badger #include <sys/cpuset.h>
3282a4538fSEric Badger #include <sys/event.h>
33d74da94cSMark Johnston #include <sys/file.h>
3482a4538fSEric Badger #include <sys/time.h>
35b38bd91fSEric Badger #include <sys/procctl.h>
36c209e3e2SJohn Baldwin #include <sys/ptrace.h>
37bc2be1d3SEric Badger #include <sys/queue.h>
38bc2be1d3SEric Badger #include <sys/runq.h>
39189ac973SJohn Baldwin #include <sys/syscall.h>
4057c74f5bSJohn Baldwin #include <sys/sysctl.h>
4157c74f5bSJohn Baldwin #include <sys/user.h>
42c209e3e2SJohn Baldwin #include <sys/wait.h>
43c209e3e2SJohn Baldwin #include <errno.h>
449e0d1159SEric Badger #include <machine/cpufunc.h>
45189ac973SJohn Baldwin #include <pthread.h>
46bc2be1d3SEric Badger #include <sched.h>
4782a4538fSEric Badger #include <semaphore.h>
48c209e3e2SJohn Baldwin #include <signal.h>
49dfa8ba12SJohn Baldwin #include <stdio.h>
50c209e3e2SJohn Baldwin #include <stdlib.h>
51c209e3e2SJohn Baldwin #include <unistd.h>
52c209e3e2SJohn Baldwin #include <atf-c.h>
53c209e3e2SJohn Baldwin 
54c209e3e2SJohn Baldwin /*
55dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
56dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
57dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
58dfa8ba12SJohn Baldwin  */
59dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {						\
60dfa8ba12SJohn Baldwin 		if (!(exp))						\
61dfa8ba12SJohn Baldwin 			child_fail_require(__FILE__, __LINE__,		\
62dfa8ba12SJohn Baldwin 			    #exp " not met");				\
63dfa8ba12SJohn Baldwin 	} while (0)
64dfa8ba12SJohn Baldwin 
6598685dc8SJohn Baldwin static __dead2 void
66dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str)
67dfa8ba12SJohn Baldwin {
68dfa8ba12SJohn Baldwin 	char buf[128];
69dfa8ba12SJohn Baldwin 
70dfa8ba12SJohn Baldwin 	snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str);
71dfa8ba12SJohn Baldwin 	write(2, buf, strlen(buf));
72dfa8ba12SJohn Baldwin 	_exit(32);
73dfa8ba12SJohn Baldwin }
74dfa8ba12SJohn Baldwin 
7598685dc8SJohn Baldwin static void
7698685dc8SJohn Baldwin trace_me(void)
7798685dc8SJohn Baldwin {
7898685dc8SJohn Baldwin 
7998685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
8098685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8198685dc8SJohn Baldwin 
8298685dc8SJohn Baldwin 	/* Trigger a stop. */
8398685dc8SJohn Baldwin 	raise(SIGSTOP);
8498685dc8SJohn Baldwin }
8598685dc8SJohn Baldwin 
8698685dc8SJohn Baldwin static void
8798685dc8SJohn Baldwin attach_child(pid_t pid)
8898685dc8SJohn Baldwin {
8998685dc8SJohn Baldwin 	pid_t wpid;
9098685dc8SJohn Baldwin 	int status;
9198685dc8SJohn Baldwin 
9298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
9398685dc8SJohn Baldwin 
9498685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
9598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == pid);
9698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
9798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
9898685dc8SJohn Baldwin }
9998685dc8SJohn Baldwin 
10098685dc8SJohn Baldwin static void
10198685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
10298685dc8SJohn Baldwin {
10398685dc8SJohn Baldwin 
10498685dc8SJohn Baldwin 	/*
10598685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
10698685dc8SJohn Baldwin 	 * there is not a better way.
10798685dc8SJohn Baldwin 	 */
10898685dc8SJohn Baldwin 	for (;;) {
10998685dc8SJohn Baldwin 		struct kinfo_proc kp;
11098685dc8SJohn Baldwin 		size_t len;
11198685dc8SJohn Baldwin 		int mib[4];
11298685dc8SJohn Baldwin 
11398685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
11498685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
11598685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
11698685dc8SJohn Baldwin 		mib[3] = pid;
11798685dc8SJohn Baldwin 		len = sizeof(kp);
11898685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
11998685dc8SJohn Baldwin 			/* The KERN_PROC_PID sysctl fails for zombies. */
12098685dc8SJohn Baldwin 			ATF_REQUIRE(errno == ESRCH);
12198685dc8SJohn Baldwin 			break;
12298685dc8SJohn Baldwin 		}
12398685dc8SJohn Baldwin 		usleep(5000);
12498685dc8SJohn Baldwin 	}
12598685dc8SJohn Baldwin }
12698685dc8SJohn Baldwin 
127dfa8ba12SJohn Baldwin /*
128c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
129c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
130c209e3e2SJohn Baldwin  */
131c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
132c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
133c209e3e2SJohn Baldwin {
134c209e3e2SJohn Baldwin 	pid_t child, wpid;
135c209e3e2SJohn Baldwin 	int status;
136c209e3e2SJohn Baldwin 
137c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
138c209e3e2SJohn Baldwin 	if (child == 0) {
139c209e3e2SJohn Baldwin 		/* Child process. */
14098685dc8SJohn Baldwin 		trace_me();
141c209e3e2SJohn Baldwin 
142b98cb919SJohn Baldwin 		_exit(1);
143c209e3e2SJohn Baldwin 	}
144c209e3e2SJohn Baldwin 
145c209e3e2SJohn Baldwin 	/* Parent process. */
146c209e3e2SJohn Baldwin 
147c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
148c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
149c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
150c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
151c209e3e2SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
152c209e3e2SJohn Baldwin 
153c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
154c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
155c209e3e2SJohn Baldwin 
156c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
157c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
158c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
159c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
160c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
161c209e3e2SJohn Baldwin 
162c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
163c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
164c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
165c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
166c209e3e2SJohn Baldwin }
167c209e3e2SJohn Baldwin 
168c209e3e2SJohn Baldwin /*
169c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
170c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
171c209e3e2SJohn Baldwin  */
172c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
173c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
174c209e3e2SJohn Baldwin {
175c209e3e2SJohn Baldwin 	pid_t child, wpid;
176c209e3e2SJohn Baldwin 	int cpipe[2], status;
177c209e3e2SJohn Baldwin 	char c;
178c209e3e2SJohn Baldwin 
179c209e3e2SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
180c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
181c209e3e2SJohn Baldwin 	if (child == 0) {
182c209e3e2SJohn Baldwin 		/* Child process. */
183c209e3e2SJohn Baldwin 		close(cpipe[0]);
184c209e3e2SJohn Baldwin 
185c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
186dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0);
187c209e3e2SJohn Baldwin 
188b98cb919SJohn Baldwin 		_exit(1);
189c209e3e2SJohn Baldwin 	}
190c209e3e2SJohn Baldwin 	close(cpipe[1]);
191c209e3e2SJohn Baldwin 
192c209e3e2SJohn Baldwin 	/* Parent process. */
193c209e3e2SJohn Baldwin 
194c209e3e2SJohn Baldwin 	/* Attach to the child process. */
19598685dc8SJohn Baldwin 	attach_child(child);
196c209e3e2SJohn Baldwin 
197c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
198c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
199c209e3e2SJohn Baldwin 
200c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
201c209e3e2SJohn Baldwin 	close(cpipe[0]);
202c209e3e2SJohn Baldwin 
203c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
204c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
205c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
206c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
207c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
208c209e3e2SJohn Baldwin 
209c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
210c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
211c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
212c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
213c209e3e2SJohn Baldwin }
214c209e3e2SJohn Baldwin 
21557c74f5bSJohn Baldwin /*
21657c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
21757c74f5bSJohn Baldwin  * after the debugger has seen it.
21857c74f5bSJohn Baldwin  */
21957c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
22057c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
22157c74f5bSJohn Baldwin {
22257c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
22357c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
22457c74f5bSJohn Baldwin 	char c;
22557c74f5bSJohn Baldwin 
22657c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
22757c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
22857c74f5bSJohn Baldwin 
22957c74f5bSJohn Baldwin 	if (child == 0) {
23057c74f5bSJohn Baldwin 		/* Child process. */
23157c74f5bSJohn Baldwin 		close(cpipe[0]);
23257c74f5bSJohn Baldwin 
23357c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
234dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
23557c74f5bSJohn Baldwin 
236b98cb919SJohn Baldwin 		_exit(1);
23757c74f5bSJohn Baldwin 	}
23857c74f5bSJohn Baldwin 	close(cpipe[1]);
23957c74f5bSJohn Baldwin 
24057c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
24157c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
24257c74f5bSJohn Baldwin 
24357c74f5bSJohn Baldwin 	if (debugger == 0) {
24457c74f5bSJohn Baldwin 		/* Debugger process. */
24557c74f5bSJohn Baldwin 		close(dpipe[0]);
24657c74f5bSJohn Baldwin 
247dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
24857c74f5bSJohn Baldwin 
24957c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
250dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
251dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
252dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
25357c74f5bSJohn Baldwin 
254dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
25557c74f5bSJohn Baldwin 
25657c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
257dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
25857c74f5bSJohn Baldwin 
25957c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
260dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0);
26157c74f5bSJohn Baldwin 
26257c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
263dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
264dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
265dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
26657c74f5bSJohn Baldwin 
267b98cb919SJohn Baldwin 		_exit(0);
26857c74f5bSJohn Baldwin 	}
26957c74f5bSJohn Baldwin 	close(dpipe[1]);
27057c74f5bSJohn Baldwin 
27157c74f5bSJohn Baldwin 	/* Parent process. */
27257c74f5bSJohn Baldwin 
27357c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
27457c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
27557c74f5bSJohn Baldwin 
27657c74f5bSJohn Baldwin 	/* Release the child. */
27757c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
27857c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
27957c74f5bSJohn Baldwin 	close(cpipe[0]);
28057c74f5bSJohn Baldwin 
28198685dc8SJohn Baldwin 	wait_for_zombie(child);
28257c74f5bSJohn Baldwin 
28357c74f5bSJohn Baldwin 	/*
2842f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
2852f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
2862f021998SJohn Baldwin 	 * until the debugger sees the exit.
28757c74f5bSJohn Baldwin 	 */
28857c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
28957c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
29057c74f5bSJohn Baldwin 
29157c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
29257c74f5bSJohn Baldwin 	close(dpipe[0]);
29357c74f5bSJohn Baldwin 
29457c74f5bSJohn Baldwin 	/* Wait for the debugger. */
29557c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
29657c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
29757c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
29857c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
29957c74f5bSJohn Baldwin 
30057c74f5bSJohn Baldwin 	/* The child process should now be ready. */
30157c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
30257c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
30357c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
30457c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
30557c74f5bSJohn Baldwin }
30657c74f5bSJohn Baldwin 
30757c74f5bSJohn Baldwin /*
30857c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
30957c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
31057c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
31157c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
31257c74f5bSJohn Baldwin  */
31357c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
31457c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
31557c74f5bSJohn Baldwin {
31657c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
31757c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
31857c74f5bSJohn Baldwin 	char c;
31957c74f5bSJohn Baldwin 
32057c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
32157c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
32257c74f5bSJohn Baldwin 
32357c74f5bSJohn Baldwin 	if (child == 0) {
32457c74f5bSJohn Baldwin 		/* Child process. */
32557c74f5bSJohn Baldwin 		close(cpipe[0]);
32657c74f5bSJohn Baldwin 
32757c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
328dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
32957c74f5bSJohn Baldwin 
330b98cb919SJohn Baldwin 		_exit(1);
33157c74f5bSJohn Baldwin 	}
33257c74f5bSJohn Baldwin 	close(cpipe[1]);
33357c74f5bSJohn Baldwin 
33457c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
33557c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
33657c74f5bSJohn Baldwin 
33757c74f5bSJohn Baldwin 	if (debugger == 0) {
33857c74f5bSJohn Baldwin 		/* Debugger parent. */
33957c74f5bSJohn Baldwin 
34057c74f5bSJohn Baldwin 		/*
34157c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
34257c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
34357c74f5bSJohn Baldwin 		 */
344dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
34557c74f5bSJohn Baldwin 		if (fpid != 0)
346b98cb919SJohn Baldwin 			_exit(2);
34757c74f5bSJohn Baldwin 
34857c74f5bSJohn Baldwin 		/* Debugger process. */
34957c74f5bSJohn Baldwin 		close(dpipe[0]);
35057c74f5bSJohn Baldwin 
351dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
35257c74f5bSJohn Baldwin 
35357c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
354dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
355dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
356dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
35757c74f5bSJohn Baldwin 
358dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
35957c74f5bSJohn Baldwin 
36057c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
361dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
36257c74f5bSJohn Baldwin 
36357c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
364dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c));
36557c74f5bSJohn Baldwin 
36657c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
367dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
368dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
369dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
37057c74f5bSJohn Baldwin 
371b98cb919SJohn Baldwin 		_exit(0);
37257c74f5bSJohn Baldwin 	}
373eddb85c6SJohn Baldwin 	close(dpipe[1]);
37457c74f5bSJohn Baldwin 
37557c74f5bSJohn Baldwin 	/* Parent process. */
37657c74f5bSJohn Baldwin 
37757c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
37857c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
37957c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
38057c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
38157c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
38257c74f5bSJohn Baldwin 
38357c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
38457c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
38557c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
38657c74f5bSJohn Baldwin 
38757c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
38857c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
38957c74f5bSJohn Baldwin 
39057c74f5bSJohn Baldwin 	/* Release the child. */
39157c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
39257c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
39357c74f5bSJohn Baldwin 	close(cpipe[0]);
39457c74f5bSJohn Baldwin 
39598685dc8SJohn Baldwin 	wait_for_zombie(child);
39657c74f5bSJohn Baldwin 
39757c74f5bSJohn Baldwin 	/*
3982f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3992f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
4002f021998SJohn Baldwin 	 * until the debugger sees the exit.
40157c74f5bSJohn Baldwin 	 */
40257c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
40357c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
40457c74f5bSJohn Baldwin 
40557c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
406eddb85c6SJohn Baldwin 	ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c));
40757c74f5bSJohn Baldwin 
40857c74f5bSJohn Baldwin 	/* Wait for the debugger. */
409eddb85c6SJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0);
410eddb85c6SJohn Baldwin 	close(dpipe[0]);
41157c74f5bSJohn Baldwin 
41257c74f5bSJohn Baldwin 	/* The child process should now be ready. */
41357c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
41457c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
41557c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
41657c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
41757c74f5bSJohn Baldwin }
41857c74f5bSJohn Baldwin 
41998685dc8SJohn Baldwin /*
42098685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
42198685dc8SJohn Baldwin  * debugger is attached to it.
42298685dc8SJohn Baldwin  */
42398685dc8SJohn Baldwin static __dead2 void
424189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
42598685dc8SJohn Baldwin {
42698685dc8SJohn Baldwin 	pid_t fpid, wpid;
42798685dc8SJohn Baldwin 	int status;
42898685dc8SJohn Baldwin 
429189ac973SJohn Baldwin 	if (use_vfork)
430189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
431189ac973SJohn Baldwin 	else
43298685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
43398685dc8SJohn Baldwin 
43498685dc8SJohn Baldwin 	if (fpid == 0)
43598685dc8SJohn Baldwin 		/* Child */
436b98cb919SJohn Baldwin 		_exit(2);
43798685dc8SJohn Baldwin 
43898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
43998685dc8SJohn Baldwin 	CHILD_REQUIRE(wpid == fpid);
44098685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
44198685dc8SJohn Baldwin 	CHILD_REQUIRE(WEXITSTATUS(status) == 2);
44298685dc8SJohn Baldwin 
443b98cb919SJohn Baldwin 	_exit(1);
44498685dc8SJohn Baldwin }
44598685dc8SJohn Baldwin 
44698685dc8SJohn Baldwin /*
44798685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
44898685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
44998685dc8SJohn Baldwin  * child process.
45098685dc8SJohn Baldwin  */
45198685dc8SJohn Baldwin static pid_t
452189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
45398685dc8SJohn Baldwin {
45498685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
45598685dc8SJohn Baldwin 	bool fork_reported[2];
45698685dc8SJohn Baldwin 	pid_t child, wpid;
45798685dc8SJohn Baldwin 	int i, status;
45898685dc8SJohn Baldwin 
45998685dc8SJohn Baldwin 	fork_reported[0] = false;
46098685dc8SJohn Baldwin 	fork_reported[1] = false;
46198685dc8SJohn Baldwin 	child = -1;
46298685dc8SJohn Baldwin 
46398685dc8SJohn Baldwin 	/*
46498685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
46598685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
46698685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
46798685dc8SJohn Baldwin 	 */
46898685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
46998685dc8SJohn Baldwin 		wpid = wait(&status);
47098685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
47198685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
47298685dc8SJohn Baldwin 
47398685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
47498685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
47598685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
47698685dc8SJohn Baldwin 		    0);
47798685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
47898685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
47998685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
48098685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
48198685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
48298685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
48398685dc8SJohn Baldwin 			if (child == -1)
48498685dc8SJohn Baldwin 				child = wpid;
48598685dc8SJohn Baldwin 			else
48698685dc8SJohn Baldwin 				ATF_REQUIRE(child == wpid);
487189ac973SJohn Baldwin 			if (ppl != NULL)
488189ac973SJohn Baldwin 				ppl[1] = pl;
48998685dc8SJohn Baldwin 			fork_reported[1] = true;
49098685dc8SJohn Baldwin 		} else {
49198685dc8SJohn Baldwin 			ATF_REQUIRE(wpid == parent);
49298685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
49398685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
49498685dc8SJohn Baldwin 			if (child == -1)
49598685dc8SJohn Baldwin 				child = pl.pl_child_pid;
49698685dc8SJohn Baldwin 			else
49798685dc8SJohn Baldwin 				ATF_REQUIRE(child == pl.pl_child_pid);
498189ac973SJohn Baldwin 			if (ppl != NULL)
499189ac973SJohn Baldwin 				ppl[0] = pl;
50098685dc8SJohn Baldwin 			fork_reported[0] = true;
50198685dc8SJohn Baldwin 		}
50298685dc8SJohn Baldwin 	}
50398685dc8SJohn Baldwin 
50498685dc8SJohn Baldwin 	return (child);
50598685dc8SJohn Baldwin }
50698685dc8SJohn Baldwin 
50798685dc8SJohn Baldwin /*
50898685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
50998685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
51098685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
51198685dc8SJohn Baldwin  */
51298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
51398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
51498685dc8SJohn Baldwin {
515479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
51698685dc8SJohn Baldwin 	int status;
51798685dc8SJohn Baldwin 
51898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
51998685dc8SJohn Baldwin 	if (fpid == 0) {
52098685dc8SJohn Baldwin 		trace_me();
521189ac973SJohn Baldwin 		follow_fork_parent(false);
52298685dc8SJohn Baldwin 	}
52398685dc8SJohn Baldwin 
52498685dc8SJohn Baldwin 	/* Parent process. */
52598685dc8SJohn Baldwin 	children[0] = fpid;
52698685dc8SJohn Baldwin 
52798685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
52898685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
52998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
53098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
53198685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
53298685dc8SJohn Baldwin 
53398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
53498685dc8SJohn Baldwin 
53598685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
53698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
53798685dc8SJohn Baldwin 
538189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
53998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
54098685dc8SJohn Baldwin 
54198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
54298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
54398685dc8SJohn Baldwin 
54498685dc8SJohn Baldwin 	/*
54598685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
54698685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
54798685dc8SJohn Baldwin 	 */
54898685dc8SJohn Baldwin 	wpid = wait(&status);
54998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
55098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
55198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
55298685dc8SJohn Baldwin 
55398685dc8SJohn Baldwin 	wpid = wait(&status);
55498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
55598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
55698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
55798685dc8SJohn Baldwin 
55898685dc8SJohn Baldwin 	wpid = wait(&status);
55998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
56098685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
56198685dc8SJohn Baldwin }
56298685dc8SJohn Baldwin 
56398685dc8SJohn Baldwin /*
56498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
56598685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
56698685dc8SJohn Baldwin  * child process is detached after it reports its fork.
56798685dc8SJohn Baldwin  */
56898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
56998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
57098685dc8SJohn Baldwin {
571479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
57298685dc8SJohn Baldwin 	int status;
57398685dc8SJohn Baldwin 
57498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
57598685dc8SJohn Baldwin 	if (fpid == 0) {
57698685dc8SJohn Baldwin 		trace_me();
577189ac973SJohn Baldwin 		follow_fork_parent(false);
57898685dc8SJohn Baldwin 	}
57998685dc8SJohn Baldwin 
58098685dc8SJohn Baldwin 	/* Parent process. */
58198685dc8SJohn Baldwin 	children[0] = fpid;
58298685dc8SJohn Baldwin 
58398685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
58498685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
58598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
58698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
58798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
58898685dc8SJohn Baldwin 
58998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
59098685dc8SJohn Baldwin 
59198685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
59298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
59398685dc8SJohn Baldwin 
594189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
59598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
59698685dc8SJohn Baldwin 
59798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
59898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
59998685dc8SJohn Baldwin 
60098685dc8SJohn Baldwin 	/*
60198685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
60298685dc8SJohn Baldwin 	 * child.
60398685dc8SJohn Baldwin 	 */
60498685dc8SJohn Baldwin 	wpid = wait(&status);
60598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
60698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
60798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
60898685dc8SJohn Baldwin 
60998685dc8SJohn Baldwin 	wpid = wait(&status);
61098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
61198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
61298685dc8SJohn Baldwin }
61398685dc8SJohn Baldwin 
61498685dc8SJohn Baldwin /*
61598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
61698685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
61798685dc8SJohn Baldwin  * traced parent is detached after the fork.
61898685dc8SJohn Baldwin  */
61998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
62098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
62198685dc8SJohn Baldwin {
622479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
62398685dc8SJohn Baldwin 	int status;
62498685dc8SJohn Baldwin 
62598685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
62698685dc8SJohn Baldwin 	if (fpid == 0) {
62798685dc8SJohn Baldwin 		trace_me();
628189ac973SJohn Baldwin 		follow_fork_parent(false);
62998685dc8SJohn Baldwin 	}
63098685dc8SJohn Baldwin 
63198685dc8SJohn Baldwin 	/* Parent process. */
63298685dc8SJohn Baldwin 	children[0] = fpid;
63398685dc8SJohn Baldwin 
63498685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
63598685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
63698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
63798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
63898685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
63998685dc8SJohn Baldwin 
64098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
64198685dc8SJohn Baldwin 
64298685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
64398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
64498685dc8SJohn Baldwin 
645189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
64698685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
64798685dc8SJohn Baldwin 
64898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
64998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
65098685dc8SJohn Baldwin 
65198685dc8SJohn Baldwin 	/*
65298685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
65398685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
65498685dc8SJohn Baldwin 	 *
65598685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
65698685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
65798685dc8SJohn Baldwin 	 * after the grandchild.
65898685dc8SJohn Baldwin 	 */
65998685dc8SJohn Baldwin 	wpid = wait(&status);
66098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
66198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
66298685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
66398685dc8SJohn Baldwin 
66498685dc8SJohn Baldwin 	wpid = wait(&status);
66598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
66698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
66798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
66898685dc8SJohn Baldwin 
66998685dc8SJohn Baldwin 	wpid = wait(&status);
67098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
67198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
67298685dc8SJohn Baldwin }
67398685dc8SJohn Baldwin 
67498685dc8SJohn Baldwin static void
67598685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
67698685dc8SJohn Baldwin {
67798685dc8SJohn Baldwin 	pid_t fpid;
67898685dc8SJohn Baldwin 
67998685dc8SJohn Baldwin 	close(cpipe[0]);
68098685dc8SJohn Baldwin 
68198685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
68298685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
68398685dc8SJohn Baldwin 	if (fpid != 0)
684b98cb919SJohn Baldwin 		_exit(3);
68598685dc8SJohn Baldwin 
68698685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
68798685dc8SJohn Baldwin 	fpid = getpid();
68898685dc8SJohn Baldwin 	CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
68998685dc8SJohn Baldwin 
69098685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
69198685dc8SJohn Baldwin 	CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
69298685dc8SJohn Baldwin }
69398685dc8SJohn Baldwin 
69498685dc8SJohn Baldwin /*
69598685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
69698685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
69798685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
69898685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
69998685dc8SJohn Baldwin  */
70098685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
70198685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
70298685dc8SJohn Baldwin {
703479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
70498685dc8SJohn Baldwin 	int cpipe[2], status;
70598685dc8SJohn Baldwin 
70698685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
70798685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
70898685dc8SJohn Baldwin 	if (fpid == 0) {
70998685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
710189ac973SJohn Baldwin 		follow_fork_parent(false);
71198685dc8SJohn Baldwin 	}
71298685dc8SJohn Baldwin 
71398685dc8SJohn Baldwin 	/* Parent process. */
71498685dc8SJohn Baldwin 	close(cpipe[1]);
71598685dc8SJohn Baldwin 
71698685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
71798685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
71898685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
71998685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
72098685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
72198685dc8SJohn Baldwin 
72298685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
72398685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
72498685dc8SJohn Baldwin 	    sizeof(children[0]));
72598685dc8SJohn Baldwin 
72698685dc8SJohn Baldwin 	/* Attach to the fork parent. */
72798685dc8SJohn Baldwin 	attach_child(children[0]);
72898685dc8SJohn Baldwin 
72998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
73098685dc8SJohn Baldwin 
73198685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
73298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
73398685dc8SJohn Baldwin 
73498685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
73598685dc8SJohn Baldwin 	close(cpipe[0]);
73698685dc8SJohn Baldwin 
737189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
73898685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
73998685dc8SJohn Baldwin 
74098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
74198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
74298685dc8SJohn Baldwin 
74398685dc8SJohn Baldwin 	/*
74498685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
74598685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
74698685dc8SJohn Baldwin 	 */
74798685dc8SJohn Baldwin 	wpid = wait(&status);
74898685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
74998685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
75098685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
75198685dc8SJohn Baldwin 
75298685dc8SJohn Baldwin 	wpid = wait(&status);
75398685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
75498685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
75598685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
75698685dc8SJohn Baldwin 
75798685dc8SJohn Baldwin 	wpid = wait(&status);
75898685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
75998685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
76098685dc8SJohn Baldwin }
76198685dc8SJohn Baldwin 
76298685dc8SJohn Baldwin /*
76398685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
76498685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
76598685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
76698685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
76798685dc8SJohn Baldwin  */
76898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
76998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
77098685dc8SJohn Baldwin {
771479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
77298685dc8SJohn Baldwin 	int cpipe[2], status;
77398685dc8SJohn Baldwin 
77498685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
77598685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
77698685dc8SJohn Baldwin 	if (fpid == 0) {
77798685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
778189ac973SJohn Baldwin 		follow_fork_parent(false);
77998685dc8SJohn Baldwin 	}
78098685dc8SJohn Baldwin 
78198685dc8SJohn Baldwin 	/* Parent process. */
78298685dc8SJohn Baldwin 	close(cpipe[1]);
78398685dc8SJohn Baldwin 
78498685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
78598685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
78698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
78798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
78898685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
78998685dc8SJohn Baldwin 
79098685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
79198685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
79298685dc8SJohn Baldwin 	    sizeof(children[0]));
79398685dc8SJohn Baldwin 
79498685dc8SJohn Baldwin 	/* Attach to the fork parent. */
79598685dc8SJohn Baldwin 	attach_child(children[0]);
79698685dc8SJohn Baldwin 
79798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
79898685dc8SJohn Baldwin 
79998685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
80098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
80198685dc8SJohn Baldwin 
80298685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
80398685dc8SJohn Baldwin 	close(cpipe[0]);
80498685dc8SJohn Baldwin 
805189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
80698685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
80798685dc8SJohn Baldwin 
80898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
80998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
81098685dc8SJohn Baldwin 
81198685dc8SJohn Baldwin 	/*
81298685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
81398685dc8SJohn Baldwin 	 * parent.
81498685dc8SJohn Baldwin 	 */
81598685dc8SJohn Baldwin 	wpid = wait(&status);
81698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
81798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
81898685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
81998685dc8SJohn Baldwin 
82098685dc8SJohn Baldwin 	wpid = wait(&status);
82198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
82298685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
82398685dc8SJohn Baldwin }
82498685dc8SJohn Baldwin 
82598685dc8SJohn Baldwin /*
82698685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
82798685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
82898685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
82998685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
83098685dc8SJohn Baldwin  */
83198685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
83298685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
83398685dc8SJohn Baldwin {
834479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
83598685dc8SJohn Baldwin 	int cpipe[2], status;
83698685dc8SJohn Baldwin 
83798685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
83898685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
83998685dc8SJohn Baldwin 	if (fpid == 0) {
84098685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
841189ac973SJohn Baldwin 		follow_fork_parent(false);
84298685dc8SJohn Baldwin 	}
84398685dc8SJohn Baldwin 
84498685dc8SJohn Baldwin 	/* Parent process. */
84598685dc8SJohn Baldwin 	close(cpipe[1]);
84698685dc8SJohn Baldwin 
84798685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
84898685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
84998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
85098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
85198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
85298685dc8SJohn Baldwin 
85398685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
85498685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
85598685dc8SJohn Baldwin 	    sizeof(children[0]));
85698685dc8SJohn Baldwin 
85798685dc8SJohn Baldwin 	/* Attach to the fork parent. */
85898685dc8SJohn Baldwin 	attach_child(children[0]);
85998685dc8SJohn Baldwin 
86098685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
86198685dc8SJohn Baldwin 
86298685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
86398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
86498685dc8SJohn Baldwin 
86598685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
86698685dc8SJohn Baldwin 	close(cpipe[0]);
86798685dc8SJohn Baldwin 
868189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
86998685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
87098685dc8SJohn Baldwin 
87198685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
87298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
87398685dc8SJohn Baldwin 
87498685dc8SJohn Baldwin 	/*
87598685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
87698685dc8SJohn Baldwin 	 * the child.
87798685dc8SJohn Baldwin 	 */
87898685dc8SJohn Baldwin 	wpid = wait(&status);
87998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
88098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
88198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
88298685dc8SJohn Baldwin 
88398685dc8SJohn Baldwin 	wpid = wait(&status);
88498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
88598685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
88698685dc8SJohn Baldwin }
88798685dc8SJohn Baldwin 
888368b2b1cSJohn Baldwin /*
889368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
890368b2b1cSJohn Baldwin  * parent but sees its original parent process.
891368b2b1cSJohn Baldwin  */
892368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
893368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
894368b2b1cSJohn Baldwin {
895368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
896368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
897368b2b1cSJohn Baldwin 	char c;
898368b2b1cSJohn Baldwin 
899368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
900368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
901368b2b1cSJohn Baldwin 
902368b2b1cSJohn Baldwin 	if (child == 0) {
903368b2b1cSJohn Baldwin 		/* Child process. */
904368b2b1cSJohn Baldwin 		close(cpipe[0]);
905368b2b1cSJohn Baldwin 
906368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
907368b2b1cSJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
908368b2b1cSJohn Baldwin 
909368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
910368b2b1cSJohn Baldwin 		ppid = getppid();
911368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) ==
912368b2b1cSJohn Baldwin 		    sizeof(ppid));
913368b2b1cSJohn Baldwin 
914368b2b1cSJohn Baldwin 		_exit(1);
915368b2b1cSJohn Baldwin 	}
916368b2b1cSJohn Baldwin 	close(cpipe[1]);
917368b2b1cSJohn Baldwin 
918368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
919368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
920368b2b1cSJohn Baldwin 
921368b2b1cSJohn Baldwin 	if (debugger == 0) {
922368b2b1cSJohn Baldwin 		/* Debugger process. */
923368b2b1cSJohn Baldwin 		close(dpipe[0]);
924368b2b1cSJohn Baldwin 
925368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
926368b2b1cSJohn Baldwin 
927368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
928368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
929368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
930368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
931368b2b1cSJohn Baldwin 
932368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
933368b2b1cSJohn Baldwin 
934368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
935368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
936368b2b1cSJohn Baldwin 
937368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
938368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
939368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
940368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
941368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
942368b2b1cSJohn Baldwin 
943368b2b1cSJohn Baldwin 		_exit(0);
944368b2b1cSJohn Baldwin 	}
945368b2b1cSJohn Baldwin 	close(dpipe[1]);
946368b2b1cSJohn Baldwin 
947368b2b1cSJohn Baldwin 	/* Parent process. */
948368b2b1cSJohn Baldwin 
949368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
950368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
951368b2b1cSJohn Baldwin 
952368b2b1cSJohn Baldwin 	/* Release the child. */
953368b2b1cSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
954368b2b1cSJohn Baldwin 
955368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
956368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid));
957368b2b1cSJohn Baldwin 	close(cpipe[0]);
958368b2b1cSJohn Baldwin 
959368b2b1cSJohn Baldwin 	ATF_REQUIRE(ppid == getpid());
960368b2b1cSJohn Baldwin 
961368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
962368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
963368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
964368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
965368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
966368b2b1cSJohn Baldwin 
967368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
968368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
969368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == child);
970368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
971368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
972368b2b1cSJohn Baldwin }
973368b2b1cSJohn Baldwin 
974189ac973SJohn Baldwin /*
975189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
976189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
977189ac973SJohn Baldwin  */
978189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
979189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
980189ac973SJohn Baldwin {
981189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
982189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
983189ac973SJohn Baldwin 	int status;
984189ac973SJohn Baldwin 
985189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
986189ac973SJohn Baldwin 	if (fpid == 0) {
987189ac973SJohn Baldwin 		trace_me();
988189ac973SJohn Baldwin 		follow_fork_parent(false);
989189ac973SJohn Baldwin 	}
990189ac973SJohn Baldwin 
991189ac973SJohn Baldwin 	/* Parent process. */
992189ac973SJohn Baldwin 	children[0] = fpid;
993189ac973SJohn Baldwin 
994189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
995189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
996189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
997189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
998189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
999189ac973SJohn Baldwin 
1000189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1001189ac973SJohn Baldwin 
1002189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1003189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1004189ac973SJohn Baldwin 
1005189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1006189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1007189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1008189ac973SJohn Baldwin 
1009189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1010189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1011189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork);
1012189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1013189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1014189ac973SJohn Baldwin 
1015189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1016189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1017189ac973SJohn Baldwin 
1018189ac973SJohn Baldwin 	/*
1019189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1020189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1021189ac973SJohn Baldwin 	 */
1022189ac973SJohn Baldwin 	wpid = wait(&status);
1023189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1024189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1025189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1026189ac973SJohn Baldwin 
1027189ac973SJohn Baldwin 	wpid = wait(&status);
1028189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1029189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1030189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1031189ac973SJohn Baldwin 
1032189ac973SJohn Baldwin 	wpid = wait(&status);
1033189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1034189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1035189ac973SJohn Baldwin }
1036189ac973SJohn Baldwin 
1037189ac973SJohn Baldwin /*
1038189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1039189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1040189ac973SJohn Baldwin  */
1041189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1042189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1043189ac973SJohn Baldwin {
1044189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1045189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1046189ac973SJohn Baldwin 	int status;
1047189ac973SJohn Baldwin 
1048189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1049189ac973SJohn Baldwin 	if (fpid == 0) {
1050189ac973SJohn Baldwin 		trace_me();
1051189ac973SJohn Baldwin 		follow_fork_parent(true);
1052189ac973SJohn Baldwin 	}
1053189ac973SJohn Baldwin 
1054189ac973SJohn Baldwin 	/* Parent process. */
1055189ac973SJohn Baldwin 	children[0] = fpid;
1056189ac973SJohn Baldwin 
1057189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1058189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1059189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1060189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1061189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1062189ac973SJohn Baldwin 
1063189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1064189ac973SJohn Baldwin 
1065189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1066189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1067189ac973SJohn Baldwin 
1068189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1069189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1070189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1071189ac973SJohn Baldwin 
1072189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1073189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1074189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork);
1075189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1076189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1077189ac973SJohn Baldwin 
1078189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1079189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1080189ac973SJohn Baldwin 
1081189ac973SJohn Baldwin 	/*
1082189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1083189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1084189ac973SJohn Baldwin 	 */
1085189ac973SJohn Baldwin 	wpid = wait(&status);
1086189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1087189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1088189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1089189ac973SJohn Baldwin 
1090189ac973SJohn Baldwin 	wpid = wait(&status);
1091189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1092189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1093189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1094189ac973SJohn Baldwin 
1095189ac973SJohn Baldwin 	wpid = wait(&status);
1096189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1097189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1098189ac973SJohn Baldwin }
1099189ac973SJohn Baldwin 
1100189ac973SJohn Baldwin static void *
1101189ac973SJohn Baldwin simple_thread(void *arg __unused)
1102189ac973SJohn Baldwin {
1103189ac973SJohn Baldwin 
1104189ac973SJohn Baldwin 	pthread_exit(NULL);
1105189ac973SJohn Baldwin }
1106189ac973SJohn Baldwin 
11075fcfab6eSJohn Baldwin static __dead2 void
11085fcfab6eSJohn Baldwin simple_thread_main(void)
11095fcfab6eSJohn Baldwin {
11105fcfab6eSJohn Baldwin 	pthread_t thread;
11115fcfab6eSJohn Baldwin 
11125fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, NULL) == 0);
11135fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_join(thread, NULL) == 0);
11145fcfab6eSJohn Baldwin 	exit(1);
11155fcfab6eSJohn Baldwin }
11165fcfab6eSJohn Baldwin 
1117189ac973SJohn Baldwin /*
1118189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1119189ac973SJohn Baldwin  * thread reports the correct value.
1120189ac973SJohn Baldwin  */
1121189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1122189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1123189ac973SJohn Baldwin {
1124189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1125189ac973SJohn Baldwin 	pid_t fpid, wpid;
1126e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1127189ac973SJohn Baldwin 	int status;
1128189ac973SJohn Baldwin 
1129189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1130189ac973SJohn Baldwin 	if (fpid == 0) {
1131189ac973SJohn Baldwin 		trace_me();
11325fcfab6eSJohn Baldwin 		simple_thread_main();
1133189ac973SJohn Baldwin 	}
1134189ac973SJohn Baldwin 
1135189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1136189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1137189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1138189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1139189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1140189ac973SJohn Baldwin 
1141189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1142189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1143e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1144189ac973SJohn Baldwin 
1145189ac973SJohn Baldwin 	/*
1146189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1147189ac973SJohn Baldwin 	 * system call exits.
1148189ac973SJohn Baldwin 	 */
1149189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1150189ac973SJohn Baldwin 
1151189ac973SJohn Baldwin 	/*
1152189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1153189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1154189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1155189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1156189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1157189ac973SJohn Baldwin 	 */
1158189ac973SJohn Baldwin 	for (;;) {
1159189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1160189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1161189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1162189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1163189ac973SJohn Baldwin 
1164189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1165189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1166189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1167189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1168e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1169189ac973SJohn Baldwin 			/* New thread seen. */
1170189ac973SJohn Baldwin 			break;
1171189ac973SJohn Baldwin 
1172189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1173189ac973SJohn Baldwin 	}
1174189ac973SJohn Baldwin 
1175189ac973SJohn Baldwin 	/* Wait for the child to exit. */
1176189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1177189ac973SJohn Baldwin 	for (;;) {
1178189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1179189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1180189ac973SJohn Baldwin 		if (WIFEXITED(status))
1181189ac973SJohn Baldwin 			break;
1182189ac973SJohn Baldwin 
1183189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1184189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1185189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1186189ac973SJohn Baldwin 	}
1187189ac973SJohn Baldwin 
1188189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1189189ac973SJohn Baldwin 
1190189ac973SJohn Baldwin 	wpid = wait(&status);
1191189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1192189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1193189ac973SJohn Baldwin }
1194189ac973SJohn Baldwin 
11955fcfab6eSJohn Baldwin /*
11965fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
11975fcfab6eSJohn Baldwin  */
11985fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
11995fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
12005fcfab6eSJohn Baldwin {
12015fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
12025fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
12035fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
12045fcfab6eSJohn Baldwin 	int status;
12055fcfab6eSJohn Baldwin 
12065fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
12075fcfab6eSJohn Baldwin 	if (fpid == 0) {
12085fcfab6eSJohn Baldwin 		trace_me();
12095fcfab6eSJohn Baldwin 		simple_thread_main();
12105fcfab6eSJohn Baldwin 	}
12115fcfab6eSJohn Baldwin 
12125fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
12135fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12145fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12155fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12165fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
12175fcfab6eSJohn Baldwin 
12185fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
12195fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
12205fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
12215fcfab6eSJohn Baldwin 
12225fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
12235fcfab6eSJohn Baldwin 
12245fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
12255fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12265fcfab6eSJohn Baldwin 
12275fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
12285fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12295fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12305fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12315fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
12325fcfab6eSJohn Baldwin 
12335fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
12345fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
12355fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
12365fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
12375fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
12385fcfab6eSJohn Baldwin 
12395fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12405fcfab6eSJohn Baldwin 
12415fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
12425fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12435fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12445fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12455fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
12465fcfab6eSJohn Baldwin 
12475fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
12485fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
12495fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
12505fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
12515fcfab6eSJohn Baldwin 
12525fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12535fcfab6eSJohn Baldwin 
12545fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
12555fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12565fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
12575fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
12585fcfab6eSJohn Baldwin 
12595fcfab6eSJohn Baldwin 	wpid = wait(&status);
12605fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
12615fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
12625fcfab6eSJohn Baldwin }
12635fcfab6eSJohn Baldwin 
12645fcfab6eSJohn Baldwin static void *
12655fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
12665fcfab6eSJohn Baldwin {
12675fcfab6eSJohn Baldwin 
12685fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
12695fcfab6eSJohn Baldwin 	exit(127);
12705fcfab6eSJohn Baldwin }
12715fcfab6eSJohn Baldwin 
12725fcfab6eSJohn Baldwin static __dead2 void
12735fcfab6eSJohn Baldwin exec_thread_main(void)
12745fcfab6eSJohn Baldwin {
12755fcfab6eSJohn Baldwin 	pthread_t thread;
12765fcfab6eSJohn Baldwin 
12775fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, exec_thread, NULL) == 0);
12785fcfab6eSJohn Baldwin 	for (;;)
12795fcfab6eSJohn Baldwin 		sleep(60);
12805fcfab6eSJohn Baldwin 	exit(1);
12815fcfab6eSJohn Baldwin }
12825fcfab6eSJohn Baldwin 
12835fcfab6eSJohn Baldwin /*
12845fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
12855fcfab6eSJohn Baldwin  * process that calls execve(2).
12865fcfab6eSJohn Baldwin  */
12875fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
12885fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
12895fcfab6eSJohn Baldwin {
12905fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
12915fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
12925fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
12935fcfab6eSJohn Baldwin 	int status;
12945fcfab6eSJohn Baldwin 
12955fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
12965fcfab6eSJohn Baldwin 	if (fpid == 0) {
12975fcfab6eSJohn Baldwin 		trace_me();
12985fcfab6eSJohn Baldwin 		exec_thread_main();
12995fcfab6eSJohn Baldwin 	}
13005fcfab6eSJohn Baldwin 
13015fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13025fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13035fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13045fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13055fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
13065fcfab6eSJohn Baldwin 
13075fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13085fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13095fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13105fcfab6eSJohn Baldwin 
13115fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
13125fcfab6eSJohn Baldwin 
13135fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
13145fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13155fcfab6eSJohn Baldwin 
13165fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13175fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13185fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13195fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13205fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13215fcfab6eSJohn Baldwin 
13225fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13235fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
13245fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13255fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13265fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13275fcfab6eSJohn Baldwin 
13285fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13295fcfab6eSJohn Baldwin 
13305fcfab6eSJohn Baldwin 	/*
13315fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
13325fcfab6eSJohn Baldwin 	 * single threading from execve().
13335fcfab6eSJohn Baldwin 	 */
13345fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13355fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13365fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13375fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13385fcfab6eSJohn Baldwin 
13395fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13405fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
13415fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
13425fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[0]);
13435fcfab6eSJohn Baldwin 
13445fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13455fcfab6eSJohn Baldwin 
13465fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
13475fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13485fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13495fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13505fcfab6eSJohn Baldwin 
13515fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13525fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
13535fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
13545fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
13555fcfab6eSJohn Baldwin 
13565fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13575fcfab6eSJohn Baldwin 
13585fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13595fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13605fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
13615fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
13625fcfab6eSJohn Baldwin 
13635fcfab6eSJohn Baldwin 	wpid = wait(&status);
13645fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
13655fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
13665fcfab6eSJohn Baldwin }
13675fcfab6eSJohn Baldwin 
13683340c45bSJohn Baldwin static void
13693340c45bSJohn Baldwin handler(int sig __unused)
13703340c45bSJohn Baldwin {
13713340c45bSJohn Baldwin }
13723340c45bSJohn Baldwin 
13733340c45bSJohn Baldwin static void
13743340c45bSJohn Baldwin signal_main(void)
13753340c45bSJohn Baldwin {
13763340c45bSJohn Baldwin 
13773340c45bSJohn Baldwin 	signal(SIGINFO, handler);
13783340c45bSJohn Baldwin 	raise(SIGINFO);
13793340c45bSJohn Baldwin 	exit(0);
13803340c45bSJohn Baldwin }
13813340c45bSJohn Baldwin 
13823340c45bSJohn Baldwin /*
13833340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
13843340c45bSJohn Baldwin  */
13853340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
13863340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
13873340c45bSJohn Baldwin {
13883340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
13893340c45bSJohn Baldwin 	pid_t fpid, wpid;
13903340c45bSJohn Baldwin 	int status;
13913340c45bSJohn Baldwin 
13923340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13933340c45bSJohn Baldwin 	if (fpid == 0) {
13943340c45bSJohn Baldwin 		trace_me();
13953340c45bSJohn Baldwin 		signal_main();
13963340c45bSJohn Baldwin 	}
13973340c45bSJohn Baldwin 
13983340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13993340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14003340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14013340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14023340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14033340c45bSJohn Baldwin 
14043340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14053340c45bSJohn Baldwin 
14063340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
14073340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14083340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14093340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGINFO);
14103340c45bSJohn Baldwin 
14113340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14123340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_event == PL_EVENT_SIGNAL);
14133340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
14143340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == SI_LWP);
14153340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_pid == wpid);
14163340c45bSJohn Baldwin 
14173340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14183340c45bSJohn Baldwin 
14193340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
14203340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14213340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
14223340c45bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
14233340c45bSJohn Baldwin 
14243340c45bSJohn Baldwin 	wpid = wait(&status);
14253340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14263340c45bSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
14273340c45bSJohn Baldwin }
14283340c45bSJohn Baldwin 
14298d570f64SJohn Baldwin /*
14308d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
14318d570f64SJohn Baldwin  */
14328d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
14338d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
14348d570f64SJohn Baldwin {
14358d570f64SJohn Baldwin 	pid_t fpid, wpid;
14368d570f64SJohn Baldwin 	int events, status;
14378d570f64SJohn Baldwin 
14388d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14398d570f64SJohn Baldwin 	if (fpid == 0) {
14408d570f64SJohn Baldwin 		trace_me();
14418d570f64SJohn Baldwin 		exec_thread(NULL);
14428d570f64SJohn Baldwin 	}
14438d570f64SJohn Baldwin 
14448d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14458d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14468d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14478d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14488d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14498d570f64SJohn Baldwin 
14508d570f64SJohn Baldwin 	events = 0;
14518d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
14528d570f64SJohn Baldwin 	    sizeof(events)) == 0);
14538d570f64SJohn Baldwin 
14548d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14558d570f64SJohn Baldwin 
14568d570f64SJohn Baldwin 	/* Should get one event at exit. */
14578d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14588d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
14598d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
14608d570f64SJohn Baldwin 
14618d570f64SJohn Baldwin 	wpid = wait(&status);
14628d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14638d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
14648d570f64SJohn Baldwin }
14658d570f64SJohn Baldwin 
14668d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
14678d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
14688d570f64SJohn Baldwin {
14698d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
14708d570f64SJohn Baldwin 	pid_t fpid, wpid;
14718d570f64SJohn Baldwin 	int events, status;
14728d570f64SJohn Baldwin 
14738d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14748d570f64SJohn Baldwin 	if (fpid == 0) {
14758d570f64SJohn Baldwin 		trace_me();
14768d570f64SJohn Baldwin 		exec_thread(NULL);
14778d570f64SJohn Baldwin 	}
14788d570f64SJohn Baldwin 
14798d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14808d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14818d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14828d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14838d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14848d570f64SJohn Baldwin 
14858d570f64SJohn Baldwin 	events = PTRACE_EXEC;
14868d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
14878d570f64SJohn Baldwin 	    sizeof(events)) == 0);
14888d570f64SJohn Baldwin 
14898d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14908d570f64SJohn Baldwin 
14918d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
14928d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14938d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14948d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
14958d570f64SJohn Baldwin 
14968d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14978d570f64SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
14988d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
14998d570f64SJohn Baldwin 
15008d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15018d570f64SJohn Baldwin 
15028d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
15038d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15048d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15058d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15068d570f64SJohn Baldwin 
15078d570f64SJohn Baldwin 	wpid = wait(&status);
15088d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15098d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15108d570f64SJohn Baldwin }
15118d570f64SJohn Baldwin 
15128d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
15138d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
15148d570f64SJohn Baldwin {
15158d570f64SJohn Baldwin 	pid_t fpid, wpid;
15168d570f64SJohn Baldwin 	int events, status;
15178d570f64SJohn Baldwin 
15188d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15198d570f64SJohn Baldwin 	if (fpid == 0) {
15208d570f64SJohn Baldwin 		trace_me();
15218d570f64SJohn Baldwin 		exit(0);
15228d570f64SJohn Baldwin 	}
15238d570f64SJohn Baldwin 
15248d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15258d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15268d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15278d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15288d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15298d570f64SJohn Baldwin 
15308d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
15318d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
15328d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15338d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15348d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_FORK);
15358d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
15368d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15378d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15388d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_FORK));
15398d570f64SJohn Baldwin 
15408d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
15418d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
15428d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15438d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15448d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_LWP);
15458d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
15468d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15478d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15488d570f64SJohn Baldwin 	ATF_REQUIRE(!(events & PTRACE_LWP));
15498d570f64SJohn Baldwin 
15508d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15518d570f64SJohn Baldwin 
15528d570f64SJohn Baldwin 	/* Should get one event at exit. */
15538d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15548d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15558d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15568d570f64SJohn Baldwin 
15578d570f64SJohn Baldwin 	wpid = wait(&status);
15588d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15598d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15608d570f64SJohn Baldwin }
15618d570f64SJohn Baldwin 
1562fc4f075aSJohn Baldwin /*
1563fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1564fc4f075aSJohn Baldwin  */
1565fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
1566fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1567fc4f075aSJohn Baldwin {
1568fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1569fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1570fc4f075aSJohn Baldwin 	int events, status;
1571fc4f075aSJohn Baldwin 
1572fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1573fc4f075aSJohn Baldwin 	if (fpid == 0) {
1574fc4f075aSJohn Baldwin 		trace_me();
1575fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1576fc4f075aSJohn Baldwin 	}
1577fc4f075aSJohn Baldwin 
1578fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1579fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1580fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1581fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1582fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1583fc4f075aSJohn Baldwin 
1584fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1585fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1586fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1587fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1588fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1589fc4f075aSJohn Baldwin 
1590fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1591fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1592fc4f075aSJohn Baldwin 
1593fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1594fc4f075aSJohn Baldwin 	wpid = wait(&status);
1595fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1596fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1597fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1598fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1599fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1600fc4f075aSJohn Baldwin 
1601fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1602fc4f075aSJohn Baldwin 
1603fc4f075aSJohn Baldwin 	wpid = wait(&status);
1604fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1605fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1606fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1607fc4f075aSJohn Baldwin 
1608fc4f075aSJohn Baldwin 	wpid = wait(&status);
1609fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1610fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1611fc4f075aSJohn Baldwin }
1612fc4f075aSJohn Baldwin 
1613fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
1614fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1615fc4f075aSJohn Baldwin {
1616fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1617fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1618fc4f075aSJohn Baldwin 	int events, status;
1619fc4f075aSJohn Baldwin 
1620fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1621fc4f075aSJohn Baldwin 	if (fpid == 0) {
1622fc4f075aSJohn Baldwin 		trace_me();
1623fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1624fc4f075aSJohn Baldwin 	}
1625fc4f075aSJohn Baldwin 
1626fc4f075aSJohn Baldwin 	/* Parent process. */
1627fc4f075aSJohn Baldwin 	children[0] = fpid;
1628fc4f075aSJohn Baldwin 
1629fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1630fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1631fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1632fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1633fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1634fc4f075aSJohn Baldwin 
1635fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1636fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1637fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1638fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1639fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1640fc4f075aSJohn Baldwin 
1641fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1642fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1643fc4f075aSJohn Baldwin 
1644fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1645fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1646fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1647fc4f075aSJohn Baldwin 
1648fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1649fc4f075aSJohn Baldwin 
1650fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1651fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1652fc4f075aSJohn Baldwin 
1653fc4f075aSJohn Baldwin 	/*
1654fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1655fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1656fc4f075aSJohn Baldwin 	 */
1657fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
1658fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1659fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1660fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1661fc4f075aSJohn Baldwin 
1662fc4f075aSJohn Baldwin 	/*
1663fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1664fc4f075aSJohn Baldwin 	 * exits.
1665fc4f075aSJohn Baldwin 	 */
1666fc4f075aSJohn Baldwin 	wpid = wait(&status);
1667fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1668fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1669fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1670fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1671fc4f075aSJohn Baldwin 	    -1);
1672fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1673fc4f075aSJohn Baldwin 
1674fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1675fc4f075aSJohn Baldwin 
1676fc4f075aSJohn Baldwin 	wpid = wait(&status);
1677fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1678fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1679fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1680fc4f075aSJohn Baldwin 
1681fc4f075aSJohn Baldwin 	wpid = wait(&status);
1682fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1683fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1684fc4f075aSJohn Baldwin }
1685fc4f075aSJohn Baldwin 
168682a4538fSEric Badger /*
1687e2ebfbbfSEric Badger  * XXX: There's nothing inherently platform specific about this test, however a
1688e2ebfbbfSEric Badger  * userspace visible breakpoint() is a prerequisite.
1689e2ebfbbfSEric Badger  */
1690e2ebfbbfSEric Badger  #if defined(__amd64__) || defined(__i386__) || defined(__sparc64__)
1691e2ebfbbfSEric Badger /*
169282a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
169382a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
169482a4538fSEric Badger  */
169582a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
169682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
169782a4538fSEric Badger {
169882a4538fSEric Badger 	pid_t fpid, wpid;
169982a4538fSEric Badger 	int status;
170082a4538fSEric Badger 
170182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
170282a4538fSEric Badger 	if (fpid == 0) {
170382a4538fSEric Badger 		trace_me();
17049e0d1159SEric Badger 		breakpoint();
170582a4538fSEric Badger 		exit(1);
170682a4538fSEric Badger 	}
170782a4538fSEric Badger 
170882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
170982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
171082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
171182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
171282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
171382a4538fSEric Badger 
171482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
171582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
171682a4538fSEric Badger 
171782a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
171882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
171982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
172082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
172182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
172282a4538fSEric Badger 
172382a4538fSEric Badger 	/* Kill the child process. */
172482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
172582a4538fSEric Badger 
172682a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
172782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
172882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
172982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
173082a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
173182a4538fSEric Badger 
173282a4538fSEric Badger 	wpid = wait(&status);
173382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
173482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
173582a4538fSEric Badger }
1736e2ebfbbfSEric Badger #endif /* defined(__amd64__) || defined(__i386__) || defined(__sparc64__) */
173782a4538fSEric Badger 
173882a4538fSEric Badger /*
173982a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
174082a4538fSEric Badger  * process exit when stopped inside of a system call.
174182a4538fSEric Badger  */
174282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
174382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
174482a4538fSEric Badger {
174582a4538fSEric Badger 	struct ptrace_lwpinfo pl;
174682a4538fSEric Badger 	pid_t fpid, wpid;
174782a4538fSEric Badger 	int status;
174882a4538fSEric Badger 
174982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
175082a4538fSEric Badger 	if (fpid == 0) {
175182a4538fSEric Badger 		trace_me();
175282a4538fSEric Badger 		getpid();
175382a4538fSEric Badger 		exit(1);
175482a4538fSEric Badger 	}
175582a4538fSEric Badger 
175682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
175782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
175882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
175982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
176082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
176182a4538fSEric Badger 
176282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
176382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
176482a4538fSEric Badger 
176582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
176682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
176782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
176882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
176982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
177082a4538fSEric Badger 
177182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
177282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
177382a4538fSEric Badger 
177482a4538fSEric Badger 	/* Kill the child process. */
177582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
177682a4538fSEric Badger 
177782a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
177882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
177982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
178082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
178182a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
178282a4538fSEric Badger 
178382a4538fSEric Badger 	wpid = wait(&status);
178482a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
178582a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
178682a4538fSEric Badger }
178782a4538fSEric Badger 
178882a4538fSEric Badger /*
178982a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
179082a4538fSEric Badger  * process exit when killing a multithreaded process.
179182a4538fSEric Badger  */
179282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
179382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
179482a4538fSEric Badger {
179582a4538fSEric Badger 	struct ptrace_lwpinfo pl;
179682a4538fSEric Badger 	pid_t fpid, wpid;
179782a4538fSEric Badger 	lwpid_t main_lwp;
179882a4538fSEric Badger 	int status;
179982a4538fSEric Badger 
180082a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
180182a4538fSEric Badger 	if (fpid == 0) {
180282a4538fSEric Badger 		trace_me();
180382a4538fSEric Badger 		simple_thread_main();
180482a4538fSEric Badger 	}
180582a4538fSEric Badger 
180682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
180782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
180882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
180982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
181082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
181182a4538fSEric Badger 
181282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
181382a4538fSEric Badger 	    sizeof(pl)) != -1);
181482a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
181582a4538fSEric Badger 
181682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
181782a4538fSEric Badger 
181882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
181982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
182082a4538fSEric Badger 
182182a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
182282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
182382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
182482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
182582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
182682a4538fSEric Badger 
182782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
182882a4538fSEric Badger 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
182982a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
183082a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
183182a4538fSEric Badger 
183282a4538fSEric Badger 	/* Kill the child process. */
183382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
183482a4538fSEric Badger 
183582a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
183682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
183782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
183882a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
183982a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
184082a4538fSEric Badger 
184182a4538fSEric Badger 	wpid = wait(&status);
184282a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
184382a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
184482a4538fSEric Badger }
184582a4538fSEric Badger 
184682a4538fSEric Badger static void *
184782a4538fSEric Badger mask_usr1_thread(void *arg)
184882a4538fSEric Badger {
184982a4538fSEric Badger 	pthread_barrier_t *pbarrier;
185082a4538fSEric Badger 	sigset_t sigmask;
185182a4538fSEric Badger 
185282a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
185382a4538fSEric Badger 
185482a4538fSEric Badger 	sigemptyset(&sigmask);
185582a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
185682a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
185782a4538fSEric Badger 
185882a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
185982a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
186082a4538fSEric Badger 
186182a4538fSEric Badger 	for (;;)
186282a4538fSEric Badger 		sleep(60);
186382a4538fSEric Badger 
186482a4538fSEric Badger 	return (NULL);
186582a4538fSEric Badger }
186682a4538fSEric Badger 
186782a4538fSEric Badger /*
186882a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
186982a4538fSEric Badger  * and prevents spurious stops due to those other signals.
187082a4538fSEric Badger  */
18713cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal);
18723cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
18733cf56bb4SEnji Cooper {
18743cf56bb4SEnji Cooper 
18753cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
18763cf56bb4SEnji Cooper }
187782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
187882a4538fSEric Badger {
187982a4538fSEric Badger 	pid_t fpid, wpid;
188082a4538fSEric Badger 	int status;
188182a4538fSEric Badger 	cpuset_t setmask;
188282a4538fSEric Badger 	pthread_t t;
188382a4538fSEric Badger 	pthread_barrier_t barrier;
1884bc2be1d3SEric Badger 	struct sched_param sched_param;
188582a4538fSEric Badger 
188682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
188782a4538fSEric Badger 	if (fpid == 0) {
1888bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
188982a4538fSEric Badger 		CPU_ZERO(&setmask);
189082a4538fSEric Badger 		CPU_SET(0, &setmask);
189182a4538fSEric Badger 		cpusetid_t setid;
189282a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
189382a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
189482a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
189582a4538fSEric Badger 
189682a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
189782a4538fSEric Badger 
189882a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
189982a4538fSEric Badger 		    (void*)&barrier) == 0);
190082a4538fSEric Badger 
1901bc2be1d3SEric Badger 		/*
1902bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
1903bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
1904bc2be1d3SEric Badger 		 * thread runs first.
1905bc2be1d3SEric Badger 		 */
1906bc2be1d3SEric Badger 		sched_param.sched_priority =
1907bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
1908bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
1909bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
1910bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
1911bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
1912bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
1913bc2be1d3SEric Badger 		    &sched_param) == 0);
1914bc2be1d3SEric Badger 
191582a4538fSEric Badger 		sigset_t sigmask;
191682a4538fSEric Badger 		sigemptyset(&sigmask);
191782a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
191882a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
191982a4538fSEric Badger 
192082a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
192182a4538fSEric Badger 		pthread_barrier_wait(&barrier);
192282a4538fSEric Badger 
192382a4538fSEric Badger 		trace_me();
192482a4538fSEric Badger 
192582a4538fSEric Badger 		for (;;)
192682a4538fSEric Badger 			sleep(60);
192782a4538fSEric Badger 
192882a4538fSEric Badger 		exit(1);
192982a4538fSEric Badger 	}
193082a4538fSEric Badger 
193182a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
193282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
193382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
193482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
193582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
193682a4538fSEric Badger 
193782a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
193882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
193982a4538fSEric Badger 
194082a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
194182a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
194282a4538fSEric Badger 
194382a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
194482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
194582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
194682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
194782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
194882a4538fSEric Badger 
194982a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
195082a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
195182a4538fSEric Badger 
195282a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
195382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
195482a4538fSEric Badger 
195582a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
195682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
195782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
195882a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
195982a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
196082a4538fSEric Badger 
196182a4538fSEric Badger 	wpid = wait(&status);
196282a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
196382a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
196482a4538fSEric Badger }
196582a4538fSEric Badger 
196682a4538fSEric Badger /*
196782a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
196882a4538fSEric Badger  * and prevents spurious stops caused by those events.
196982a4538fSEric Badger  */
19703cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop);
19713cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc)
19723cf56bb4SEnji Cooper {
19733cf56bb4SEnji Cooper 
19743cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
19753cf56bb4SEnji Cooper }
197682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
197782a4538fSEric Badger {
197882a4538fSEric Badger 	pid_t fpid, wpid;
1979bc2be1d3SEric Badger 	int status;
198082a4538fSEric Badger 	cpuset_t setmask;
198182a4538fSEric Badger 	pthread_t t;
198282a4538fSEric Badger 	pthread_barrier_t barrier;
198382a4538fSEric Badger 	lwpid_t main_lwp;
198482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
1985bc2be1d3SEric Badger 	struct sched_param sched_param;
198682a4538fSEric Badger 
198782a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
198882a4538fSEric Badger 	if (fpid == 0) {
198982a4538fSEric Badger 		trace_me();
199082a4538fSEric Badger 
1991bc2be1d3SEric Badger 		/* Bind to one CPU so only one thread at a time will run. */
199282a4538fSEric Badger 		CPU_ZERO(&setmask);
199382a4538fSEric Badger 		CPU_SET(0, &setmask);
199482a4538fSEric Badger 		cpusetid_t setid;
199582a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
199682a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
199782a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
199882a4538fSEric Badger 
199982a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
200082a4538fSEric Badger 
200182a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
200282a4538fSEric Badger 		    (void*)&barrier) == 0);
200382a4538fSEric Badger 
2004bc2be1d3SEric Badger 		/*
2005bc2be1d3SEric Badger 		 * Give the main thread higher priority. The test always
2006bc2be1d3SEric Badger 		 * assumes that, if both threads are able to run, the main
2007bc2be1d3SEric Badger 		 * thread runs first.
2008bc2be1d3SEric Badger 		 */
2009bc2be1d3SEric Badger 		sched_param.sched_priority =
2010bc2be1d3SEric Badger 		    (sched_get_priority_max(SCHED_FIFO) +
2011bc2be1d3SEric Badger 		    sched_get_priority_min(SCHED_FIFO)) / 2;
2012bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
2013bc2be1d3SEric Badger 		    SCHED_FIFO, &sched_param) == 0);
2014bc2be1d3SEric Badger 		sched_param.sched_priority -= RQ_PPQ;
2015bc2be1d3SEric Badger 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
2016bc2be1d3SEric Badger 		    &sched_param) == 0);
2017bc2be1d3SEric Badger 
201882a4538fSEric Badger 		sigset_t sigmask;
201982a4538fSEric Badger 		sigemptyset(&sigmask);
202082a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
202182a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
202282a4538fSEric Badger 
202382a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
202482a4538fSEric Badger 		pthread_barrier_wait(&barrier);
202582a4538fSEric Badger 
202682a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
202782a4538fSEric Badger 		raise(SIGSTOP);
202882a4538fSEric Badger 
202982a4538fSEric Badger 		getpid();
203082a4538fSEric Badger 		exit(1);
203182a4538fSEric Badger 	}
203282a4538fSEric Badger 
203382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
203482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
203582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
203682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
203782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
203882a4538fSEric Badger 
203982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
204082a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
204182a4538fSEric Badger 
204282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
204382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
204482a4538fSEric Badger 
204582a4538fSEric Badger 	/*
204682a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
204782a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
204882a4538fSEric Badger 	 */
204982a4538fSEric Badger 	for (;;) {
205082a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
205182a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
205282a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
205382a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
205482a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
205582a4538fSEric Badger 			    sizeof(pl)) != -1);
205682a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
205782a4538fSEric Badger 		} else {
205882a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
205982a4538fSEric Badger 			break;
206082a4538fSEric Badger 		}
206182a4538fSEric Badger 		ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
206282a4538fSEric Badger 	}
206382a4538fSEric Badger 
2064bc2be1d3SEric Badger 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
206582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
206682a4538fSEric Badger 
206782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
206882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
206982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
207082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
207182a4538fSEric Badger 
207282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
207382a4538fSEric Badger 	    sizeof(pl)) != -1);
2074bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid == main_lwp);
207582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
2076bc2be1d3SEric Badger 	/* Prevent the main thread from hitting its syscall exit for now. */
207782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0);
207882a4538fSEric Badger 
2079bc2be1d3SEric Badger 	/*
2080bc2be1d3SEric Badger 	 * Proceed, allowing second thread to hit syscall exit for
2081bc2be1d3SEric Badger 	 * pthread_barrier_wait().
2082bc2be1d3SEric Badger 	 */
2083bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
2084bc2be1d3SEric Badger 
2085bc2be1d3SEric Badger 	wpid = waitpid(fpid, &status, 0);
2086bc2be1d3SEric Badger 	ATF_REQUIRE(wpid == fpid);
2087bc2be1d3SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2088bc2be1d3SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
2089bc2be1d3SEric Badger 
2090bc2be1d3SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
2091bc2be1d3SEric Badger 	    sizeof(pl)) != -1);
2092bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
2093bc2be1d3SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
209482a4538fSEric Badger 
209582a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
209682a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
209782a4538fSEric Badger 
209882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
209982a4538fSEric Badger 
2100bc2be1d3SEric Badger 	/* The next wait() should report the SIGUSR2. */
210182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
210282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
210382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
210482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
210582a4538fSEric Badger 
210682a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
210782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_RESUME, main_lwp, 0, 0) == 0);
210882a4538fSEric Badger 
210982a4538fSEric Badger 	/*
211082a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
2111bc2be1d3SEric Badger 	 * has been resumed. The second thread has taken a SIGUSR2 which will
2112bc2be1d3SEric Badger 	 * be replaced with a SIGKILL below. The main thread will get to run
2113bc2be1d3SEric Badger 	 * first. It should notice the kill request (even though the signal
2114bc2be1d3SEric Badger 	 * replacement occurred in the other thread) and exit accordingly.  It
2115bc2be1d3SEric Badger 	 * should not stop for the system call exit event.
211682a4538fSEric Badger 	 */
211782a4538fSEric Badger 
211882a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
211982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
212082a4538fSEric Badger 
212182a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
212282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
212382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
212482a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
212582a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
212682a4538fSEric Badger 
212782a4538fSEric Badger 	wpid = wait(&status);
212882a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
212982a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
213082a4538fSEric Badger }
213182a4538fSEric Badger 
213282a4538fSEric Badger static void
213382a4538fSEric Badger sigusr1_handler(int sig)
213482a4538fSEric Badger {
213582a4538fSEric Badger 
213682a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
213782a4538fSEric Badger 	_exit(2);
213882a4538fSEric Badger }
213982a4538fSEric Badger 
214082a4538fSEric Badger /*
214182a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
214282a4538fSEric Badger  * a PT_KILL will kill the process.
214382a4538fSEric Badger  */
214482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
214582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
214682a4538fSEric Badger {
214782a4538fSEric Badger 	pid_t fpid, wpid;
214882a4538fSEric Badger 	int status;
214982a4538fSEric Badger 	int max_pending_per_proc;
215082a4538fSEric Badger 	size_t len;
215182a4538fSEric Badger 	int i;
215282a4538fSEric Badger 
215382a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
215482a4538fSEric Badger 
215582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
215682a4538fSEric Badger 	if (fpid == 0) {
215782a4538fSEric Badger 		trace_me();
215882a4538fSEric Badger 		exit(1);
215982a4538fSEric Badger 	}
216082a4538fSEric Badger 
216182a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
216282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
216382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
216482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
216582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
216682a4538fSEric Badger 
216782a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
216882a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
216982a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
217082a4538fSEric Badger 
217182a4538fSEric Badger 	/* Fill the signal queue. */
217282a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
217382a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
217482a4538fSEric Badger 
217582a4538fSEric Badger 	/* Kill the child process. */
217682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
217782a4538fSEric Badger 
217882a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
217982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
218082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
218182a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
218282a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
218382a4538fSEric Badger 
218482a4538fSEric Badger 	wpid = wait(&status);
218582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
218682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
218782a4538fSEric Badger }
218882a4538fSEric Badger 
218982a4538fSEric Badger /*
219082a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
219182a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
219282a4538fSEric Badger  * call is complete.
219382a4538fSEric Badger  */
219482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
219582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
219682a4538fSEric Badger {
219782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
219882a4538fSEric Badger 	pid_t fpid, wpid;
219982a4538fSEric Badger 	int status;
220082a4538fSEric Badger 
220182a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
220282a4538fSEric Badger 
220382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
220482a4538fSEric Badger 	if (fpid == 0) {
220582a4538fSEric Badger 		trace_me();
220682a4538fSEric Badger 		getpid();
220782a4538fSEric Badger 		exit(1);
220882a4538fSEric Badger 	}
220982a4538fSEric Badger 
221082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
221182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
221282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
221382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
221482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
221582a4538fSEric Badger 
221682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
221782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
221882a4538fSEric Badger 
221982a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
222082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
222182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
222282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
222382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
222482a4538fSEric Badger 
222582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
222682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
222782a4538fSEric Badger 
222882a4538fSEric Badger 	/* Continue the child process with a signal. */
222982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
223082a4538fSEric Badger 
223182a4538fSEric Badger 	for (;;) {
223282a4538fSEric Badger 		/*
223382a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
223482a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
223582a4538fSEric Badger 		 * past any syscall stops.
223682a4538fSEric Badger 		 */
223782a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
223882a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
223982a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
224082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
224182a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
224282a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
224382a4538fSEric Badger 		} else {
224482a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
224582a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
224682a4538fSEric Badger 			break;
224782a4538fSEric Badger 		}
224882a4538fSEric Badger 	}
224982a4538fSEric Badger 
225082a4538fSEric Badger 	wpid = wait(&status);
225182a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
225282a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
225382a4538fSEric Badger }
225482a4538fSEric Badger 
225582a4538fSEric Badger static void
225682a4538fSEric Badger sigusr1_counting_handler(int sig)
225782a4538fSEric Badger {
225882a4538fSEric Badger 	static int counter = 0;
225982a4538fSEric Badger 
226082a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
226182a4538fSEric Badger 	counter++;
226282a4538fSEric Badger 	if (counter == 2)
226382a4538fSEric Badger 		_exit(2);
226482a4538fSEric Badger }
226582a4538fSEric Badger 
226682a4538fSEric Badger /*
226782a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
226882a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
226982a4538fSEric Badger  * the system call is complete.
227082a4538fSEric Badger  */
227182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
227282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
227382a4538fSEric Badger {
227482a4538fSEric Badger 	struct ptrace_lwpinfo pl;
227582a4538fSEric Badger 	pid_t fpid, wpid;
227682a4538fSEric Badger 	int status;
227782a4538fSEric Badger 
227882a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
227982a4538fSEric Badger 
228082a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
228182a4538fSEric Badger 	if (fpid == 0) {
228282a4538fSEric Badger 		trace_me();
228382a4538fSEric Badger 		getpid();
228482a4538fSEric Badger 		exit(1);
228582a4538fSEric Badger 	}
228682a4538fSEric Badger 
228782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
228882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
228982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
229082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
229182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
229282a4538fSEric Badger 
229382a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
229482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
229582a4538fSEric Badger 
229682a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
229782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
229882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
229982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
230082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
230182a4538fSEric Badger 
230282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
230382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
230482a4538fSEric Badger 
230582a4538fSEric Badger 	/* Continue the child process with a signal. */
230682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
230782a4538fSEric Badger 
230882a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
230982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
231082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
231182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
231282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
231382a4538fSEric Badger 
231482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
231582a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
231682a4538fSEric Badger 
231782a4538fSEric Badger 	/* Continue the child process with a signal. */
231882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
231982a4538fSEric Badger 
232082a4538fSEric Badger 	for (;;) {
232182a4538fSEric Badger 		/*
232282a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
232382a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
232482a4538fSEric Badger 		 * past any syscall stops.
232582a4538fSEric Badger 		 */
232682a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
232782a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
232882a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
232982a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
233082a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
233182a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
233282a4538fSEric Badger 		} else {
233382a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
233482a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
233582a4538fSEric Badger 			break;
233682a4538fSEric Badger 		}
233782a4538fSEric Badger 	}
233882a4538fSEric Badger 
233982a4538fSEric Badger 	wpid = wait(&status);
234082a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
234182a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
234282a4538fSEric Badger }
234382a4538fSEric Badger 
234482a4538fSEric Badger /*
234582a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
234682a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
234782a4538fSEric Badger  */
234882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
234982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
235082a4538fSEric Badger {
235182a4538fSEric Badger 	pid_t fpid, wpid;
235282a4538fSEric Badger 	int status;
235382a4538fSEric Badger 	int max_pending_per_proc;
235482a4538fSEric Badger 	size_t len;
235582a4538fSEric Badger 	int i;
235682a4538fSEric Badger 
235782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
235882a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
235982a4538fSEric Badger 
236082a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
236182a4538fSEric Badger 	if (fpid == 0) {
236282a4538fSEric Badger 		trace_me();
236382a4538fSEric Badger 		exit(1);
236482a4538fSEric Badger 	}
236582a4538fSEric Badger 
236682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
236782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
236882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
236982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
237082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
237182a4538fSEric Badger 
237282a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
237382a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
237482a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
237582a4538fSEric Badger 
237682a4538fSEric Badger 	/* Fill the signal queue. */
237782a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
237882a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
237982a4538fSEric Badger 
238082a4538fSEric Badger 	/* Continue with signal. */
238182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
238282a4538fSEric Badger 
238382a4538fSEric Badger 	for (;;) {
238482a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
238582a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
238682a4538fSEric Badger 		if (WIFSTOPPED(status)) {
238782a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
238882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
238982a4538fSEric Badger 		} else {
239082a4538fSEric Badger 			/*
239182a4538fSEric Badger 			 * The last wait() should report normal _exit from the
239282a4538fSEric Badger 			 * SIGUSR1 handler.
239382a4538fSEric Badger 			 */
239482a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
239582a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
239682a4538fSEric Badger 			break;
239782a4538fSEric Badger 		}
239882a4538fSEric Badger 	}
239982a4538fSEric Badger 
240082a4538fSEric Badger 	wpid = wait(&status);
240182a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
240282a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
240382a4538fSEric Badger }
240482a4538fSEric Badger 
2405*753e2922SBryan Drewery static sem_t sigusr1_sem;
2406*753e2922SBryan Drewery static int got_usr1;
2407*753e2922SBryan Drewery 
2408*753e2922SBryan Drewery static void
2409*753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused)
2410*753e2922SBryan Drewery {
2411*753e2922SBryan Drewery 
2412*753e2922SBryan Drewery 	got_usr1++;
2413*753e2922SBryan Drewery 	CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0);
2414*753e2922SBryan Drewery }
2415*753e2922SBryan Drewery 
2416*753e2922SBryan Drewery /*
2417*753e2922SBryan Drewery  * Verify that even if the signal queue is full for a child process,
2418*753e2922SBryan Drewery  * and the signal is masked, a PT_CONTINUE with a signal will not
2419*753e2922SBryan Drewery  * result in loss of that signal.
2420*753e2922SBryan Drewery  */
2421*753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
2422*753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
2423*753e2922SBryan Drewery {
2424*753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2425*753e2922SBryan Drewery 	pid_t fpid, wpid;
2426*753e2922SBryan Drewery 	int status, err;
2427*753e2922SBryan Drewery 	int max_pending_per_proc;
2428*753e2922SBryan Drewery 	size_t len;
2429*753e2922SBryan Drewery 	int i;
2430*753e2922SBryan Drewery 	sigset_t sigmask;
2431*753e2922SBryan Drewery 
2432*753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
2433*753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2434*753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2435*753e2922SBryan Drewery 
2436*753e2922SBryan Drewery 	got_usr1 = 0;
2437*753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2438*753e2922SBryan Drewery 	if (fpid == 0) {
2439*753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2440*753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2441*753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2442*753e2922SBryan Drewery 
2443*753e2922SBryan Drewery 		trace_me();
2444*753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2445*753e2922SBryan Drewery 
2446*753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2447*753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2448*753e2922SBryan Drewery 		/* Wait to receive the SIGUSR1. */
2449*753e2922SBryan Drewery 		do {
2450*753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2451*753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2452*753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2453*753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2454*753e2922SBryan Drewery 		exit(1);
2455*753e2922SBryan Drewery 	}
2456*753e2922SBryan Drewery 
2457*753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2458*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2459*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2460*753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2461*753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2462*753e2922SBryan Drewery 
2463*753e2922SBryan Drewery 	len = sizeof(max_pending_per_proc);
2464*753e2922SBryan Drewery 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
2465*753e2922SBryan Drewery 	    &max_pending_per_proc, &len, NULL, 0) == 0);
2466*753e2922SBryan Drewery 
2467*753e2922SBryan Drewery 	/* Fill the signal queue. */
2468*753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i)
2469*753e2922SBryan Drewery 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
2470*753e2922SBryan Drewery 
2471*753e2922SBryan Drewery 	/* Continue with signal. */
2472*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2473*753e2922SBryan Drewery 
2474*753e2922SBryan Drewery 	/* Collect and ignore all of the SIGUSR2. */
2475*753e2922SBryan Drewery 	for (i = 0; i < max_pending_per_proc; ++i) {
2476*753e2922SBryan Drewery 		wpid = waitpid(fpid, &status, 0);
2477*753e2922SBryan Drewery 		ATF_REQUIRE(wpid == fpid);
2478*753e2922SBryan Drewery 		ATF_REQUIRE(WIFSTOPPED(status));
2479*753e2922SBryan Drewery 		ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
2480*753e2922SBryan Drewery 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2481*753e2922SBryan Drewery 	}
2482*753e2922SBryan Drewery 
2483*753e2922SBryan Drewery 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
2484*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2485*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2486*753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2487*753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2488*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2489*753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2490*753e2922SBryan Drewery 
2491*753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
2492*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2493*753e2922SBryan Drewery 
2494*753e2922SBryan Drewery 	/* The last wait() should report exit after receiving SIGUSR1. */
2495*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2496*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2497*753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2498*753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2499*753e2922SBryan Drewery 
2500*753e2922SBryan Drewery 	wpid = wait(&status);
2501*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2502*753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2503*753e2922SBryan Drewery }
2504*753e2922SBryan Drewery 
250582a4538fSEric Badger /*
250682a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
250782a4538fSEric Badger  * replaced with another signal.
250882a4538fSEric Badger  */
250982a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
251082a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
251182a4538fSEric Badger {
251282a4538fSEric Badger 	struct ptrace_lwpinfo pl;
251382a4538fSEric Badger 	pid_t fpid, wpid;
251482a4538fSEric Badger 	int status;
251582a4538fSEric Badger 
251682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
251782a4538fSEric Badger 	if (fpid == 0) {
251882a4538fSEric Badger 		trace_me();
251982a4538fSEric Badger 		sleep(20);
252082a4538fSEric Badger 		exit(1);
252182a4538fSEric Badger 	}
252282a4538fSEric Badger 
252382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
252482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
252582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
252682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
252782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
252882a4538fSEric Badger 
252982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
253082a4538fSEric Badger 
253182a4538fSEric Badger 	/* Send a signal without ptrace. */
253282a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGINT) == 0);
253382a4538fSEric Badger 
253482a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
253582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
253682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
253782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
253882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGINT);
253982a4538fSEric Badger 
254082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
254182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
254282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGINT);
254382a4538fSEric Badger 
254482a4538fSEric Badger 	/* Continue the child process with a different signal. */
254582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM) == 0);
254682a4538fSEric Badger 
254782a4538fSEric Badger 	/*
254882a4538fSEric Badger 	 * The last wait() should report having died due to the new
254982a4538fSEric Badger 	 * signal, SIGTERM.
255082a4538fSEric Badger 	 */
255182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
255282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
255382a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
255482a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGTERM);
255582a4538fSEric Badger 
255682a4538fSEric Badger 	wpid = wait(&status);
255782a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
255882a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
255982a4538fSEric Badger }
256082a4538fSEric Badger 
256182a4538fSEric Badger /*
256282a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
256382a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
256482a4538fSEric Badger  * invented for e.g, system call stops.
256582a4538fSEric Badger  */
256682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
256782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
256882a4538fSEric Badger {
256982a4538fSEric Badger 	struct ptrace_lwpinfo pl;
2570fc1e29dcSBryan Drewery 	struct rlimit rl;
257182a4538fSEric Badger 	pid_t fpid, wpid;
257282a4538fSEric Badger 	int status;
257382a4538fSEric Badger 
257482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
257582a4538fSEric Badger 	if (fpid == 0) {
257682a4538fSEric Badger 		trace_me();
2577fc1e29dcSBryan Drewery 		/* SIGTRAP expected to cause exit on syscall entry. */
2578fc1e29dcSBryan Drewery 		rl.rlim_cur = rl.rlim_max = 0;
2579fc1e29dcSBryan Drewery 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0);
258082a4538fSEric Badger 		getpid();
258182a4538fSEric Badger 		exit(1);
258282a4538fSEric Badger 	}
258382a4538fSEric Badger 
258482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
258582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
258682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
258782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
258882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
258982a4538fSEric Badger 
259082a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
259182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
259282a4538fSEric Badger 
259382a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
259482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
259582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
259682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
259782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
259882a4538fSEric Badger 
259982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
260082a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
260182a4538fSEric Badger 
260282a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
260382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP) == 0);
260482a4538fSEric Badger 
260582a4538fSEric Badger 	for (;;) {
260682a4538fSEric Badger 		/*
260782a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
260882a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
260982a4538fSEric Badger 		 */
261082a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
261182a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
261282a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
261382a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
261482a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
261582a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
261682a4538fSEric Badger 		} else {
261782a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
261882a4538fSEric Badger 			ATF_REQUIRE(WTERMSIG(status) == SIGTRAP);
261982a4538fSEric Badger 			break;
262082a4538fSEric Badger 		}
262182a4538fSEric Badger 	}
262282a4538fSEric Badger 
262382a4538fSEric Badger 	wpid = wait(&status);
262482a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
262582a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
262682a4538fSEric Badger 
262782a4538fSEric Badger }
262882a4538fSEric Badger 
262982a4538fSEric Badger /*
263082a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
263182a4538fSEric Badger  */
263282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
263382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
263482a4538fSEric Badger {
263582a4538fSEric Badger 	struct ptrace_lwpinfo pl;
263682a4538fSEric Badger 	pid_t fpid, wpid;
263782a4538fSEric Badger 	int status;
263882a4538fSEric Badger 
263982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
264082a4538fSEric Badger 
264182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
264282a4538fSEric Badger 	if (fpid == 0) {
264382a4538fSEric Badger 		trace_me();
264482a4538fSEric Badger 		getpid();
264582a4538fSEric Badger 		exit(1);
264682a4538fSEric Badger 	}
264782a4538fSEric Badger 
264882a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
264982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
265082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
265182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
265282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
265382a4538fSEric Badger 
265482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
265582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
265682a4538fSEric Badger 
265782a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
265882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
265982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
266082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
266182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
266282a4538fSEric Badger 
266382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
266482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
266582a4538fSEric Badger 
266682a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
266782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
266882a4538fSEric Badger 
266982a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
267082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
267182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
267282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
267382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
267482a4538fSEric Badger 
267582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
267682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
267782a4538fSEric Badger 
267882a4538fSEric Badger 	/* Send an ABRT without ptrace. */
267982a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGABRT) == 0);
268082a4538fSEric Badger 
268182a4538fSEric Badger 	/* Continue normally. */
268282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
268382a4538fSEric Badger 
268482a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
268582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
268682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
268782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
268882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
268982a4538fSEric Badger 
269082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
269182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
269282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
269382a4538fSEric Badger 
269482a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
269582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
269682a4538fSEric Badger 
269782a4538fSEric Badger 	for (;;) {
269882a4538fSEric Badger 		/*
269982a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
270082a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
270182a4538fSEric Badger 		 * past any syscall stops.
270282a4538fSEric Badger 		 */
270382a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
270482a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
270582a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
270682a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
270782a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
270882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
270982a4538fSEric Badger 		} else {
271082a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
271182a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
271282a4538fSEric Badger 			break;
271382a4538fSEric Badger 		}
271482a4538fSEric Badger 	}
271582a4538fSEric Badger 
271682a4538fSEric Badger 	wpid = wait(&status);
271782a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
271882a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
271982a4538fSEric Badger 
272082a4538fSEric Badger }
272182a4538fSEric Badger 
272282a4538fSEric Badger /*
272382a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
272482a4538fSEric Badger  */
272582a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
272682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
272782a4538fSEric Badger {
272882a4538fSEric Badger 	pid_t fpid, wpid;
272982a4538fSEric Badger 	int status, kq, nevents;
273082a4538fSEric Badger 	struct kevent kev;
273182a4538fSEric Badger 
273282a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
273382a4538fSEric Badger 
273482a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
273582a4538fSEric Badger 	if (fpid == 0) {
273682a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
273782a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
273882a4538fSEric Badger 		CHILD_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0);
273982a4538fSEric Badger 
274082a4538fSEric Badger 		trace_me();
274182a4538fSEric Badger 
274282a4538fSEric Badger 		for (;;) {
274382a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
274482a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
274582a4538fSEric Badger 				continue;
274682a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
274782a4538fSEric Badger 			CHILD_REQUIRE(kev.filter == EVFILT_SIGNAL);
274882a4538fSEric Badger 			CHILD_REQUIRE(kev.ident == SIGUSR1);
274982a4538fSEric Badger 			break;
275082a4538fSEric Badger 		}
275182a4538fSEric Badger 
275282a4538fSEric Badger 		exit(1);
275382a4538fSEric Badger 	}
275482a4538fSEric Badger 
275582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
275682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
275782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
275882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
275982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
276082a4538fSEric Badger 
276182a4538fSEric Badger 	/* Continue with the SIGUSR1. */
276282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
276382a4538fSEric Badger 
276482a4538fSEric Badger 	/*
276582a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
276682a4538fSEric Badger 	 */
276782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
276882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
276982a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
277082a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
277182a4538fSEric Badger 
277282a4538fSEric Badger 	wpid = wait(&status);
277382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
277482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
277582a4538fSEric Badger }
277682a4538fSEric Badger 
277782a4538fSEric Badger static void *
277882a4538fSEric Badger signal_thread(void *arg)
277982a4538fSEric Badger {
278082a4538fSEric Badger 	int err;
278182a4538fSEric Badger 	sigset_t sigmask;
278282a4538fSEric Badger 
278382a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
278482a4538fSEric Badger 
278582a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
278682a4538fSEric Badger 	do {
278782a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
278882a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
278982a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
279082a4538fSEric Badger 
279182a4538fSEric Badger 	/* Free our companion thread from the barrier. */
279282a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
279382a4538fSEric Badger 
279482a4538fSEric Badger 	/*
279582a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
279682a4538fSEric Badger 	 * other thread.
279782a4538fSEric Badger 	 */
279882a4538fSEric Badger 	CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
279982a4538fSEric Badger 	CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
280082a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
280182a4538fSEric Badger 
280282a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
280382a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
280482a4538fSEric Badger 
280582a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
280682a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
280782a4538fSEric Badger 
280882a4538fSEric Badger 	return (NULL);
280982a4538fSEric Badger }
281082a4538fSEric Badger 
281182a4538fSEric Badger /*
2812*753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2813*753e2922SBryan Drewery  * signal from kill() once unmasked.
2814*753e2922SBryan Drewery  */
2815*753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
2816*753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
2817*753e2922SBryan Drewery {
2818*753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2819*753e2922SBryan Drewery 	pid_t fpid, wpid;
2820*753e2922SBryan Drewery 	int status, err;
2821*753e2922SBryan Drewery 	sigset_t sigmask;
2822*753e2922SBryan Drewery 
2823*753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2824*753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2825*753e2922SBryan Drewery 	got_usr1 = 0;
2826*753e2922SBryan Drewery 
2827*753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2828*753e2922SBryan Drewery 	if (fpid == 0) {
2829*753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2830*753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2831*753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2832*753e2922SBryan Drewery 
2833*753e2922SBryan Drewery 		trace_me();
2834*753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2835*753e2922SBryan Drewery 
2836*753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2837*753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2838*753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2839*753e2922SBryan Drewery 		do {
2840*753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2841*753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2842*753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2843*753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2844*753e2922SBryan Drewery 		exit(1);
2845*753e2922SBryan Drewery 	}
2846*753e2922SBryan Drewery 
2847*753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2848*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2849*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2850*753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2851*753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2852*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2853*753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
2854*753e2922SBryan Drewery 
2855*753e2922SBryan Drewery 	/* Send blocked SIGUSR1 which should cause a stop. */
2856*753e2922SBryan Drewery 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
2857*753e2922SBryan Drewery 
2858*753e2922SBryan Drewery 	/* Continue the child ignoring the SIGSTOP. */
2859*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2860*753e2922SBryan Drewery 
2861*753e2922SBryan Drewery 	/* The next wait() should report the kill(SIGUSR1) was received. */
2862*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2863*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2864*753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2865*753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2866*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2867*753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2868*753e2922SBryan Drewery 
2869*753e2922SBryan Drewery 	/* Continue the child, allowing in the SIGUSR1. */
2870*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2871*753e2922SBryan Drewery 
2872*753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
2873*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2874*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2875*753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2876*753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2877*753e2922SBryan Drewery 
2878*753e2922SBryan Drewery 	wpid = wait(&status);
2879*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2880*753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2881*753e2922SBryan Drewery }
2882*753e2922SBryan Drewery 
2883*753e2922SBryan Drewery /*
2884*753e2922SBryan Drewery  * Verify that a traced process with blocked signal received the
2885*753e2922SBryan Drewery  * signal from PT_CONTINUE once unmasked.
2886*753e2922SBryan Drewery  */
2887*753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
2888*753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
2889*753e2922SBryan Drewery {
2890*753e2922SBryan Drewery 	struct ptrace_lwpinfo pl;
2891*753e2922SBryan Drewery 	pid_t fpid, wpid;
2892*753e2922SBryan Drewery 	int status, err;
2893*753e2922SBryan Drewery 	sigset_t sigmask;
2894*753e2922SBryan Drewery 
2895*753e2922SBryan Drewery 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
2896*753e2922SBryan Drewery 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
2897*753e2922SBryan Drewery 	got_usr1 = 0;
2898*753e2922SBryan Drewery 
2899*753e2922SBryan Drewery 	ATF_REQUIRE((fpid = fork()) != -1);
2900*753e2922SBryan Drewery 	if (fpid == 0) {
2901*753e2922SBryan Drewery 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
2902*753e2922SBryan Drewery 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
2903*753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
2904*753e2922SBryan Drewery 
2905*753e2922SBryan Drewery 		trace_me();
2906*753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 0);
2907*753e2922SBryan Drewery 
2908*753e2922SBryan Drewery 		/* Allow the pending SIGUSR1 in now. */
2909*753e2922SBryan Drewery 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
2910*753e2922SBryan Drewery 		/* Wait to receive a SIGUSR1. */
2911*753e2922SBryan Drewery 		do {
2912*753e2922SBryan Drewery 			err = sem_wait(&sigusr1_sem);
2913*753e2922SBryan Drewery 			CHILD_REQUIRE(err == 0 || errno == EINTR);
2914*753e2922SBryan Drewery 		} while (err != 0 && errno == EINTR);
2915*753e2922SBryan Drewery 
2916*753e2922SBryan Drewery 		CHILD_REQUIRE(got_usr1 == 1);
2917*753e2922SBryan Drewery 		exit(1);
2918*753e2922SBryan Drewery 	}
2919*753e2922SBryan Drewery 
2920*753e2922SBryan Drewery 	/* The first wait() should report the stop from SIGSTOP. */
2921*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2922*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2923*753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2924*753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2925*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2926*753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
2927*753e2922SBryan Drewery 
2928*753e2922SBryan Drewery 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
2929*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
2930*753e2922SBryan Drewery 
2931*753e2922SBryan Drewery 	/* The next wait() should report the SIGUSR1 was received. */
2932*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2933*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2934*753e2922SBryan Drewery 	ATF_REQUIRE(WIFSTOPPED(status));
2935*753e2922SBryan Drewery 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
2936*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
2937*753e2922SBryan Drewery 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
2938*753e2922SBryan Drewery 
2939*753e2922SBryan Drewery 	/* Continue the child, ignoring the SIGUSR1. */
2940*753e2922SBryan Drewery 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2941*753e2922SBryan Drewery 
2942*753e2922SBryan Drewery 	/* The last wait() should report normal exit with code 1. */
2943*753e2922SBryan Drewery 	wpid = waitpid(fpid, &status, 0);
2944*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == fpid);
2945*753e2922SBryan Drewery 	ATF_REQUIRE(WIFEXITED(status));
2946*753e2922SBryan Drewery 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
2947*753e2922SBryan Drewery 
2948*753e2922SBryan Drewery 	wpid = wait(&status);
2949*753e2922SBryan Drewery 	ATF_REQUIRE(wpid == -1);
2950*753e2922SBryan Drewery 	ATF_REQUIRE(errno == ECHILD);
2951*753e2922SBryan Drewery }
2952*753e2922SBryan Drewery 
2953*753e2922SBryan Drewery /*
295482a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
295582a4538fSEric Badger  * a different signal that the new signal is routed to a thread
295682a4538fSEric Badger  * that can accept it, and that that thread is awakened by the signal
295782a4538fSEric Badger  * in a timely manner.
295882a4538fSEric Badger  */
295982a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
296082a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
296182a4538fSEric Badger {
296282a4538fSEric Badger 	pid_t fpid, wpid;
296382a4538fSEric Badger 	int status, err;
296482a4538fSEric Badger 	pthread_t t;
296582a4538fSEric Badger 	sigset_t sigmask;
296682a4538fSEric Badger 	pthread_barrier_t barrier;
296782a4538fSEric Badger 
296882a4538fSEric Badger 	ATF_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
296982a4538fSEric Badger 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
297082a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
297182a4538fSEric Badger 
297282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
297382a4538fSEric Badger 	if (fpid == 0) {
297482a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, signal_thread, (void*)&barrier) == 0);
297582a4538fSEric Badger 
297682a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
297782a4538fSEric Badger 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
297882a4538fSEric Badger 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
297982a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
298082a4538fSEric Badger 
298182a4538fSEric Badger 		trace_me();
298282a4538fSEric Badger 
298382a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
298482a4538fSEric Badger 		pthread_barrier_wait(&barrier);
298582a4538fSEric Badger 
298682a4538fSEric Badger 		/*
298782a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
298882a4538fSEric Badger 		 * thread.
298982a4538fSEric Badger 		 */
299082a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
299182a4538fSEric Badger 
299282a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
299382a4538fSEric Badger 		pthread_barrier_wait(&barrier);
299482a4538fSEric Badger 
299582a4538fSEric Badger 		/*
299682a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
299782a4538fSEric Badger 		 * now.
299882a4538fSEric Badger 		 */
299982a4538fSEric Badger 		raise(SIGSTOP);
300082a4538fSEric Badger 
300182a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
300282a4538fSEric Badger 		do {
300382a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
300482a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
300582a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
300682a4538fSEric Badger 
300782a4538fSEric Badger 		/* Free the other thread from the barrier. */
300882a4538fSEric Badger 		pthread_barrier_wait(&barrier);
300982a4538fSEric Badger 
301082a4538fSEric Badger 		CHILD_REQUIRE(pthread_join(t, NULL) == 0);
301182a4538fSEric Badger 
301282a4538fSEric Badger 		exit(1);
301382a4538fSEric Badger 	}
301482a4538fSEric Badger 
301582a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
301682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
301782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
301882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
301982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
302082a4538fSEric Badger 
302182a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
302282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
302382a4538fSEric Badger 
302482a4538fSEric Badger 	/*
302582a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
302682a4538fSEric Badger 	 * in this case).
302782a4538fSEric Badger 	 */
302882a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
302982a4538fSEric Badger 
303082a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
303182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
303282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
303382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
303482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
303582a4538fSEric Badger 
303682a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
303782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
303882a4538fSEric Badger 
303982a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
304082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
304182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
304282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
304382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
304482a4538fSEric Badger 
304582a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
304682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
304782a4538fSEric Badger 
304882a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
304982a4538fSEric Badger 
305082a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
305182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
305282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
305382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
305482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
305582a4538fSEric Badger 
305682a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
305782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
305882a4538fSEric Badger 
305982a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
306082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
306182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
306282a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
306382a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
306482a4538fSEric Badger 
306582a4538fSEric Badger 	wpid = wait(&status);
306682a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
306782a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
306882a4538fSEric Badger }
306982a4538fSEric Badger 
3070b38bd91fSEric Badger static void *
3071b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
3072b38bd91fSEric Badger {
3073b38bd91fSEric Badger 
3074b38bd91fSEric Badger 	raise(SIGSTOP);
3075b38bd91fSEric Badger 	return NULL;
3076b38bd91fSEric Badger }
3077b38bd91fSEric Badger 
3078b38bd91fSEric Badger static void *
3079b38bd91fSEric Badger sleep_thread(void *arg __unused)
3080b38bd91fSEric Badger {
3081b38bd91fSEric Badger 
3082b38bd91fSEric Badger 	sleep(60);
3083b38bd91fSEric Badger 	return NULL;
3084b38bd91fSEric Badger }
3085b38bd91fSEric Badger 
3086b38bd91fSEric Badger static void
3087b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
3088b38bd91fSEric Badger {
3089b38bd91fSEric Badger 	pid_t fpid, wpid;
3090b38bd91fSEric Badger 	int status, i;
3091b38bd91fSEric Badger 	cpuset_t setmask;
3092b38bd91fSEric Badger 	cpusetid_t setid;
3093b38bd91fSEric Badger 	pthread_t t;
3094b38bd91fSEric Badger 
3095b38bd91fSEric Badger 	/*
3096b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
3097b38bd91fSEric Badger 	 * that both child and grandchild have died.
3098b38bd91fSEric Badger 	 */
3099b38bd91fSEric Badger 	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
3100b38bd91fSEric Badger 
3101b38bd91fSEric Badger 	fpid = fork();
3102b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
3103b38bd91fSEric Badger 	if (fpid == 0) {
3104b38bd91fSEric Badger 		fpid = fork();
3105b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
3106b38bd91fSEric Badger 		if (fpid == 0) {
3107b38bd91fSEric Badger 			trace_me();
3108b38bd91fSEric Badger 
3109b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
3110b38bd91fSEric Badger 			CPU_ZERO(&setmask);
3111b38bd91fSEric Badger 			CPU_SET(0, &setmask);
3112b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset(&setid) == 0);
3113b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
3114b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
3115b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
3116b38bd91fSEric Badger 
3117b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
3118b38bd91fSEric Badger 				/*
3119b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
3120b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
3121b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
3122b38bd91fSEric Badger 				 * threads compete.
3123b38bd91fSEric Badger 				 */
3124b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3125b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
3126b38bd91fSEric Badger 				raise(SIGSTOP);
3127b38bd91fSEric Badger 			} else {
3128b38bd91fSEric Badger 				/*
3129b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
3130b38bd91fSEric Badger 				 * this thread. After creating the new thread,
3131b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
3132b38bd91fSEric Badger 				 * raise the SIGSTOP.
3133b38bd91fSEric Badger 				 */
3134b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
3135b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
3136b38bd91fSEric Badger 				sleep(60);
3137b38bd91fSEric Badger 			}
3138b38bd91fSEric Badger 
3139b38bd91fSEric Badger 			exit(0);
3140b38bd91fSEric Badger 		}
3141b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
3142b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3143b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
3144b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3145b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3146b38bd91fSEric Badger 
3147b38bd91fSEric Badger 		CHILD_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3148b38bd91fSEric Badger 
3149b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
3150b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
3151b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
3152b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
3153b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3154b38bd91fSEric Badger 
3155b38bd91fSEric Badger 		/*
3156b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
3157b38bd91fSEric Badger 		 * should be killed.
3158b38bd91fSEric Badger 		 */
3159b38bd91fSEric Badger 		exit(0);
3160b38bd91fSEric Badger 	}
3161b38bd91fSEric Badger 
3162b38bd91fSEric Badger 	/*
3163b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
3164b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
3165b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
3166b38bd91fSEric Badger 	 * left dangling when its parent died.
3167b38bd91fSEric Badger 	 */
3168b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
3169b38bd91fSEric Badger 		wpid = wait(&status);
3170b38bd91fSEric Badger 		if (wpid == fpid)
3171b38bd91fSEric Badger 			ATF_REQUIRE(WIFEXITED(status) &&
3172b38bd91fSEric Badger 			    WEXITSTATUS(status) == 0);
3173b38bd91fSEric Badger 		else
3174b38bd91fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status) &&
3175b38bd91fSEric Badger 			    WTERMSIG(status) == SIGKILL);
3176b38bd91fSEric Badger 	}
3177b38bd91fSEric Badger }
3178b38bd91fSEric Badger 
3179b38bd91fSEric Badger /*
3180b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
3181b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
3182b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
3183b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
3184b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
3185b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
3186b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
3187b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
3188b38bd91fSEric Badger  * past, so make no assumption.
3189b38bd91fSEric Badger  */
31903cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
31913cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
31923cf56bb4SEnji Cooper {
31933cf56bb4SEnji Cooper 
31943cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
31953cf56bb4SEnji Cooper }
3196b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
3197b38bd91fSEric Badger {
3198b38bd91fSEric Badger 
3199b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
3200b38bd91fSEric Badger }
32013cf56bb4SEnji Cooper 
32023cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
32033cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
32043cf56bb4SEnji Cooper {
32053cf56bb4SEnji Cooper 
32063cf56bb4SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
32073cf56bb4SEnji Cooper }
3208b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
3209b38bd91fSEric Badger {
3210b38bd91fSEric Badger 
3211b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
3212b38bd91fSEric Badger }
3213b38bd91fSEric Badger 
3214b4d33259SEric Badger /*
3215b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
3216b4d33259SEric Badger  * is not modified.
3217b4d33259SEric Badger  */
3218b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
3219b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
3220b4d33259SEric Badger {
3221b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
3222b4d33259SEric Badger 	pid_t fpid, wpid;
3223b4d33259SEric Badger 	int status, event_mask, new_event_mask;
3224b4d33259SEric Badger 
3225b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
3226b4d33259SEric Badger 	if (fpid == 0) {
3227b4d33259SEric Badger 		trace_me();
3228b4d33259SEric Badger 		raise(SIGSTOP);
3229b4d33259SEric Badger 		exit(0);
3230b4d33259SEric Badger 	}
3231b4d33259SEric Badger 
3232b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
3233b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3234b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3235b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3236b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3237b4d33259SEric Badger 
3238b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
3239b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
3240b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
3241b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
3242b4d33259SEric Badger 
3243b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
3244b4d33259SEric Badger 	ATF_REQUIRE(kill(fpid, SIGKILL) == 0);
3245b4d33259SEric Badger 
3246b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
3247b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3248b4d33259SEric Badger 
3249b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
3250b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3251b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3252b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3253b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGKILL);
3254b4d33259SEric Badger 
3255b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
3256b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
3257b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGKILL);
3258b4d33259SEric Badger 
3259b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
3260b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3261b4d33259SEric Badger 
3262b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
3263b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3264b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
3265b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
3266b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
3267b4d33259SEric Badger 
3268b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
3269b4d33259SEric Badger 	new_event_mask = 0;
3270b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
3271b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
3272b4d33259SEric Badger 	ATF_REQUIRE(event_mask == new_event_mask);
3273b4d33259SEric Badger 
3274b4d33259SEric Badger 	/* Continue the child to let it exit. */
3275b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
3276b4d33259SEric Badger 
3277b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
3278b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
3279b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
3280b4d33259SEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
3281b4d33259SEric Badger 
3282b4d33259SEric Badger 	wpid = wait(&status);
3283b4d33259SEric Badger 	ATF_REQUIRE(wpid == -1);
3284b4d33259SEric Badger 	ATF_REQUIRE(errno == ECHILD);
3285b4d33259SEric Badger }
3286b4d33259SEric Badger 
3287d74da94cSMark Johnston static void *
3288d74da94cSMark Johnston flock_thread(void *arg)
3289d74da94cSMark Johnston {
3290d74da94cSMark Johnston 	int fd;
3291d74da94cSMark Johnston 
3292d74da94cSMark Johnston 	fd = *(int *)arg;
3293d74da94cSMark Johnston 	(void)flock(fd, LOCK_EX);
3294d74da94cSMark Johnston 	(void)flock(fd, LOCK_UN);
3295d74da94cSMark Johnston 	return (NULL);
3296d74da94cSMark Johnston }
3297d74da94cSMark Johnston 
3298d74da94cSMark Johnston /*
3299d74da94cSMark Johnston  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
3300d74da94cSMark Johnston  * We rely on the fact that the lockf implementation sets SBDRY before blocking
3301d74da94cSMark Johnston  * on a lock. This is a regression test for r318191.
3302d74da94cSMark Johnston  */
3303d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
3304d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
3305d74da94cSMark Johnston {
3306d74da94cSMark Johnston 	pthread_barrier_t barrier;
3307d74da94cSMark Johnston 	pthread_barrierattr_t battr;
3308d74da94cSMark Johnston 	char tmpfile[64];
3309d74da94cSMark Johnston 	pid_t child, wpid;
3310d74da94cSMark Johnston 	int error, fd, i, status;
3311d74da94cSMark Johnston 
3312d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_init(&battr) == 0);
3313d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
3314d74da94cSMark Johnston 	    PTHREAD_PROCESS_SHARED) == 0);
3315d74da94cSMark Johnston 	ATF_REQUIRE(pthread_barrier_init(&barrier, &battr, 2) == 0);
3316d74da94cSMark Johnston 
3317d74da94cSMark Johnston 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
3318d74da94cSMark Johnston 	fd = mkstemp(tmpfile);
3319d74da94cSMark Johnston 	ATF_REQUIRE(fd >= 0);
3320d74da94cSMark Johnston 
3321d74da94cSMark Johnston 	ATF_REQUIRE((child = fork()) != -1);
3322d74da94cSMark Johnston 	if (child == 0) {
3323d74da94cSMark Johnston 		pthread_t t[2];
332496437391SBryan Drewery 		int cfd;
3325d74da94cSMark Johnston 
3326d74da94cSMark Johnston 		error = pthread_barrier_wait(&barrier);
3327d74da94cSMark Johnston 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
3328d74da94cSMark Johnston 			_exit(1);
3329d74da94cSMark Johnston 
3330d74da94cSMark Johnston 		cfd = open(tmpfile, O_RDONLY);
3331d74da94cSMark Johnston 		if (cfd < 0)
3332d74da94cSMark Johnston 			_exit(1);
3333d74da94cSMark Johnston 
3334d74da94cSMark Johnston 		/*
3335d74da94cSMark Johnston 		 * We want at least two threads blocked on the file lock since
3336d74da94cSMark Johnston 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
3337d74da94cSMark Johnston 		 * sleep.
3338d74da94cSMark Johnston 		 */
3339d74da94cSMark Johnston 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
3340d74da94cSMark Johnston 			_exit(1);
3341d74da94cSMark Johnston 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
3342d74da94cSMark Johnston 			_exit(1);
3343d74da94cSMark Johnston 		if (pthread_join(t[0], NULL) != 0)
3344d74da94cSMark Johnston 			_exit(1);
3345d74da94cSMark Johnston 		if (pthread_join(t[1], NULL) != 0)
3346d74da94cSMark Johnston 			_exit(1);
3347d74da94cSMark Johnston 		_exit(0);
3348d74da94cSMark Johnston 	}
3349d74da94cSMark Johnston 
3350d74da94cSMark Johnston 	ATF_REQUIRE(flock(fd, LOCK_EX) == 0);
3351d74da94cSMark Johnston 
3352d74da94cSMark Johnston 	error = pthread_barrier_wait(&barrier);
3353d74da94cSMark Johnston 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
3354d74da94cSMark Johnston 
3355d74da94cSMark Johnston 	/*
3356d74da94cSMark Johnston 	 * Give the child some time to block. Is there a better way to do this?
3357d74da94cSMark Johnston 	 */
3358d74da94cSMark Johnston 	sleep(1);
3359d74da94cSMark Johnston 
3360d74da94cSMark Johnston 	/*
3361d74da94cSMark Johnston 	 * Attach and give the child 3 seconds to stop.
3362d74da94cSMark Johnston 	 */
3363d74da94cSMark Johnston 	ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0);
3364d74da94cSMark Johnston 	for (i = 0; i < 3; i++) {
3365d74da94cSMark Johnston 		wpid = waitpid(child, &status, WNOHANG);
3366d74da94cSMark Johnston 		if (wpid == child && WIFSTOPPED(status) &&
3367d74da94cSMark Johnston 		    WSTOPSIG(status) == SIGSTOP)
3368d74da94cSMark Johnston 			break;
3369d74da94cSMark Johnston 		sleep(1);
3370d74da94cSMark Johnston 	}
3371d74da94cSMark Johnston 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
3372d74da94cSMark Johnston 
3373d74da94cSMark Johnston 	ATF_REQUIRE(ptrace(PT_DETACH, child, NULL, 0) == 0);
3374d74da94cSMark Johnston 
3375d74da94cSMark Johnston 	ATF_REQUIRE(flock(fd, LOCK_UN) == 0);
3376d74da94cSMark Johnston 	ATF_REQUIRE(unlink(tmpfile) == 0);
3377d74da94cSMark Johnston 	ATF_REQUIRE(close(fd) == 0);
3378d74da94cSMark Johnston }
3379d74da94cSMark Johnston 
3380c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
3381c209e3e2SJohn Baldwin {
3382c209e3e2SJohn Baldwin 
3383c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
3384c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
338557c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
338657c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
338798685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
338898685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
338998685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
339098685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
339198685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
339298685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
339398685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
339498685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
3395368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
3396189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
3397189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
3398189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
33995fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
34005fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
34013340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
34028d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
34038d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
34048d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
3405fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
3406fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
3407e2ebfbbfSEric Badger #if defined(__amd64__) || defined(__i386__) || defined(__sparc64__)
340882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
3409e2ebfbbfSEric Badger #endif
341082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
341182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
341282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
341382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
341482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
341582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
341682a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
341782a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
341882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
3419*753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
342082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
342182a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
342282a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
342382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
3424*753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
3425*753e2922SBryan Drewery 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
342682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
3427b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
3428b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
3429b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
3430d74da94cSMark Johnston 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
3431c209e3e2SJohn Baldwin 
3432c209e3e2SJohn Baldwin 	return (atf_no_error());
3433c209e3e2SJohn Baldwin }
3434