xref: /freebsd/tests/sys/kern/ptrace_test.c (revision b4d332597538b5a130b3351cf7f1e6acfeec4c84)
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>
3382a4538fSEric Badger #include <sys/time.h>
34b38bd91fSEric Badger #include <sys/procctl.h>
35c209e3e2SJohn Baldwin #include <sys/ptrace.h>
36189ac973SJohn Baldwin #include <sys/syscall.h>
3757c74f5bSJohn Baldwin #include <sys/sysctl.h>
3857c74f5bSJohn Baldwin #include <sys/user.h>
39c209e3e2SJohn Baldwin #include <sys/wait.h>
40c209e3e2SJohn Baldwin #include <errno.h>
419e0d1159SEric Badger #include <machine/cpufunc.h>
42189ac973SJohn Baldwin #include <pthread.h>
4382a4538fSEric Badger #include <semaphore.h>
44c209e3e2SJohn Baldwin #include <signal.h>
45dfa8ba12SJohn Baldwin #include <stdio.h>
46c209e3e2SJohn Baldwin #include <stdlib.h>
47c209e3e2SJohn Baldwin #include <unistd.h>
48c209e3e2SJohn Baldwin #include <atf-c.h>
49c209e3e2SJohn Baldwin 
50c209e3e2SJohn Baldwin /*
51dfa8ba12SJohn Baldwin  * A variant of ATF_REQUIRE that is suitable for use in child
52dfa8ba12SJohn Baldwin  * processes.  This only works if the parent process is tripped up by
53dfa8ba12SJohn Baldwin  * the early exit and fails some requirement itself.
54dfa8ba12SJohn Baldwin  */
55dfa8ba12SJohn Baldwin #define	CHILD_REQUIRE(exp) do {						\
56dfa8ba12SJohn Baldwin 		if (!(exp))						\
57dfa8ba12SJohn Baldwin 			child_fail_require(__FILE__, __LINE__,		\
58dfa8ba12SJohn Baldwin 			    #exp " not met");				\
59dfa8ba12SJohn Baldwin 	} while (0)
60dfa8ba12SJohn Baldwin 
6198685dc8SJohn Baldwin static __dead2 void
62dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str)
63dfa8ba12SJohn Baldwin {
64dfa8ba12SJohn Baldwin 	char buf[128];
65dfa8ba12SJohn Baldwin 
66dfa8ba12SJohn Baldwin 	snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str);
67dfa8ba12SJohn Baldwin 	write(2, buf, strlen(buf));
68dfa8ba12SJohn Baldwin 	_exit(32);
69dfa8ba12SJohn Baldwin }
70dfa8ba12SJohn Baldwin 
7198685dc8SJohn Baldwin static void
7298685dc8SJohn Baldwin trace_me(void)
7398685dc8SJohn Baldwin {
7498685dc8SJohn Baldwin 
7598685dc8SJohn Baldwin 	/* Attach the parent process as a tracer of this process. */
7698685dc8SJohn Baldwin 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7798685dc8SJohn Baldwin 
7898685dc8SJohn Baldwin 	/* Trigger a stop. */
7998685dc8SJohn Baldwin 	raise(SIGSTOP);
8098685dc8SJohn Baldwin }
8198685dc8SJohn Baldwin 
8298685dc8SJohn Baldwin static void
8398685dc8SJohn Baldwin attach_child(pid_t pid)
8498685dc8SJohn Baldwin {
8598685dc8SJohn Baldwin 	pid_t wpid;
8698685dc8SJohn Baldwin 	int status;
8798685dc8SJohn Baldwin 
8898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
8998685dc8SJohn Baldwin 
9098685dc8SJohn Baldwin 	wpid = waitpid(pid, &status, 0);
9198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == pid);
9298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
9398685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
9498685dc8SJohn Baldwin }
9598685dc8SJohn Baldwin 
9698685dc8SJohn Baldwin static void
9798685dc8SJohn Baldwin wait_for_zombie(pid_t pid)
9898685dc8SJohn Baldwin {
9998685dc8SJohn Baldwin 
10098685dc8SJohn Baldwin 	/*
10198685dc8SJohn Baldwin 	 * Wait for a process to exit.  This is kind of gross, but
10298685dc8SJohn Baldwin 	 * there is not a better way.
10398685dc8SJohn Baldwin 	 */
10498685dc8SJohn Baldwin 	for (;;) {
10598685dc8SJohn Baldwin 		struct kinfo_proc kp;
10698685dc8SJohn Baldwin 		size_t len;
10798685dc8SJohn Baldwin 		int mib[4];
10898685dc8SJohn Baldwin 
10998685dc8SJohn Baldwin 		mib[0] = CTL_KERN;
11098685dc8SJohn Baldwin 		mib[1] = KERN_PROC;
11198685dc8SJohn Baldwin 		mib[2] = KERN_PROC_PID;
11298685dc8SJohn Baldwin 		mib[3] = pid;
11398685dc8SJohn Baldwin 		len = sizeof(kp);
11498685dc8SJohn Baldwin 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
11598685dc8SJohn Baldwin 			/* The KERN_PROC_PID sysctl fails for zombies. */
11698685dc8SJohn Baldwin 			ATF_REQUIRE(errno == ESRCH);
11798685dc8SJohn Baldwin 			break;
11898685dc8SJohn Baldwin 		}
11998685dc8SJohn Baldwin 		usleep(5000);
12098685dc8SJohn Baldwin 	}
12198685dc8SJohn Baldwin }
12298685dc8SJohn Baldwin 
123dfa8ba12SJohn Baldwin /*
124c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
125c209e3e2SJohn Baldwin  * process exactly once when attached via PT_TRACE_ME.
126c209e3e2SJohn Baldwin  */
127c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
128c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
129c209e3e2SJohn Baldwin {
130c209e3e2SJohn Baldwin 	pid_t child, wpid;
131c209e3e2SJohn Baldwin 	int status;
132c209e3e2SJohn Baldwin 
133c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
134c209e3e2SJohn Baldwin 	if (child == 0) {
135c209e3e2SJohn Baldwin 		/* Child process. */
13698685dc8SJohn Baldwin 		trace_me();
137c209e3e2SJohn Baldwin 
138b98cb919SJohn Baldwin 		_exit(1);
139c209e3e2SJohn Baldwin 	}
140c209e3e2SJohn Baldwin 
141c209e3e2SJohn Baldwin 	/* Parent process. */
142c209e3e2SJohn Baldwin 
143c209e3e2SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
144c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
145c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
146c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
147c209e3e2SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
148c209e3e2SJohn Baldwin 
149c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
150c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
151c209e3e2SJohn Baldwin 
152c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
153c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
154c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
155c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
156c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
157c209e3e2SJohn Baldwin 
158c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
159c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
160c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
161c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
162c209e3e2SJohn Baldwin }
163c209e3e2SJohn Baldwin 
164c209e3e2SJohn Baldwin /*
165c209e3e2SJohn Baldwin  * Verify that a parent debugger process "sees" the exit of a debugged
166c209e3e2SJohn Baldwin  * process exactly once when attached via PT_ATTACH.
167c209e3e2SJohn Baldwin  */
168c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
169c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
170c209e3e2SJohn Baldwin {
171c209e3e2SJohn Baldwin 	pid_t child, wpid;
172c209e3e2SJohn Baldwin 	int cpipe[2], status;
173c209e3e2SJohn Baldwin 	char c;
174c209e3e2SJohn Baldwin 
175c209e3e2SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
176c209e3e2SJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
177c209e3e2SJohn Baldwin 	if (child == 0) {
178c209e3e2SJohn Baldwin 		/* Child process. */
179c209e3e2SJohn Baldwin 		close(cpipe[0]);
180c209e3e2SJohn Baldwin 
181c209e3e2SJohn Baldwin 		/* Wait for the parent to attach. */
182dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0);
183c209e3e2SJohn Baldwin 
184b98cb919SJohn Baldwin 		_exit(1);
185c209e3e2SJohn Baldwin 	}
186c209e3e2SJohn Baldwin 	close(cpipe[1]);
187c209e3e2SJohn Baldwin 
188c209e3e2SJohn Baldwin 	/* Parent process. */
189c209e3e2SJohn Baldwin 
190c209e3e2SJohn Baldwin 	/* Attach to the child process. */
19198685dc8SJohn Baldwin 	attach_child(child);
192c209e3e2SJohn Baldwin 
193c209e3e2SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
194c209e3e2SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
195c209e3e2SJohn Baldwin 
196c209e3e2SJohn Baldwin 	/* Signal the child to exit. */
197c209e3e2SJohn Baldwin 	close(cpipe[0]);
198c209e3e2SJohn Baldwin 
199c209e3e2SJohn Baldwin 	/* The second wait() should report the exit status. */
200c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
201c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == child);
202c209e3e2SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
203c209e3e2SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
204c209e3e2SJohn Baldwin 
205c209e3e2SJohn Baldwin 	/* The child should no longer exist. */
206c209e3e2SJohn Baldwin 	wpid = waitpid(child, &status, 0);
207c209e3e2SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
208c209e3e2SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
209c209e3e2SJohn Baldwin }
210c209e3e2SJohn Baldwin 
21157c74f5bSJohn Baldwin /*
21257c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process only
21357c74f5bSJohn Baldwin  * after the debugger has seen it.
21457c74f5bSJohn Baldwin  */
21557c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
21657c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
21757c74f5bSJohn Baldwin {
21857c74f5bSJohn Baldwin 	pid_t child, debugger, wpid;
21957c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
22057c74f5bSJohn Baldwin 	char c;
22157c74f5bSJohn Baldwin 
22257c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
22357c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
22457c74f5bSJohn Baldwin 
22557c74f5bSJohn Baldwin 	if (child == 0) {
22657c74f5bSJohn Baldwin 		/* Child process. */
22757c74f5bSJohn Baldwin 		close(cpipe[0]);
22857c74f5bSJohn Baldwin 
22957c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
230dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
23157c74f5bSJohn Baldwin 
232b98cb919SJohn Baldwin 		_exit(1);
23357c74f5bSJohn Baldwin 	}
23457c74f5bSJohn Baldwin 	close(cpipe[1]);
23557c74f5bSJohn Baldwin 
23657c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
23757c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
23857c74f5bSJohn Baldwin 
23957c74f5bSJohn Baldwin 	if (debugger == 0) {
24057c74f5bSJohn Baldwin 		/* Debugger process. */
24157c74f5bSJohn Baldwin 		close(dpipe[0]);
24257c74f5bSJohn Baldwin 
243dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
24457c74f5bSJohn Baldwin 
24557c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
246dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
247dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
248dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
24957c74f5bSJohn Baldwin 
250dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
25157c74f5bSJohn Baldwin 
25257c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
253dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
25457c74f5bSJohn Baldwin 
25557c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
256dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0);
25757c74f5bSJohn Baldwin 
25857c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
259dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
260dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
261dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
26257c74f5bSJohn Baldwin 
263b98cb919SJohn Baldwin 		_exit(0);
26457c74f5bSJohn Baldwin 	}
26557c74f5bSJohn Baldwin 	close(dpipe[1]);
26657c74f5bSJohn Baldwin 
26757c74f5bSJohn Baldwin 	/* Parent process. */
26857c74f5bSJohn Baldwin 
26957c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
27057c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
27157c74f5bSJohn Baldwin 
27257c74f5bSJohn Baldwin 	/* Release the child. */
27357c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
27457c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
27557c74f5bSJohn Baldwin 	close(cpipe[0]);
27657c74f5bSJohn Baldwin 
27798685dc8SJohn Baldwin 	wait_for_zombie(child);
27857c74f5bSJohn Baldwin 
27957c74f5bSJohn Baldwin 	/*
2802f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
2812f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
2822f021998SJohn Baldwin 	 * until the debugger sees the exit.
28357c74f5bSJohn Baldwin 	 */
28457c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
28557c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
28657c74f5bSJohn Baldwin 
28757c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
28857c74f5bSJohn Baldwin 	close(dpipe[0]);
28957c74f5bSJohn Baldwin 
29057c74f5bSJohn Baldwin 	/* Wait for the debugger. */
29157c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
29257c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
29357c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
29457c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
29557c74f5bSJohn Baldwin 
29657c74f5bSJohn Baldwin 	/* The child process should now be ready. */
29757c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
29857c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
29957c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
30057c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
30157c74f5bSJohn Baldwin }
30257c74f5bSJohn Baldwin 
30357c74f5bSJohn Baldwin /*
30457c74f5bSJohn Baldwin  * Verify that a parent process "sees" the exit of a debugged process
30557c74f5bSJohn Baldwin  * only after a non-direct-child debugger has seen it.  In particular,
30657c74f5bSJohn Baldwin  * various wait() calls in the parent must avoid failing with ESRCH by
30757c74f5bSJohn Baldwin  * checking the parent's orphan list for the debugee.
30857c74f5bSJohn Baldwin  */
30957c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
31057c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
31157c74f5bSJohn Baldwin {
31257c74f5bSJohn Baldwin 	pid_t child, debugger, fpid, wpid;
31357c74f5bSJohn Baldwin 	int cpipe[2], dpipe[2], status;
31457c74f5bSJohn Baldwin 	char c;
31557c74f5bSJohn Baldwin 
31657c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
31757c74f5bSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
31857c74f5bSJohn Baldwin 
31957c74f5bSJohn Baldwin 	if (child == 0) {
32057c74f5bSJohn Baldwin 		/* Child process. */
32157c74f5bSJohn Baldwin 		close(cpipe[0]);
32257c74f5bSJohn Baldwin 
32357c74f5bSJohn Baldwin 		/* Wait for parent to be ready. */
324dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
32557c74f5bSJohn Baldwin 
326b98cb919SJohn Baldwin 		_exit(1);
32757c74f5bSJohn Baldwin 	}
32857c74f5bSJohn Baldwin 	close(cpipe[1]);
32957c74f5bSJohn Baldwin 
33057c74f5bSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
33157c74f5bSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
33257c74f5bSJohn Baldwin 
33357c74f5bSJohn Baldwin 	if (debugger == 0) {
33457c74f5bSJohn Baldwin 		/* Debugger parent. */
33557c74f5bSJohn Baldwin 
33657c74f5bSJohn Baldwin 		/*
33757c74f5bSJohn Baldwin 		 * Fork again and drop the debugger parent so that the
33857c74f5bSJohn Baldwin 		 * debugger is not a child of the main parent.
33957c74f5bSJohn Baldwin 		 */
340dfa8ba12SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
34157c74f5bSJohn Baldwin 		if (fpid != 0)
342b98cb919SJohn Baldwin 			_exit(2);
34357c74f5bSJohn Baldwin 
34457c74f5bSJohn Baldwin 		/* Debugger process. */
34557c74f5bSJohn Baldwin 		close(dpipe[0]);
34657c74f5bSJohn Baldwin 
347dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
34857c74f5bSJohn Baldwin 
34957c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
350dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
351dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
352dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
35357c74f5bSJohn Baldwin 
354dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
35557c74f5bSJohn Baldwin 
35657c74f5bSJohn Baldwin 		/* Signal parent that debugger is attached. */
357dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
35857c74f5bSJohn Baldwin 
35957c74f5bSJohn Baldwin 		/* Wait for parent's failed wait. */
360dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c));
36157c74f5bSJohn Baldwin 
36257c74f5bSJohn Baldwin 		wpid = waitpid(child, &status, 0);
363dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(wpid == child);
364dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
365dfa8ba12SJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
36657c74f5bSJohn Baldwin 
367b98cb919SJohn Baldwin 		_exit(0);
36857c74f5bSJohn Baldwin 	}
369eddb85c6SJohn Baldwin 	close(dpipe[1]);
37057c74f5bSJohn Baldwin 
37157c74f5bSJohn Baldwin 	/* Parent process. */
37257c74f5bSJohn Baldwin 
37357c74f5bSJohn Baldwin 	/* Wait for the debugger parent process to exit. */
37457c74f5bSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
37557c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
37657c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
37757c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
37857c74f5bSJohn Baldwin 
37957c74f5bSJohn Baldwin 	/* A WNOHANG wait here should see the non-exited child. */
38057c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
38157c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
38257c74f5bSJohn Baldwin 
38357c74f5bSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
38457c74f5bSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
38557c74f5bSJohn Baldwin 
38657c74f5bSJohn Baldwin 	/* Release the child. */
38757c74f5bSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
38857c74f5bSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
38957c74f5bSJohn Baldwin 	close(cpipe[0]);
39057c74f5bSJohn Baldwin 
39198685dc8SJohn Baldwin 	wait_for_zombie(child);
39257c74f5bSJohn Baldwin 
39357c74f5bSJohn Baldwin 	/*
3942f021998SJohn Baldwin 	 * This wait should return a pid of 0 to indicate no status to
3952f021998SJohn Baldwin 	 * report.  The parent should see the child as non-exited
3962f021998SJohn Baldwin 	 * until the debugger sees the exit.
39757c74f5bSJohn Baldwin 	 */
39857c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
39957c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == 0);
40057c74f5bSJohn Baldwin 
40157c74f5bSJohn Baldwin 	/* Signal the debugger to wait for the child. */
402eddb85c6SJohn Baldwin 	ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c));
40357c74f5bSJohn Baldwin 
40457c74f5bSJohn Baldwin 	/* Wait for the debugger. */
405eddb85c6SJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0);
406eddb85c6SJohn Baldwin 	close(dpipe[0]);
40757c74f5bSJohn Baldwin 
40857c74f5bSJohn Baldwin 	/* The child process should now be ready. */
40957c74f5bSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
41057c74f5bSJohn Baldwin 	ATF_REQUIRE(wpid == child);
41157c74f5bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
41257c74f5bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
41357c74f5bSJohn Baldwin }
41457c74f5bSJohn Baldwin 
41598685dc8SJohn Baldwin /*
41698685dc8SJohn Baldwin  * The parent process should always act the same regardless of how the
41798685dc8SJohn Baldwin  * debugger is attached to it.
41898685dc8SJohn Baldwin  */
41998685dc8SJohn Baldwin static __dead2 void
420189ac973SJohn Baldwin follow_fork_parent(bool use_vfork)
42198685dc8SJohn Baldwin {
42298685dc8SJohn Baldwin 	pid_t fpid, wpid;
42398685dc8SJohn Baldwin 	int status;
42498685dc8SJohn Baldwin 
425189ac973SJohn Baldwin 	if (use_vfork)
426189ac973SJohn Baldwin 		CHILD_REQUIRE((fpid = vfork()) != -1);
427189ac973SJohn Baldwin 	else
42898685dc8SJohn Baldwin 		CHILD_REQUIRE((fpid = fork()) != -1);
42998685dc8SJohn Baldwin 
43098685dc8SJohn Baldwin 	if (fpid == 0)
43198685dc8SJohn Baldwin 		/* Child */
432b98cb919SJohn Baldwin 		_exit(2);
43398685dc8SJohn Baldwin 
43498685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
43598685dc8SJohn Baldwin 	CHILD_REQUIRE(wpid == fpid);
43698685dc8SJohn Baldwin 	CHILD_REQUIRE(WIFEXITED(status));
43798685dc8SJohn Baldwin 	CHILD_REQUIRE(WEXITSTATUS(status) == 2);
43898685dc8SJohn Baldwin 
439b98cb919SJohn Baldwin 	_exit(1);
44098685dc8SJohn Baldwin }
44198685dc8SJohn Baldwin 
44298685dc8SJohn Baldwin /*
44398685dc8SJohn Baldwin  * Helper routine for follow fork tests.  This waits for two stops
44498685dc8SJohn Baldwin  * that report both "sides" of a fork.  It returns the pid of the new
44598685dc8SJohn Baldwin  * child process.
44698685dc8SJohn Baldwin  */
44798685dc8SJohn Baldwin static pid_t
448189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
44998685dc8SJohn Baldwin {
45098685dc8SJohn Baldwin 	struct ptrace_lwpinfo pl;
45198685dc8SJohn Baldwin 	bool fork_reported[2];
45298685dc8SJohn Baldwin 	pid_t child, wpid;
45398685dc8SJohn Baldwin 	int i, status;
45498685dc8SJohn Baldwin 
45598685dc8SJohn Baldwin 	fork_reported[0] = false;
45698685dc8SJohn Baldwin 	fork_reported[1] = false;
45798685dc8SJohn Baldwin 	child = -1;
45898685dc8SJohn Baldwin 
45998685dc8SJohn Baldwin 	/*
46098685dc8SJohn Baldwin 	 * Each process should report a fork event.  The parent should
46198685dc8SJohn Baldwin 	 * report a PL_FLAG_FORKED event, and the child should report
46298685dc8SJohn Baldwin 	 * a PL_FLAG_CHILD event.
46398685dc8SJohn Baldwin 	 */
46498685dc8SJohn Baldwin 	for (i = 0; i < 2; i++) {
46598685dc8SJohn Baldwin 		wpid = wait(&status);
46698685dc8SJohn Baldwin 		ATF_REQUIRE(wpid > 0);
46798685dc8SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
46898685dc8SJohn Baldwin 
46998685dc8SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
47098685dc8SJohn Baldwin 		    sizeof(pl)) != -1);
47198685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
47298685dc8SJohn Baldwin 		    0);
47398685dc8SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
47498685dc8SJohn Baldwin 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
47598685dc8SJohn Baldwin 		if (pl.pl_flags & PL_FLAG_CHILD) {
47698685dc8SJohn Baldwin 			ATF_REQUIRE(wpid != parent);
47798685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
47898685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[1]);
47998685dc8SJohn Baldwin 			if (child == -1)
48098685dc8SJohn Baldwin 				child = wpid;
48198685dc8SJohn Baldwin 			else
48298685dc8SJohn Baldwin 				ATF_REQUIRE(child == wpid);
483189ac973SJohn Baldwin 			if (ppl != NULL)
484189ac973SJohn Baldwin 				ppl[1] = pl;
48598685dc8SJohn Baldwin 			fork_reported[1] = true;
48698685dc8SJohn Baldwin 		} else {
48798685dc8SJohn Baldwin 			ATF_REQUIRE(wpid == parent);
48898685dc8SJohn Baldwin 			ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
48998685dc8SJohn Baldwin 			ATF_REQUIRE(!fork_reported[0]);
49098685dc8SJohn Baldwin 			if (child == -1)
49198685dc8SJohn Baldwin 				child = pl.pl_child_pid;
49298685dc8SJohn Baldwin 			else
49398685dc8SJohn Baldwin 				ATF_REQUIRE(child == pl.pl_child_pid);
494189ac973SJohn Baldwin 			if (ppl != NULL)
495189ac973SJohn Baldwin 				ppl[0] = pl;
49698685dc8SJohn Baldwin 			fork_reported[0] = true;
49798685dc8SJohn Baldwin 		}
49898685dc8SJohn Baldwin 	}
49998685dc8SJohn Baldwin 
50098685dc8SJohn Baldwin 	return (child);
50198685dc8SJohn Baldwin }
50298685dc8SJohn Baldwin 
50398685dc8SJohn Baldwin /*
50498685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
50598685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
50698685dc8SJohn Baldwin  * when both processes remain attached to the debugger.
50798685dc8SJohn Baldwin  */
50898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
50998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
51098685dc8SJohn Baldwin {
511479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
51298685dc8SJohn Baldwin 	int status;
51398685dc8SJohn Baldwin 
51498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
51598685dc8SJohn Baldwin 	if (fpid == 0) {
51698685dc8SJohn Baldwin 		trace_me();
517189ac973SJohn Baldwin 		follow_fork_parent(false);
51898685dc8SJohn Baldwin 	}
51998685dc8SJohn Baldwin 
52098685dc8SJohn Baldwin 	/* Parent process. */
52198685dc8SJohn Baldwin 	children[0] = fpid;
52298685dc8SJohn Baldwin 
52398685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
52498685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
52598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
52698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
52798685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
52898685dc8SJohn Baldwin 
52998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
53098685dc8SJohn Baldwin 
53198685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
53298685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
53398685dc8SJohn Baldwin 
534189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
53598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
53698685dc8SJohn Baldwin 
53798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
53898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
53998685dc8SJohn Baldwin 
54098685dc8SJohn Baldwin 	/*
54198685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
54298685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
54398685dc8SJohn Baldwin 	 */
54498685dc8SJohn Baldwin 	wpid = wait(&status);
54598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
54698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
54798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
54898685dc8SJohn Baldwin 
54998685dc8SJohn Baldwin 	wpid = wait(&status);
55098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
55198685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
55298685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
55398685dc8SJohn Baldwin 
55498685dc8SJohn Baldwin 	wpid = wait(&status);
55598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
55698685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
55798685dc8SJohn Baldwin }
55898685dc8SJohn Baldwin 
55998685dc8SJohn Baldwin /*
56098685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
56198685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
56298685dc8SJohn Baldwin  * child process is detached after it reports its fork.
56398685dc8SJohn Baldwin  */
56498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
56598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
56698685dc8SJohn Baldwin {
567479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
56898685dc8SJohn Baldwin 	int status;
56998685dc8SJohn Baldwin 
57098685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
57198685dc8SJohn Baldwin 	if (fpid == 0) {
57298685dc8SJohn Baldwin 		trace_me();
573189ac973SJohn Baldwin 		follow_fork_parent(false);
57498685dc8SJohn Baldwin 	}
57598685dc8SJohn Baldwin 
57698685dc8SJohn Baldwin 	/* Parent process. */
57798685dc8SJohn Baldwin 	children[0] = fpid;
57898685dc8SJohn Baldwin 
57998685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
58098685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
58198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
58298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
58398685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
58498685dc8SJohn Baldwin 
58598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
58698685dc8SJohn Baldwin 
58798685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
58898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
58998685dc8SJohn Baldwin 
590189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
59198685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
59298685dc8SJohn Baldwin 
59398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
59498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
59598685dc8SJohn Baldwin 
59698685dc8SJohn Baldwin 	/*
59798685dc8SJohn Baldwin 	 * Should not see any status from the grandchild now, only the
59898685dc8SJohn Baldwin 	 * child.
59998685dc8SJohn Baldwin 	 */
60098685dc8SJohn Baldwin 	wpid = wait(&status);
60198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
60298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
60398685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
60498685dc8SJohn Baldwin 
60598685dc8SJohn Baldwin 	wpid = wait(&status);
60698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
60798685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
60898685dc8SJohn Baldwin }
60998685dc8SJohn Baldwin 
61098685dc8SJohn Baldwin /*
61198685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
61298685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
61398685dc8SJohn Baldwin  * traced parent is detached after the fork.
61498685dc8SJohn Baldwin  */
61598685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
61698685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
61798685dc8SJohn Baldwin {
618479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
61998685dc8SJohn Baldwin 	int status;
62098685dc8SJohn Baldwin 
62198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
62298685dc8SJohn Baldwin 	if (fpid == 0) {
62398685dc8SJohn Baldwin 		trace_me();
624189ac973SJohn Baldwin 		follow_fork_parent(false);
62598685dc8SJohn Baldwin 	}
62698685dc8SJohn Baldwin 
62798685dc8SJohn Baldwin 	/* Parent process. */
62898685dc8SJohn Baldwin 	children[0] = fpid;
62998685dc8SJohn Baldwin 
63098685dc8SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
63198685dc8SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
63298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
63398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
63498685dc8SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
63598685dc8SJohn Baldwin 
63698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
63798685dc8SJohn Baldwin 
63898685dc8SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
63998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
64098685dc8SJohn Baldwin 
641189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
64298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
64398685dc8SJohn Baldwin 
64498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
64598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
64698685dc8SJohn Baldwin 
64798685dc8SJohn Baldwin 	/*
64898685dc8SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
64998685dc8SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
65098685dc8SJohn Baldwin 	 *
65198685dc8SJohn Baldwin 	 * Even though the child process is detached, it is still a
65298685dc8SJohn Baldwin 	 * child of the debugger, so it will still report it's exit
65398685dc8SJohn Baldwin 	 * after the grandchild.
65498685dc8SJohn Baldwin 	 */
65598685dc8SJohn Baldwin 	wpid = wait(&status);
65698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
65798685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
65898685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
65998685dc8SJohn Baldwin 
66098685dc8SJohn Baldwin 	wpid = wait(&status);
66198685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
66298685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
66398685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
66498685dc8SJohn Baldwin 
66598685dc8SJohn Baldwin 	wpid = wait(&status);
66698685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
66798685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
66898685dc8SJohn Baldwin }
66998685dc8SJohn Baldwin 
67098685dc8SJohn Baldwin static void
67198685dc8SJohn Baldwin attach_fork_parent(int cpipe[2])
67298685dc8SJohn Baldwin {
67398685dc8SJohn Baldwin 	pid_t fpid;
67498685dc8SJohn Baldwin 
67598685dc8SJohn Baldwin 	close(cpipe[0]);
67698685dc8SJohn Baldwin 
67798685dc8SJohn Baldwin 	/* Double-fork to disassociate from the debugger. */
67898685dc8SJohn Baldwin 	CHILD_REQUIRE((fpid = fork()) != -1);
67998685dc8SJohn Baldwin 	if (fpid != 0)
680b98cb919SJohn Baldwin 		_exit(3);
68198685dc8SJohn Baldwin 
68298685dc8SJohn Baldwin 	/* Send the pid of the disassociated child to the debugger. */
68398685dc8SJohn Baldwin 	fpid = getpid();
68498685dc8SJohn Baldwin 	CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
68598685dc8SJohn Baldwin 
68698685dc8SJohn Baldwin 	/* Wait for the debugger to attach. */
68798685dc8SJohn Baldwin 	CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
68898685dc8SJohn Baldwin }
68998685dc8SJohn Baldwin 
69098685dc8SJohn Baldwin /*
69198685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork and
69298685dc8SJohn Baldwin  * that the traced parent sees the exit of the child after the debugger
69398685dc8SJohn Baldwin  * when both processes remain attached to the debugger.  In this test
69498685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
69598685dc8SJohn Baldwin  */
69698685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
69798685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
69898685dc8SJohn Baldwin {
699479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
70098685dc8SJohn Baldwin 	int cpipe[2], status;
70198685dc8SJohn Baldwin 
70298685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
70398685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
70498685dc8SJohn Baldwin 	if (fpid == 0) {
70598685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
706189ac973SJohn Baldwin 		follow_fork_parent(false);
70798685dc8SJohn Baldwin 	}
70898685dc8SJohn Baldwin 
70998685dc8SJohn Baldwin 	/* Parent process. */
71098685dc8SJohn Baldwin 	close(cpipe[1]);
71198685dc8SJohn Baldwin 
71298685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
71398685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
71498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
71598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
71698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
71798685dc8SJohn Baldwin 
71898685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
71998685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
72098685dc8SJohn Baldwin 	    sizeof(children[0]));
72198685dc8SJohn Baldwin 
72298685dc8SJohn Baldwin 	/* Attach to the fork parent. */
72398685dc8SJohn Baldwin 	attach_child(children[0]);
72498685dc8SJohn Baldwin 
72598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
72698685dc8SJohn Baldwin 
72798685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
72898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
72998685dc8SJohn Baldwin 
73098685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
73198685dc8SJohn Baldwin 	close(cpipe[0]);
73298685dc8SJohn Baldwin 
733189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
73498685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
73598685dc8SJohn Baldwin 
73698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
73798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
73898685dc8SJohn Baldwin 
73998685dc8SJohn Baldwin 	/*
74098685dc8SJohn Baldwin 	 * The fork parent can't exit until the child reports status,
74198685dc8SJohn Baldwin 	 * so the child should report its exit first to the debugger.
74298685dc8SJohn Baldwin 	 */
74398685dc8SJohn Baldwin 	wpid = wait(&status);
74498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
74598685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
74698685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
74798685dc8SJohn Baldwin 
74898685dc8SJohn Baldwin 	wpid = wait(&status);
74998685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
75098685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
75198685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
75298685dc8SJohn Baldwin 
75398685dc8SJohn Baldwin 	wpid = wait(&status);
75498685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
75598685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
75698685dc8SJohn Baldwin }
75798685dc8SJohn Baldwin 
75898685dc8SJohn Baldwin /*
75998685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
76098685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the new
76198685dc8SJohn Baldwin  * child process is detached after it reports its fork.  In this test
76298685dc8SJohn Baldwin  * the parent that forks is not a direct child of the debugger.
76398685dc8SJohn Baldwin  */
76498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
76598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
76698685dc8SJohn Baldwin {
767479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
76898685dc8SJohn Baldwin 	int cpipe[2], status;
76998685dc8SJohn Baldwin 
77098685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
77198685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
77298685dc8SJohn Baldwin 	if (fpid == 0) {
77398685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
774189ac973SJohn Baldwin 		follow_fork_parent(false);
77598685dc8SJohn Baldwin 	}
77698685dc8SJohn Baldwin 
77798685dc8SJohn Baldwin 	/* Parent process. */
77898685dc8SJohn Baldwin 	close(cpipe[1]);
77998685dc8SJohn Baldwin 
78098685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
78198685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
78298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
78398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
78498685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
78598685dc8SJohn Baldwin 
78698685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
78798685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
78898685dc8SJohn Baldwin 	    sizeof(children[0]));
78998685dc8SJohn Baldwin 
79098685dc8SJohn Baldwin 	/* Attach to the fork parent. */
79198685dc8SJohn Baldwin 	attach_child(children[0]);
79298685dc8SJohn Baldwin 
79398685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
79498685dc8SJohn Baldwin 
79598685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
79698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
79798685dc8SJohn Baldwin 
79898685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
79998685dc8SJohn Baldwin 	close(cpipe[0]);
80098685dc8SJohn Baldwin 
801189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
80298685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
80398685dc8SJohn Baldwin 
80498685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
80598685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
80698685dc8SJohn Baldwin 
80798685dc8SJohn Baldwin 	/*
80898685dc8SJohn Baldwin 	 * Should not see any status from the child now, only the fork
80998685dc8SJohn Baldwin 	 * parent.
81098685dc8SJohn Baldwin 	 */
81198685dc8SJohn Baldwin 	wpid = wait(&status);
81298685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
81398685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
81498685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
81598685dc8SJohn Baldwin 
81698685dc8SJohn Baldwin 	wpid = wait(&status);
81798685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
81898685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
81998685dc8SJohn Baldwin }
82098685dc8SJohn Baldwin 
82198685dc8SJohn Baldwin /*
82298685dc8SJohn Baldwin  * Verify that a new child process is stopped after a followed fork
82398685dc8SJohn Baldwin  * and that the traced parent sees the exit of the child when the
82498685dc8SJohn Baldwin  * traced parent is detached after the fork.  In this test the parent
82598685dc8SJohn Baldwin  * that forks is not a direct child of the debugger.
82698685dc8SJohn Baldwin  */
82798685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
82898685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
82998685dc8SJohn Baldwin {
830479b610dSJohn Baldwin 	pid_t children[2], fpid, wpid;
83198685dc8SJohn Baldwin 	int cpipe[2], status;
83298685dc8SJohn Baldwin 
83398685dc8SJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
83498685dc8SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
83598685dc8SJohn Baldwin 	if (fpid == 0) {
83698685dc8SJohn Baldwin 		attach_fork_parent(cpipe);
837189ac973SJohn Baldwin 		follow_fork_parent(false);
83898685dc8SJohn Baldwin 	}
83998685dc8SJohn Baldwin 
84098685dc8SJohn Baldwin 	/* Parent process. */
84198685dc8SJohn Baldwin 	close(cpipe[1]);
84298685dc8SJohn Baldwin 
84398685dc8SJohn Baldwin 	/* Wait for the direct child to exit. */
84498685dc8SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
84598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
84698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
84798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
84898685dc8SJohn Baldwin 
84998685dc8SJohn Baldwin 	/* Read the pid of the fork parent. */
85098685dc8SJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
85198685dc8SJohn Baldwin 	    sizeof(children[0]));
85298685dc8SJohn Baldwin 
85398685dc8SJohn Baldwin 	/* Attach to the fork parent. */
85498685dc8SJohn Baldwin 	attach_child(children[0]);
85598685dc8SJohn Baldwin 
85698685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
85798685dc8SJohn Baldwin 
85898685dc8SJohn Baldwin 	/* Continue the fork parent ignoring the SIGSTOP. */
85998685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
86098685dc8SJohn Baldwin 
86198685dc8SJohn Baldwin 	/* Signal the fork parent to continue. */
86298685dc8SJohn Baldwin 	close(cpipe[0]);
86398685dc8SJohn Baldwin 
864189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], NULL);
86598685dc8SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
86698685dc8SJohn Baldwin 
86798685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
86898685dc8SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
86998685dc8SJohn Baldwin 
87098685dc8SJohn Baldwin 	/*
87198685dc8SJohn Baldwin 	 * Should not see any status from the fork parent now, only
87298685dc8SJohn Baldwin 	 * the child.
87398685dc8SJohn Baldwin 	 */
87498685dc8SJohn Baldwin 	wpid = wait(&status);
87598685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
87698685dc8SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
87798685dc8SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
87898685dc8SJohn Baldwin 
87998685dc8SJohn Baldwin 	wpid = wait(&status);
88098685dc8SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
88198685dc8SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
88298685dc8SJohn Baldwin }
88398685dc8SJohn Baldwin 
884368b2b1cSJohn Baldwin /*
885368b2b1cSJohn Baldwin  * Verify that a child process does not see an unrelated debugger as its
886368b2b1cSJohn Baldwin  * parent but sees its original parent process.
887368b2b1cSJohn Baldwin  */
888368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid);
889368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc)
890368b2b1cSJohn Baldwin {
891368b2b1cSJohn Baldwin 	pid_t child, debugger, ppid, wpid;
892368b2b1cSJohn Baldwin 	int cpipe[2], dpipe[2], status;
893368b2b1cSJohn Baldwin 	char c;
894368b2b1cSJohn Baldwin 
895368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(cpipe) == 0);
896368b2b1cSJohn Baldwin 	ATF_REQUIRE((child = fork()) != -1);
897368b2b1cSJohn Baldwin 
898368b2b1cSJohn Baldwin 	if (child == 0) {
899368b2b1cSJohn Baldwin 		/* Child process. */
900368b2b1cSJohn Baldwin 		close(cpipe[0]);
901368b2b1cSJohn Baldwin 
902368b2b1cSJohn Baldwin 		/* Wait for parent to be ready. */
903368b2b1cSJohn Baldwin 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
904368b2b1cSJohn Baldwin 
905368b2b1cSJohn Baldwin 		/* Report the parent PID to the parent. */
906368b2b1cSJohn Baldwin 		ppid = getppid();
907368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) ==
908368b2b1cSJohn Baldwin 		    sizeof(ppid));
909368b2b1cSJohn Baldwin 
910368b2b1cSJohn Baldwin 		_exit(1);
911368b2b1cSJohn Baldwin 	}
912368b2b1cSJohn Baldwin 	close(cpipe[1]);
913368b2b1cSJohn Baldwin 
914368b2b1cSJohn Baldwin 	ATF_REQUIRE(pipe(dpipe) == 0);
915368b2b1cSJohn Baldwin 	ATF_REQUIRE((debugger = fork()) != -1);
916368b2b1cSJohn Baldwin 
917368b2b1cSJohn Baldwin 	if (debugger == 0) {
918368b2b1cSJohn Baldwin 		/* Debugger process. */
919368b2b1cSJohn Baldwin 		close(dpipe[0]);
920368b2b1cSJohn Baldwin 
921368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
922368b2b1cSJohn Baldwin 
923368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
924368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
925368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFSTOPPED(status));
926368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
927368b2b1cSJohn Baldwin 
928368b2b1cSJohn Baldwin 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
929368b2b1cSJohn Baldwin 
930368b2b1cSJohn Baldwin 		/* Signal parent that debugger is attached. */
931368b2b1cSJohn Baldwin 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
932368b2b1cSJohn Baldwin 
933368b2b1cSJohn Baldwin 		/* Wait for traced child to exit. */
934368b2b1cSJohn Baldwin 		wpid = waitpid(child, &status, 0);
935368b2b1cSJohn Baldwin 		CHILD_REQUIRE(wpid == child);
936368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WIFEXITED(status));
937368b2b1cSJohn Baldwin 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
938368b2b1cSJohn Baldwin 
939368b2b1cSJohn Baldwin 		_exit(0);
940368b2b1cSJohn Baldwin 	}
941368b2b1cSJohn Baldwin 	close(dpipe[1]);
942368b2b1cSJohn Baldwin 
943368b2b1cSJohn Baldwin 	/* Parent process. */
944368b2b1cSJohn Baldwin 
945368b2b1cSJohn Baldwin 	/* Wait for the debugger to attach to the child. */
946368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
947368b2b1cSJohn Baldwin 
948368b2b1cSJohn Baldwin 	/* Release the child. */
949368b2b1cSJohn Baldwin 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
950368b2b1cSJohn Baldwin 
951368b2b1cSJohn Baldwin 	/* Read the parent PID from the child. */
952368b2b1cSJohn Baldwin 	ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid));
953368b2b1cSJohn Baldwin 	close(cpipe[0]);
954368b2b1cSJohn Baldwin 
955368b2b1cSJohn Baldwin 	ATF_REQUIRE(ppid == getpid());
956368b2b1cSJohn Baldwin 
957368b2b1cSJohn Baldwin 	/* Wait for the debugger. */
958368b2b1cSJohn Baldwin 	wpid = waitpid(debugger, &status, 0);
959368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == debugger);
960368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
961368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
962368b2b1cSJohn Baldwin 
963368b2b1cSJohn Baldwin 	/* The child process should now be ready. */
964368b2b1cSJohn Baldwin 	wpid = waitpid(child, &status, WNOHANG);
965368b2b1cSJohn Baldwin 	ATF_REQUIRE(wpid == child);
966368b2b1cSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
967368b2b1cSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
968368b2b1cSJohn Baldwin }
969368b2b1cSJohn Baldwin 
970189ac973SJohn Baldwin /*
971189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
972189ac973SJohn Baldwin  * child process created via fork() reports the correct value.
973189ac973SJohn Baldwin  */
974189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
975189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
976189ac973SJohn Baldwin {
977189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
978189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
979189ac973SJohn Baldwin 	int status;
980189ac973SJohn Baldwin 
981189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
982189ac973SJohn Baldwin 	if (fpid == 0) {
983189ac973SJohn Baldwin 		trace_me();
984189ac973SJohn Baldwin 		follow_fork_parent(false);
985189ac973SJohn Baldwin 	}
986189ac973SJohn Baldwin 
987189ac973SJohn Baldwin 	/* Parent process. */
988189ac973SJohn Baldwin 	children[0] = fpid;
989189ac973SJohn Baldwin 
990189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
991189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
992189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
993189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
994189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
995189ac973SJohn Baldwin 
996189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
997189ac973SJohn Baldwin 
998189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
999189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1000189ac973SJohn Baldwin 
1001189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1002189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1003189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1004189ac973SJohn Baldwin 
1005189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1006189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1007189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork);
1008189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1009189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1010189ac973SJohn Baldwin 
1011189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1012189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1013189ac973SJohn Baldwin 
1014189ac973SJohn Baldwin 	/*
1015189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1016189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1017189ac973SJohn Baldwin 	 */
1018189ac973SJohn Baldwin 	wpid = wait(&status);
1019189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1020189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1021189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1022189ac973SJohn Baldwin 
1023189ac973SJohn Baldwin 	wpid = wait(&status);
1024189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1025189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1026189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1027189ac973SJohn Baldwin 
1028189ac973SJohn Baldwin 	wpid = wait(&status);
1029189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1030189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1031189ac973SJohn Baldwin }
1032189ac973SJohn Baldwin 
1033189ac973SJohn Baldwin /*
1034189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1035189ac973SJohn Baldwin  * child process created via vfork() reports the correct value.
1036189ac973SJohn Baldwin  */
1037189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
1038189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
1039189ac973SJohn Baldwin {
1040189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1041189ac973SJohn Baldwin 	pid_t children[2], fpid, wpid;
1042189ac973SJohn Baldwin 	int status;
1043189ac973SJohn Baldwin 
1044189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1045189ac973SJohn Baldwin 	if (fpid == 0) {
1046189ac973SJohn Baldwin 		trace_me();
1047189ac973SJohn Baldwin 		follow_fork_parent(true);
1048189ac973SJohn Baldwin 	}
1049189ac973SJohn Baldwin 
1050189ac973SJohn Baldwin 	/* Parent process. */
1051189ac973SJohn Baldwin 	children[0] = fpid;
1052189ac973SJohn Baldwin 
1053189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1054189ac973SJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1055189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1056189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1057189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1058189ac973SJohn Baldwin 
1059189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
1060189ac973SJohn Baldwin 
1061189ac973SJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1062189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1063189ac973SJohn Baldwin 
1064189ac973SJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1065189ac973SJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1066189ac973SJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1067189ac973SJohn Baldwin 
1068189ac973SJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
1069189ac973SJohn Baldwin 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
1070189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork);
1071189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
1072189ac973SJohn Baldwin 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
1073189ac973SJohn Baldwin 
1074189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1075189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1076189ac973SJohn Baldwin 
1077189ac973SJohn Baldwin 	/*
1078189ac973SJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1079189ac973SJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1080189ac973SJohn Baldwin 	 */
1081189ac973SJohn Baldwin 	wpid = wait(&status);
1082189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1083189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1084189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1085189ac973SJohn Baldwin 
1086189ac973SJohn Baldwin 	wpid = wait(&status);
1087189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1088189ac973SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1089189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1090189ac973SJohn Baldwin 
1091189ac973SJohn Baldwin 	wpid = wait(&status);
1092189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1093189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1094189ac973SJohn Baldwin }
1095189ac973SJohn Baldwin 
1096189ac973SJohn Baldwin static void *
1097189ac973SJohn Baldwin simple_thread(void *arg __unused)
1098189ac973SJohn Baldwin {
1099189ac973SJohn Baldwin 
1100189ac973SJohn Baldwin 	pthread_exit(NULL);
1101189ac973SJohn Baldwin }
1102189ac973SJohn Baldwin 
11035fcfab6eSJohn Baldwin static __dead2 void
11045fcfab6eSJohn Baldwin simple_thread_main(void)
11055fcfab6eSJohn Baldwin {
11065fcfab6eSJohn Baldwin 	pthread_t thread;
11075fcfab6eSJohn Baldwin 
11085fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, NULL) == 0);
11095fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_join(thread, NULL) == 0);
11105fcfab6eSJohn Baldwin 	exit(1);
11115fcfab6eSJohn Baldwin }
11125fcfab6eSJohn Baldwin 
1113189ac973SJohn Baldwin /*
1114189ac973SJohn Baldwin  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
1115189ac973SJohn Baldwin  * thread reports the correct value.
1116189ac973SJohn Baldwin  */
1117189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
1118189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
1119189ac973SJohn Baldwin {
1120189ac973SJohn Baldwin 	struct ptrace_lwpinfo pl;
1121189ac973SJohn Baldwin 	pid_t fpid, wpid;
1122e72879e5SJohn Baldwin 	lwpid_t mainlwp;
1123189ac973SJohn Baldwin 	int status;
1124189ac973SJohn Baldwin 
1125189ac973SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1126189ac973SJohn Baldwin 	if (fpid == 0) {
1127189ac973SJohn Baldwin 		trace_me();
11285fcfab6eSJohn Baldwin 		simple_thread_main();
1129189ac973SJohn Baldwin 	}
1130189ac973SJohn Baldwin 
1131189ac973SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1132189ac973SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1133189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1134189ac973SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1135189ac973SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1136189ac973SJohn Baldwin 
1137189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1138189ac973SJohn Baldwin 	    sizeof(pl)) != -1);
1139e72879e5SJohn Baldwin 	mainlwp = pl.pl_lwpid;
1140189ac973SJohn Baldwin 
1141189ac973SJohn Baldwin 	/*
1142189ac973SJohn Baldwin 	 * Continue the child ignoring the SIGSTOP and tracing all
1143189ac973SJohn Baldwin 	 * system call exits.
1144189ac973SJohn Baldwin 	 */
1145189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
1146189ac973SJohn Baldwin 
1147189ac973SJohn Baldwin 	/*
1148189ac973SJohn Baldwin 	 * Wait for the new thread to arrive.  pthread_create() might
1149189ac973SJohn Baldwin 	 * invoke any number of system calls.  For now we just wait
1150189ac973SJohn Baldwin 	 * for the new thread to arrive and make sure it reports a
1151189ac973SJohn Baldwin 	 * valid system call code.  If ptrace grows thread event
1152189ac973SJohn Baldwin 	 * reporting then this test can be made more precise.
1153189ac973SJohn Baldwin 	 */
1154189ac973SJohn Baldwin 	for (;;) {
1155189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1156189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1157189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1158189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1159189ac973SJohn Baldwin 
1160189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
1161189ac973SJohn Baldwin 		    sizeof(pl)) != -1);
1162189ac973SJohn Baldwin 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
1163189ac973SJohn Baldwin 		ATF_REQUIRE(pl.pl_syscall_code != 0);
1164e72879e5SJohn Baldwin 		if (pl.pl_lwpid != mainlwp)
1165189ac973SJohn Baldwin 			/* New thread seen. */
1166189ac973SJohn Baldwin 			break;
1167189ac973SJohn Baldwin 
1168189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1169189ac973SJohn Baldwin 	}
1170189ac973SJohn Baldwin 
1171189ac973SJohn Baldwin 	/* Wait for the child to exit. */
1172189ac973SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1173189ac973SJohn Baldwin 	for (;;) {
1174189ac973SJohn Baldwin 		wpid = waitpid(fpid, &status, 0);
1175189ac973SJohn Baldwin 		ATF_REQUIRE(wpid == fpid);
1176189ac973SJohn Baldwin 		if (WIFEXITED(status))
1177189ac973SJohn Baldwin 			break;
1178189ac973SJohn Baldwin 
1179189ac973SJohn Baldwin 		ATF_REQUIRE(WIFSTOPPED(status));
1180189ac973SJohn Baldwin 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1181189ac973SJohn Baldwin 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
1182189ac973SJohn Baldwin 	}
1183189ac973SJohn Baldwin 
1184189ac973SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1185189ac973SJohn Baldwin 
1186189ac973SJohn Baldwin 	wpid = wait(&status);
1187189ac973SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1188189ac973SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1189189ac973SJohn Baldwin }
1190189ac973SJohn Baldwin 
11915fcfab6eSJohn Baldwin /*
11925fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a child thread.
11935fcfab6eSJohn Baldwin  */
11945fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
11955fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc)
11965fcfab6eSJohn Baldwin {
11975fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
11985fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
11995fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
12005fcfab6eSJohn Baldwin 	int status;
12015fcfab6eSJohn Baldwin 
12025fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
12035fcfab6eSJohn Baldwin 	if (fpid == 0) {
12045fcfab6eSJohn Baldwin 		trace_me();
12055fcfab6eSJohn Baldwin 		simple_thread_main();
12065fcfab6eSJohn Baldwin 	}
12075fcfab6eSJohn Baldwin 
12085fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
12095fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12105fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12115fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12125fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
12135fcfab6eSJohn Baldwin 
12145fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
12155fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
12165fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
12175fcfab6eSJohn Baldwin 
12185fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
12195fcfab6eSJohn Baldwin 
12205fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
12215fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12225fcfab6eSJohn Baldwin 
12235fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
12245fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12255fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12265fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12275fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
12285fcfab6eSJohn Baldwin 
12295fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
12305fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
12315fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
12325fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
12335fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
12345fcfab6eSJohn Baldwin 
12355fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12365fcfab6eSJohn Baldwin 
12375fcfab6eSJohn Baldwin 	/* The next event should be for the child thread's death. */
12385fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12395fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
12405fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
12415fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
12425fcfab6eSJohn Baldwin 
12435fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
12445fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
12455fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
12465fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
12475fcfab6eSJohn Baldwin 
12485fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
12495fcfab6eSJohn Baldwin 
12505fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
12515fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12525fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
12535fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
12545fcfab6eSJohn Baldwin 
12555fcfab6eSJohn Baldwin 	wpid = wait(&status);
12565fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
12575fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
12585fcfab6eSJohn Baldwin }
12595fcfab6eSJohn Baldwin 
12605fcfab6eSJohn Baldwin static void *
12615fcfab6eSJohn Baldwin exec_thread(void *arg __unused)
12625fcfab6eSJohn Baldwin {
12635fcfab6eSJohn Baldwin 
12645fcfab6eSJohn Baldwin 	execl("/usr/bin/true", "true", NULL);
12655fcfab6eSJohn Baldwin 	exit(127);
12665fcfab6eSJohn Baldwin }
12675fcfab6eSJohn Baldwin 
12685fcfab6eSJohn Baldwin static __dead2 void
12695fcfab6eSJohn Baldwin exec_thread_main(void)
12705fcfab6eSJohn Baldwin {
12715fcfab6eSJohn Baldwin 	pthread_t thread;
12725fcfab6eSJohn Baldwin 
12735fcfab6eSJohn Baldwin 	CHILD_REQUIRE(pthread_create(&thread, NULL, exec_thread, NULL) == 0);
12745fcfab6eSJohn Baldwin 	for (;;)
12755fcfab6eSJohn Baldwin 		sleep(60);
12765fcfab6eSJohn Baldwin 	exit(1);
12775fcfab6eSJohn Baldwin }
12785fcfab6eSJohn Baldwin 
12795fcfab6eSJohn Baldwin /*
12805fcfab6eSJohn Baldwin  * Verify that the expected LWP events are reported for a multithreaded
12815fcfab6eSJohn Baldwin  * process that calls execve(2).
12825fcfab6eSJohn Baldwin  */
12835fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
12845fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc)
12855fcfab6eSJohn Baldwin {
12865fcfab6eSJohn Baldwin 	struct ptrace_lwpinfo pl;
12875fcfab6eSJohn Baldwin 	pid_t fpid, wpid;
12885fcfab6eSJohn Baldwin 	lwpid_t lwps[2];
12895fcfab6eSJohn Baldwin 	int status;
12905fcfab6eSJohn Baldwin 
12915fcfab6eSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
12925fcfab6eSJohn Baldwin 	if (fpid == 0) {
12935fcfab6eSJohn Baldwin 		trace_me();
12945fcfab6eSJohn Baldwin 		exec_thread_main();
12955fcfab6eSJohn Baldwin 	}
12965fcfab6eSJohn Baldwin 
12975fcfab6eSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
12985fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
12995fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13005fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13015fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
13025fcfab6eSJohn Baldwin 
13035fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
13045fcfab6eSJohn Baldwin 	    sizeof(pl)) != -1);
13055fcfab6eSJohn Baldwin 	lwps[0] = pl.pl_lwpid;
13065fcfab6eSJohn Baldwin 
13075fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
13085fcfab6eSJohn Baldwin 
13095fcfab6eSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
13105fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13115fcfab6eSJohn Baldwin 
13125fcfab6eSJohn Baldwin 	/* The first event should be for the child thread's birth. */
13135fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13145fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13155fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13165fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13175fcfab6eSJohn Baldwin 
13185fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13195fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
13205fcfab6eSJohn Baldwin 	    (PL_FLAG_BORN | PL_FLAG_SCX));
13215fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
13225fcfab6eSJohn Baldwin 	lwps[1] = pl.pl_lwpid;
13235fcfab6eSJohn Baldwin 
13245fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13255fcfab6eSJohn Baldwin 
13265fcfab6eSJohn Baldwin 	/*
13275fcfab6eSJohn Baldwin 	 * The next event should be for the main thread's death due to
13285fcfab6eSJohn Baldwin 	 * single threading from execve().
13295fcfab6eSJohn Baldwin 	 */
13305fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13315fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13325fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13335fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13345fcfab6eSJohn Baldwin 
13355fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13365fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
13375fcfab6eSJohn Baldwin 	    (PL_FLAG_EXITED));
13385fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[0]);
13395fcfab6eSJohn Baldwin 
13405fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13415fcfab6eSJohn Baldwin 
13425fcfab6eSJohn Baldwin 	/* The next event should be for the child process's exec. */
13435fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13445fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13455fcfab6eSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
13465fcfab6eSJohn Baldwin 
13475fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
13485fcfab6eSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
13495fcfab6eSJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
13505fcfab6eSJohn Baldwin 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
13515fcfab6eSJohn Baldwin 
13525fcfab6eSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
13535fcfab6eSJohn Baldwin 
13545fcfab6eSJohn Baldwin 	/* The last event should be for the child process's exit. */
13555fcfab6eSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13565fcfab6eSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
13575fcfab6eSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
13585fcfab6eSJohn Baldwin 
13595fcfab6eSJohn Baldwin 	wpid = wait(&status);
13605fcfab6eSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
13615fcfab6eSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
13625fcfab6eSJohn Baldwin }
13635fcfab6eSJohn Baldwin 
13643340c45bSJohn Baldwin static void
13653340c45bSJohn Baldwin handler(int sig __unused)
13663340c45bSJohn Baldwin {
13673340c45bSJohn Baldwin }
13683340c45bSJohn Baldwin 
13693340c45bSJohn Baldwin static void
13703340c45bSJohn Baldwin signal_main(void)
13713340c45bSJohn Baldwin {
13723340c45bSJohn Baldwin 
13733340c45bSJohn Baldwin 	signal(SIGINFO, handler);
13743340c45bSJohn Baldwin 	raise(SIGINFO);
13753340c45bSJohn Baldwin 	exit(0);
13763340c45bSJohn Baldwin }
13773340c45bSJohn Baldwin 
13783340c45bSJohn Baldwin /*
13793340c45bSJohn Baldwin  * Verify that the expected ptrace event is reported for a signal.
13803340c45bSJohn Baldwin  */
13813340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
13823340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc)
13833340c45bSJohn Baldwin {
13843340c45bSJohn Baldwin 	struct ptrace_lwpinfo pl;
13853340c45bSJohn Baldwin 	pid_t fpid, wpid;
13863340c45bSJohn Baldwin 	int status;
13873340c45bSJohn Baldwin 
13883340c45bSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
13893340c45bSJohn Baldwin 	if (fpid == 0) {
13903340c45bSJohn Baldwin 		trace_me();
13913340c45bSJohn Baldwin 		signal_main();
13923340c45bSJohn Baldwin 	}
13933340c45bSJohn Baldwin 
13943340c45bSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
13953340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
13963340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
13973340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
13983340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
13993340c45bSJohn Baldwin 
14003340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14013340c45bSJohn Baldwin 
14023340c45bSJohn Baldwin 	/* The next event should be for the SIGINFO. */
14033340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14043340c45bSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14053340c45bSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGINFO);
14063340c45bSJohn Baldwin 
14073340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14083340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_event == PL_EVENT_SIGNAL);
14093340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
14103340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_code == SI_LWP);
14113340c45bSJohn Baldwin 	ATF_REQUIRE(pl.pl_siginfo.si_pid == wpid);
14123340c45bSJohn Baldwin 
14133340c45bSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14143340c45bSJohn Baldwin 
14153340c45bSJohn Baldwin 	/* The last event should be for the child process's exit. */
14163340c45bSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14173340c45bSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
14183340c45bSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
14193340c45bSJohn Baldwin 
14203340c45bSJohn Baldwin 	wpid = wait(&status);
14213340c45bSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14223340c45bSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
14233340c45bSJohn Baldwin }
14243340c45bSJohn Baldwin 
14258d570f64SJohn Baldwin /*
14268d570f64SJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
14278d570f64SJohn Baldwin  */
14288d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
14298d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
14308d570f64SJohn Baldwin {
14318d570f64SJohn Baldwin 	pid_t fpid, wpid;
14328d570f64SJohn Baldwin 	int events, status;
14338d570f64SJohn Baldwin 
14348d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14358d570f64SJohn Baldwin 	if (fpid == 0) {
14368d570f64SJohn Baldwin 		trace_me();
14378d570f64SJohn Baldwin 		exec_thread(NULL);
14388d570f64SJohn Baldwin 	}
14398d570f64SJohn Baldwin 
14408d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14418d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14428d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14438d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14448d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14458d570f64SJohn Baldwin 
14468d570f64SJohn Baldwin 	events = 0;
14478d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
14488d570f64SJohn Baldwin 	    sizeof(events)) == 0);
14498d570f64SJohn Baldwin 
14508d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14518d570f64SJohn Baldwin 
14528d570f64SJohn Baldwin 	/* Should get one event at exit. */
14538d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14548d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
14558d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
14568d570f64SJohn Baldwin 
14578d570f64SJohn Baldwin 	wpid = wait(&status);
14588d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
14598d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
14608d570f64SJohn Baldwin }
14618d570f64SJohn Baldwin 
14628d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
14638d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
14648d570f64SJohn Baldwin {
14658d570f64SJohn Baldwin 	struct ptrace_lwpinfo pl;
14668d570f64SJohn Baldwin 	pid_t fpid, wpid;
14678d570f64SJohn Baldwin 	int events, status;
14688d570f64SJohn Baldwin 
14698d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
14708d570f64SJohn Baldwin 	if (fpid == 0) {
14718d570f64SJohn Baldwin 		trace_me();
14728d570f64SJohn Baldwin 		exec_thread(NULL);
14738d570f64SJohn Baldwin 	}
14748d570f64SJohn Baldwin 
14758d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
14768d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14778d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
14788d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14798d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
14808d570f64SJohn Baldwin 
14818d570f64SJohn Baldwin 	events = PTRACE_EXEC;
14828d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
14838d570f64SJohn Baldwin 	    sizeof(events)) == 0);
14848d570f64SJohn Baldwin 
14858d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14868d570f64SJohn Baldwin 
14878d570f64SJohn Baldwin 	/* The next event should be for the child process's exec. */
14888d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
14898d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
14908d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
14918d570f64SJohn Baldwin 
14928d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
14938d570f64SJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
14948d570f64SJohn Baldwin 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
14958d570f64SJohn Baldwin 
14968d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
14978d570f64SJohn Baldwin 
14988d570f64SJohn Baldwin 	/* The last event should be for the child process's exit. */
14998d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15008d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15018d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15028d570f64SJohn Baldwin 
15038d570f64SJohn Baldwin 	wpid = wait(&status);
15048d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15058d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15068d570f64SJohn Baldwin }
15078d570f64SJohn Baldwin 
15088d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
15098d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc)
15108d570f64SJohn Baldwin {
15118d570f64SJohn Baldwin 	pid_t fpid, wpid;
15128d570f64SJohn Baldwin 	int events, status;
15138d570f64SJohn Baldwin 
15148d570f64SJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
15158d570f64SJohn Baldwin 	if (fpid == 0) {
15168d570f64SJohn Baldwin 		trace_me();
15178d570f64SJohn Baldwin 		exit(0);
15188d570f64SJohn Baldwin 	}
15198d570f64SJohn Baldwin 
15208d570f64SJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
15218d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15228d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
15238d570f64SJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
15248d570f64SJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
15258d570f64SJohn Baldwin 
15268d570f64SJohn Baldwin 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
15278d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
15288d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15298d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15308d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_FORK);
15318d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -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 
15368d570f64SJohn Baldwin 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
15378d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
15388d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
15398d570f64SJohn Baldwin 	    sizeof(events)) == 0);
15408d570f64SJohn Baldwin 	ATF_REQUIRE(events & PTRACE_LWP);
15418d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -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 
15468d570f64SJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
15478d570f64SJohn Baldwin 
15488d570f64SJohn Baldwin 	/* Should get one event at exit. */
15498d570f64SJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
15508d570f64SJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
15518d570f64SJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
15528d570f64SJohn Baldwin 
15538d570f64SJohn Baldwin 	wpid = wait(&status);
15548d570f64SJohn Baldwin 	ATF_REQUIRE(wpid == -1);
15558d570f64SJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
15568d570f64SJohn Baldwin }
15578d570f64SJohn Baldwin 
1558fc4f075aSJohn Baldwin /*
1559fc4f075aSJohn Baldwin  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
1560fc4f075aSJohn Baldwin  */
1561fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
1562fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc)
1563fc4f075aSJohn Baldwin {
1564fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl;
1565fc4f075aSJohn Baldwin 	pid_t fpid, wpid;
1566fc4f075aSJohn Baldwin 	int events, status;
1567fc4f075aSJohn Baldwin 
1568fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1569fc4f075aSJohn Baldwin 	if (fpid == 0) {
1570fc4f075aSJohn Baldwin 		trace_me();
1571fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1572fc4f075aSJohn Baldwin 	}
1573fc4f075aSJohn Baldwin 
1574fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1575fc4f075aSJohn Baldwin 	wpid = waitpid(fpid, &status, 0);
1576fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1577fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1578fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1579fc4f075aSJohn Baldwin 
1580fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
1581fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1582fc4f075aSJohn Baldwin 	events |= PTRACE_VFORK;
1583fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
1584fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1585fc4f075aSJohn Baldwin 
1586fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1587fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1588fc4f075aSJohn Baldwin 
1589fc4f075aSJohn Baldwin 	/* The next event should report the end of the vfork. */
1590fc4f075aSJohn Baldwin 	wpid = wait(&status);
1591fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1592fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1593fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1594fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
1595fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
1596fc4f075aSJohn Baldwin 
1597fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
1598fc4f075aSJohn Baldwin 
1599fc4f075aSJohn Baldwin 	wpid = wait(&status);
1600fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == fpid);
1601fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1602fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1603fc4f075aSJohn Baldwin 
1604fc4f075aSJohn Baldwin 	wpid = wait(&status);
1605fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1606fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1607fc4f075aSJohn Baldwin }
1608fc4f075aSJohn Baldwin 
1609fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
1610fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
1611fc4f075aSJohn Baldwin {
1612fc4f075aSJohn Baldwin 	struct ptrace_lwpinfo pl[2];
1613fc4f075aSJohn Baldwin 	pid_t children[2], fpid, wpid;
1614fc4f075aSJohn Baldwin 	int events, status;
1615fc4f075aSJohn Baldwin 
1616fc4f075aSJohn Baldwin 	ATF_REQUIRE((fpid = fork()) != -1);
1617fc4f075aSJohn Baldwin 	if (fpid == 0) {
1618fc4f075aSJohn Baldwin 		trace_me();
1619fc4f075aSJohn Baldwin 		follow_fork_parent(true);
1620fc4f075aSJohn Baldwin 	}
1621fc4f075aSJohn Baldwin 
1622fc4f075aSJohn Baldwin 	/* Parent process. */
1623fc4f075aSJohn Baldwin 	children[0] = fpid;
1624fc4f075aSJohn Baldwin 
1625fc4f075aSJohn Baldwin 	/* The first wait() should report the stop from SIGSTOP. */
1626fc4f075aSJohn Baldwin 	wpid = waitpid(children[0], &status, 0);
1627fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1628fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1629fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
1630fc4f075aSJohn Baldwin 
1631fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
1632fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1633fc4f075aSJohn Baldwin 	events |= PTRACE_FORK | PTRACE_VFORK;
1634fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
1635fc4f075aSJohn Baldwin 	    sizeof(events)) == 0);
1636fc4f075aSJohn Baldwin 
1637fc4f075aSJohn Baldwin 	/* Continue the child ignoring the SIGSTOP. */
1638fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1639fc4f075aSJohn Baldwin 
1640fc4f075aSJohn Baldwin 	/* Wait for both halves of the fork event to get reported. */
1641fc4f075aSJohn Baldwin 	children[1] = handle_fork_events(children[0], pl);
1642fc4f075aSJohn Baldwin 	ATF_REQUIRE(children[1] > 0);
1643fc4f075aSJohn Baldwin 
1644fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
1645fc4f075aSJohn Baldwin 
1646fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1647fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
1648fc4f075aSJohn Baldwin 
1649fc4f075aSJohn Baldwin 	/*
1650fc4f075aSJohn Baldwin 	 * The child can't exit until the grandchild reports status, so the
1651fc4f075aSJohn Baldwin 	 * grandchild should report its exit first to the debugger.
1652fc4f075aSJohn Baldwin 	 */
1653fc4f075aSJohn Baldwin 	wpid = waitpid(children[1], &status, 0);
1654fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[1]);
1655fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1656fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
1657fc4f075aSJohn Baldwin 
1658fc4f075aSJohn Baldwin 	/*
1659fc4f075aSJohn Baldwin 	 * The child should report it's vfork() completion before it
1660fc4f075aSJohn Baldwin 	 * exits.
1661fc4f075aSJohn Baldwin 	 */
1662fc4f075aSJohn Baldwin 	wpid = wait(&status);
1663fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1664fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFSTOPPED(status));
1665fc4f075aSJohn Baldwin 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
1666fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
1667fc4f075aSJohn Baldwin 	    -1);
1668fc4f075aSJohn Baldwin 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
1669fc4f075aSJohn Baldwin 
1670fc4f075aSJohn Baldwin 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
1671fc4f075aSJohn Baldwin 
1672fc4f075aSJohn Baldwin 	wpid = wait(&status);
1673fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == children[0]);
1674fc4f075aSJohn Baldwin 	ATF_REQUIRE(WIFEXITED(status));
1675fc4f075aSJohn Baldwin 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
1676fc4f075aSJohn Baldwin 
1677fc4f075aSJohn Baldwin 	wpid = wait(&status);
1678fc4f075aSJohn Baldwin 	ATF_REQUIRE(wpid == -1);
1679fc4f075aSJohn Baldwin 	ATF_REQUIRE(errno == ECHILD);
1680fc4f075aSJohn Baldwin }
1681fc4f075aSJohn Baldwin 
168282a4538fSEric Badger /*
1683e2ebfbbfSEric Badger  * XXX: There's nothing inherently platform specific about this test, however a
1684e2ebfbbfSEric Badger  * userspace visible breakpoint() is a prerequisite.
1685e2ebfbbfSEric Badger  */
1686e2ebfbbfSEric Badger  #if defined(__amd64__) || defined(__i386__) || defined(__sparc64__)
1687e2ebfbbfSEric Badger /*
168882a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
168982a4538fSEric Badger  * process exit when stopped due to a breakpoint trap.
169082a4538fSEric Badger  */
169182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
169282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
169382a4538fSEric Badger {
169482a4538fSEric Badger 	pid_t fpid, wpid;
169582a4538fSEric Badger 	int status;
169682a4538fSEric Badger 
169782a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
169882a4538fSEric Badger 	if (fpid == 0) {
169982a4538fSEric Badger 		trace_me();
17009e0d1159SEric Badger 		breakpoint();
170182a4538fSEric Badger 		exit(1);
170282a4538fSEric Badger 	}
170382a4538fSEric Badger 
170482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
170582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
170682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
170782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
170882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
170982a4538fSEric Badger 
171082a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
171182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
171282a4538fSEric Badger 
171382a4538fSEric Badger 	/* The second wait() should report hitting the breakpoint. */
171482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
171582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
171682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
171782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
171882a4538fSEric Badger 
171982a4538fSEric Badger 	/* Kill the child process. */
172082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
172182a4538fSEric Badger 
172282a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
172382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
172482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
172582a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
172682a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
172782a4538fSEric Badger 
172882a4538fSEric Badger 	wpid = wait(&status);
172982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
173082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
173182a4538fSEric Badger }
1732e2ebfbbfSEric Badger #endif /* defined(__amd64__) || defined(__i386__) || defined(__sparc64__) */
173382a4538fSEric Badger 
173482a4538fSEric Badger /*
173582a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
173682a4538fSEric Badger  * process exit when stopped inside of a system call.
173782a4538fSEric Badger  */
173882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
173982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
174082a4538fSEric Badger {
174182a4538fSEric Badger 	struct ptrace_lwpinfo pl;
174282a4538fSEric Badger 	pid_t fpid, wpid;
174382a4538fSEric Badger 	int status;
174482a4538fSEric Badger 
174582a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
174682a4538fSEric Badger 	if (fpid == 0) {
174782a4538fSEric Badger 		trace_me();
174882a4538fSEric Badger 		getpid();
174982a4538fSEric Badger 		exit(1);
175082a4538fSEric Badger 	}
175182a4538fSEric Badger 
175282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
175382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
175482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
175582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
175682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
175782a4538fSEric Badger 
175882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
175982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
176082a4538fSEric Badger 
176182a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
176282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
176382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
176482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
176582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
176682a4538fSEric Badger 
176782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
176882a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
176982a4538fSEric Badger 
177082a4538fSEric Badger 	/* Kill the child process. */
177182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
177282a4538fSEric Badger 
177382a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
177482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
177582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
177682a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
177782a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
177882a4538fSEric Badger 
177982a4538fSEric Badger 	wpid = wait(&status);
178082a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
178182a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
178282a4538fSEric Badger }
178382a4538fSEric Badger 
178482a4538fSEric Badger /*
178582a4538fSEric Badger  * Verify that no more events are reported after PT_KILL except for the
178682a4538fSEric Badger  * process exit when killing a multithreaded process.
178782a4538fSEric Badger  */
178882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
178982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
179082a4538fSEric Badger {
179182a4538fSEric Badger 	struct ptrace_lwpinfo pl;
179282a4538fSEric Badger 	pid_t fpid, wpid;
179382a4538fSEric Badger 	lwpid_t main_lwp;
179482a4538fSEric Badger 	int status;
179582a4538fSEric Badger 
179682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
179782a4538fSEric Badger 	if (fpid == 0) {
179882a4538fSEric Badger 		trace_me();
179982a4538fSEric Badger 		simple_thread_main();
180082a4538fSEric Badger 	}
180182a4538fSEric Badger 
180282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
180382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
180482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
180582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
180682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
180782a4538fSEric Badger 
180882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
180982a4538fSEric Badger 	    sizeof(pl)) != -1);
181082a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
181182a4538fSEric Badger 
181282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
181382a4538fSEric Badger 
181482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
181582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
181682a4538fSEric Badger 
181782a4538fSEric Badger 	/* The first event should be for the child thread's birth. */
181882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
181982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
182082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
182182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
182282a4538fSEric Badger 
182382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
182482a4538fSEric Badger 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
182582a4538fSEric Badger 	    (PL_FLAG_BORN | PL_FLAG_SCX));
182682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
182782a4538fSEric Badger 
182882a4538fSEric Badger 	/* Kill the child process. */
182982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
183082a4538fSEric Badger 
183182a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
183282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
183382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
183482a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
183582a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
183682a4538fSEric Badger 
183782a4538fSEric Badger 	wpid = wait(&status);
183882a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
183982a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
184082a4538fSEric Badger }
184182a4538fSEric Badger 
184282a4538fSEric Badger static void *
184382a4538fSEric Badger mask_usr1_thread(void *arg)
184482a4538fSEric Badger {
184582a4538fSEric Badger 	pthread_barrier_t *pbarrier;
184682a4538fSEric Badger 	sigset_t sigmask;
184782a4538fSEric Badger 
184882a4538fSEric Badger 	pbarrier = (pthread_barrier_t*)arg;
184982a4538fSEric Badger 
185082a4538fSEric Badger 	sigemptyset(&sigmask);
185182a4538fSEric Badger 	sigaddset(&sigmask, SIGUSR1);
185282a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
185382a4538fSEric Badger 
185482a4538fSEric Badger 	/* Sync up with other thread after sigmask updated. */
185582a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
185682a4538fSEric Badger 
185782a4538fSEric Badger 	for (;;)
185882a4538fSEric Badger 		sleep(60);
185982a4538fSEric Badger 
186082a4538fSEric Badger 	return (NULL);
186182a4538fSEric Badger }
186282a4538fSEric Badger 
186382a4538fSEric Badger /*
186482a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other signals
186582a4538fSEric Badger  * and prevents spurious stops due to those other signals.
186682a4538fSEric Badger  */
186782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_competing_signal);
186882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
186982a4538fSEric Badger {
187082a4538fSEric Badger 	pid_t fpid, wpid;
187182a4538fSEric Badger 	int status;
187282a4538fSEric Badger 	cpuset_t setmask;
187382a4538fSEric Badger 	pthread_t t;
187482a4538fSEric Badger 	pthread_barrier_t barrier;
187582a4538fSEric Badger 
187682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
187782a4538fSEric Badger 	if (fpid == 0) {
187882a4538fSEric Badger 		/*
187982a4538fSEric Badger 		 * Bind to one CPU so only one thread at a time will run. This
188082a4538fSEric Badger 		 * test expects that the first thread created (the main thread)
188182a4538fSEric Badger 		 * will be unsuspended first and will block the second thread
188282a4538fSEric Badger 		 * from running.
188382a4538fSEric Badger 		 */
188482a4538fSEric Badger 		CPU_ZERO(&setmask);
188582a4538fSEric Badger 		CPU_SET(0, &setmask);
188682a4538fSEric Badger 		cpusetid_t setid;
188782a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
188882a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
188982a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
189082a4538fSEric Badger 
189182a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
189282a4538fSEric Badger 
189382a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
189482a4538fSEric Badger 		    (void*)&barrier) == 0);
189582a4538fSEric Badger 
189682a4538fSEric Badger 		sigset_t sigmask;
189782a4538fSEric Badger 		sigemptyset(&sigmask);
189882a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
189982a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
190082a4538fSEric Badger 
190182a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
190282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
190382a4538fSEric Badger 
190482a4538fSEric Badger 		trace_me();
190582a4538fSEric Badger 
190682a4538fSEric Badger 		for (;;)
190782a4538fSEric Badger 			sleep(60);
190882a4538fSEric Badger 
190982a4538fSEric Badger 		exit(1);
191082a4538fSEric Badger 	}
191182a4538fSEric Badger 
191282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
191382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
191482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
191582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
191682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
191782a4538fSEric Badger 
191882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
191982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
192082a4538fSEric Badger 
192182a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
192282a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
192382a4538fSEric Badger 
192482a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
192582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
192682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
192782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
192882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
192982a4538fSEric Badger 
193082a4538fSEric Badger 	/* Send a signal that only the first thread can handle. */
193182a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
193282a4538fSEric Badger 
193382a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
193482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
193582a4538fSEric Badger 
193682a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
193782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
193882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
193982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
194082a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
194182a4538fSEric Badger 
194282a4538fSEric Badger 	wpid = wait(&status);
194382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
194482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
194582a4538fSEric Badger }
194682a4538fSEric Badger 
194782a4538fSEric Badger /*
194882a4538fSEric Badger  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
194982a4538fSEric Badger  * and prevents spurious stops caused by those events.
195082a4538fSEric Badger  */
195182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_competing_stop);
195282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
195382a4538fSEric Badger {
195482a4538fSEric Badger 	pid_t fpid, wpid;
195582a4538fSEric Badger 	int status, i;
195682a4538fSEric Badger 	cpuset_t setmask;
195782a4538fSEric Badger 	pthread_t t;
195882a4538fSEric Badger 	pthread_barrier_t barrier;
195982a4538fSEric Badger 	lwpid_t main_lwp;
196082a4538fSEric Badger 	struct ptrace_lwpinfo pl;
196182a4538fSEric Badger 
196282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
196382a4538fSEric Badger 	if (fpid == 0) {
196482a4538fSEric Badger 		trace_me();
196582a4538fSEric Badger 
196682a4538fSEric Badger 		/*
196782a4538fSEric Badger 		 * Bind to one CPU so only one thread at a time will run. This
196882a4538fSEric Badger 		 * test expects that the first thread created (the main thread)
196982a4538fSEric Badger 		 * will be unsuspended first and will block the second thread
197082a4538fSEric Badger 		 * from running.
197182a4538fSEric Badger 		 */
197282a4538fSEric Badger 		CPU_ZERO(&setmask);
197382a4538fSEric Badger 		CPU_SET(0, &setmask);
197482a4538fSEric Badger 		cpusetid_t setid;
197582a4538fSEric Badger 		CHILD_REQUIRE(cpuset(&setid) == 0);
197682a4538fSEric Badger 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
197782a4538fSEric Badger 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
197882a4538fSEric Badger 
197982a4538fSEric Badger 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
198082a4538fSEric Badger 
198182a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
198282a4538fSEric Badger 		    (void*)&barrier) == 0);
198382a4538fSEric Badger 
198482a4538fSEric Badger 		sigset_t sigmask;
198582a4538fSEric Badger 		sigemptyset(&sigmask);
198682a4538fSEric Badger 		sigaddset(&sigmask, SIGUSR2);
198782a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
198882a4538fSEric Badger 
198982a4538fSEric Badger 		/* Sync up with other thread after sigmask updated. */
199082a4538fSEric Badger 		pthread_barrier_wait(&barrier);
199182a4538fSEric Badger 
199282a4538fSEric Badger 		/* Sync up with the test before doing the getpid(). */
199382a4538fSEric Badger 		raise(SIGSTOP);
199482a4538fSEric Badger 
199582a4538fSEric Badger 		getpid();
199682a4538fSEric Badger 		exit(1);
199782a4538fSEric Badger 	}
199882a4538fSEric Badger 
199982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
200082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
200182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
200282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
200382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
200482a4538fSEric Badger 
200582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
200682a4538fSEric Badger 	main_lwp = pl.pl_lwpid;
200782a4538fSEric Badger 
200882a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
200982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
201082a4538fSEric Badger 
201182a4538fSEric Badger 	/*
201282a4538fSEric Badger 	 * Continue until child is done with setup, which is indicated with
201382a4538fSEric Badger 	 * SIGSTOP. Ignore system calls in the meantime.
201482a4538fSEric Badger 	 */
201582a4538fSEric Badger 	for (;;) {
201682a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
201782a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
201882a4538fSEric Badger 		ATF_REQUIRE(WIFSTOPPED(status));
201982a4538fSEric Badger 		if (WSTOPSIG(status) == SIGTRAP) {
202082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
202182a4538fSEric Badger 			    sizeof(pl)) != -1);
202282a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
202382a4538fSEric Badger 		} else {
202482a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
202582a4538fSEric Badger 			break;
202682a4538fSEric Badger 		}
202782a4538fSEric Badger 		ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
202882a4538fSEric Badger 	}
202982a4538fSEric Badger 
203082a4538fSEric Badger 	/* Let both threads hit their syscall entries. */
203182a4538fSEric Badger 	for (i = 0; i < 2; ++i) {
203282a4538fSEric Badger 		ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
203382a4538fSEric Badger 
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) == SIGTRAP);
203882a4538fSEric Badger 
203982a4538fSEric Badger 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
204082a4538fSEric Badger 		    sizeof(pl)) != -1);
204182a4538fSEric Badger 		ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
204282a4538fSEric Badger 
204382a4538fSEric Badger 		/*
204482a4538fSEric Badger 		 * Prevent the main thread from hitting its syscall exit for
204582a4538fSEric Badger 		 * now.
204682a4538fSEric Badger 		 */
204782a4538fSEric Badger 		if (pl.pl_lwpid == main_lwp)
204882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0);
204982a4538fSEric Badger 
205082a4538fSEric Badger 	}
205182a4538fSEric Badger 
205282a4538fSEric Badger 	/* Send a signal that only the second thread can handle. */
205382a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
205482a4538fSEric Badger 
205582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
205682a4538fSEric Badger 
205782a4538fSEric Badger 	/* The second wait() should report the SIGUSR2. */
205882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
205982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
206082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
206182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
206282a4538fSEric Badger 
206382a4538fSEric Badger 	/* Allow the main thread to try to finish its system call. */
206482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_RESUME, main_lwp, 0, 0) == 0);
206582a4538fSEric Badger 
206682a4538fSEric Badger 	/*
206782a4538fSEric Badger 	 * At this point, the main thread is in the middle of a system call and
206882a4538fSEric Badger 	 * has been resumed. The second thread has taken a signal which will be
206982a4538fSEric Badger 	 * replaced with a SIGKILL. We expect the main thread will get to run
207082a4538fSEric Badger 	 * first. It should notice the kill request and exit accordingly and
207182a4538fSEric Badger 	 * not stop for the system call exit event.
207282a4538fSEric Badger 	 */
207382a4538fSEric Badger 
207482a4538fSEric Badger 	/* Replace the SIGUSR2 with a kill. */
207582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
207682a4538fSEric Badger 
207782a4538fSEric Badger 	/* The last wait() should report the SIGKILL (not a syscall exit). */
207882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
207982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
208082a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
208182a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
208282a4538fSEric Badger 
208382a4538fSEric Badger 	wpid = wait(&status);
208482a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
208582a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
208682a4538fSEric Badger }
208782a4538fSEric Badger 
208882a4538fSEric Badger static void
208982a4538fSEric Badger sigusr1_handler(int sig)
209082a4538fSEric Badger {
209182a4538fSEric Badger 
209282a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
209382a4538fSEric Badger 	_exit(2);
209482a4538fSEric Badger }
209582a4538fSEric Badger 
209682a4538fSEric Badger /*
209782a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
209882a4538fSEric Badger  * a PT_KILL will kill the process.
209982a4538fSEric Badger  */
210082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
210182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
210282a4538fSEric Badger {
210382a4538fSEric Badger 	pid_t fpid, wpid;
210482a4538fSEric Badger 	int status;
210582a4538fSEric Badger 	int max_pending_per_proc;
210682a4538fSEric Badger 	size_t len;
210782a4538fSEric Badger 	int i;
210882a4538fSEric Badger 
210982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
211082a4538fSEric Badger 
211182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
211282a4538fSEric Badger 	if (fpid == 0) {
211382a4538fSEric Badger 		trace_me();
211482a4538fSEric Badger 		exit(1);
211582a4538fSEric Badger 	}
211682a4538fSEric Badger 
211782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
211882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
211982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
212082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
212182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
212282a4538fSEric Badger 
212382a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
212482a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
212582a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
212682a4538fSEric Badger 
212782a4538fSEric Badger 	/* Fill the signal queue. */
212882a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
212982a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
213082a4538fSEric Badger 
213182a4538fSEric Badger 	/* Kill the child process. */
213282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
213382a4538fSEric Badger 
213482a4538fSEric Badger 	/* The last wait() should report the SIGKILL. */
213582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
213682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
213782a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
213882a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
213982a4538fSEric Badger 
214082a4538fSEric Badger 	wpid = wait(&status);
214182a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
214282a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
214382a4538fSEric Badger }
214482a4538fSEric Badger 
214582a4538fSEric Badger /*
214682a4538fSEric Badger  * Verify that when stopped at a system call entry, a signal can be
214782a4538fSEric Badger  * requested with PT_CONTINUE which will be delivered once the system
214882a4538fSEric Badger  * call is complete.
214982a4538fSEric Badger  */
215082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
215182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
215282a4538fSEric Badger {
215382a4538fSEric Badger 	struct ptrace_lwpinfo pl;
215482a4538fSEric Badger 	pid_t fpid, wpid;
215582a4538fSEric Badger 	int status;
215682a4538fSEric Badger 
215782a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
215882a4538fSEric Badger 
215982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
216082a4538fSEric Badger 	if (fpid == 0) {
216182a4538fSEric Badger 		trace_me();
216282a4538fSEric Badger 		getpid();
216382a4538fSEric Badger 		exit(1);
216482a4538fSEric Badger 	}
216582a4538fSEric Badger 
216682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
216782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
216882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
216982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
217082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
217182a4538fSEric Badger 
217282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
217382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
217482a4538fSEric Badger 
217582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
217682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
217782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
217882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
217982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
218082a4538fSEric Badger 
218182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
218282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
218382a4538fSEric Badger 
218482a4538fSEric Badger 	/* Continue the child process with a signal. */
218582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
218682a4538fSEric Badger 
218782a4538fSEric Badger 	for (;;) {
218882a4538fSEric Badger 		/*
218982a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
219082a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
219182a4538fSEric Badger 		 * past any syscall stops.
219282a4538fSEric Badger 		 */
219382a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
219482a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
219582a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
219682a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
219782a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
219882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
219982a4538fSEric Badger 		} else {
220082a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
220182a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
220282a4538fSEric Badger 			break;
220382a4538fSEric Badger 		}
220482a4538fSEric Badger 	}
220582a4538fSEric Badger 
220682a4538fSEric Badger 	wpid = wait(&status);
220782a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
220882a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
220982a4538fSEric Badger }
221082a4538fSEric Badger 
221182a4538fSEric Badger static void
221282a4538fSEric Badger sigusr1_counting_handler(int sig)
221382a4538fSEric Badger {
221482a4538fSEric Badger 	static int counter = 0;
221582a4538fSEric Badger 
221682a4538fSEric Badger 	CHILD_REQUIRE(sig == SIGUSR1);
221782a4538fSEric Badger 	counter++;
221882a4538fSEric Badger 	if (counter == 2)
221982a4538fSEric Badger 		_exit(2);
222082a4538fSEric Badger }
222182a4538fSEric Badger 
222282a4538fSEric Badger /*
222382a4538fSEric Badger  * Verify that, when continuing from a stop at system call entry and exit,
222482a4538fSEric Badger  * a signal can be requested from both stops, and both will be delivered when
222582a4538fSEric Badger  * the system call is complete.
222682a4538fSEric Badger  */
222782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
222882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
222982a4538fSEric Badger {
223082a4538fSEric Badger 	struct ptrace_lwpinfo pl;
223182a4538fSEric Badger 	pid_t fpid, wpid;
223282a4538fSEric Badger 	int status;
223382a4538fSEric Badger 
223482a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
223582a4538fSEric Badger 
223682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
223782a4538fSEric Badger 	if (fpid == 0) {
223882a4538fSEric Badger 		trace_me();
223982a4538fSEric Badger 		getpid();
224082a4538fSEric Badger 		exit(1);
224182a4538fSEric Badger 	}
224282a4538fSEric Badger 
224382a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
224482a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
224582a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
224682a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
224782a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
224882a4538fSEric Badger 
224982a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
225082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
225182a4538fSEric Badger 
225282a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
225382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
225482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
225582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
225682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
225782a4538fSEric Badger 
225882a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
225982a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
226082a4538fSEric Badger 
226182a4538fSEric Badger 	/* Continue the child process with a signal. */
226282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
226382a4538fSEric Badger 
226482a4538fSEric Badger 	/* The third wait() should report a system call exit for getpid(). */
226582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
226682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
226782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
226882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
226982a4538fSEric Badger 
227082a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
227182a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
227282a4538fSEric Badger 
227382a4538fSEric Badger 	/* Continue the child process with a signal. */
227482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
227582a4538fSEric Badger 
227682a4538fSEric Badger 	for (;;) {
227782a4538fSEric Badger 		/*
227882a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
227982a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
228082a4538fSEric Badger 		 * past any syscall stops.
228182a4538fSEric Badger 		 */
228282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
228382a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
228482a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
228582a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
228682a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
228782a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
228882a4538fSEric Badger 		} else {
228982a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
229082a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
229182a4538fSEric Badger 			break;
229282a4538fSEric Badger 		}
229382a4538fSEric Badger 	}
229482a4538fSEric Badger 
229582a4538fSEric Badger 	wpid = wait(&status);
229682a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
229782a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
229882a4538fSEric Badger }
229982a4538fSEric Badger 
230082a4538fSEric Badger /*
230182a4538fSEric Badger  * Verify that even if the signal queue is full for a child process,
230282a4538fSEric Badger  * a PT_CONTINUE with a signal will not result in loss of that signal.
230382a4538fSEric Badger  */
230482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
230582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
230682a4538fSEric Badger {
230782a4538fSEric Badger 	pid_t fpid, wpid;
230882a4538fSEric Badger 	int status;
230982a4538fSEric Badger 	int max_pending_per_proc;
231082a4538fSEric Badger 	size_t len;
231182a4538fSEric Badger 	int i;
231282a4538fSEric Badger 
231382a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
231482a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
231582a4538fSEric Badger 
231682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
231782a4538fSEric Badger 	if (fpid == 0) {
231882a4538fSEric Badger 		trace_me();
231982a4538fSEric Badger 		exit(1);
232082a4538fSEric Badger 	}
232182a4538fSEric Badger 
232282a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
232382a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
232482a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
232582a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
232682a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
232782a4538fSEric Badger 
232882a4538fSEric Badger 	len = sizeof(max_pending_per_proc);
232982a4538fSEric Badger 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
233082a4538fSEric Badger 	    &max_pending_per_proc, &len, NULL, 0) == 0);
233182a4538fSEric Badger 
233282a4538fSEric Badger 	/* Fill the signal queue. */
233382a4538fSEric Badger 	for (i = 0; i < max_pending_per_proc; ++i)
233482a4538fSEric Badger 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
233582a4538fSEric Badger 
233682a4538fSEric Badger 	/* Continue with signal. */
233782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
233882a4538fSEric Badger 
233982a4538fSEric Badger 	for (;;) {
234082a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
234182a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
234282a4538fSEric Badger 		if (WIFSTOPPED(status)) {
234382a4538fSEric Badger 			ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
234482a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
234582a4538fSEric Badger 		} else {
234682a4538fSEric Badger 			/*
234782a4538fSEric Badger 			 * The last wait() should report normal _exit from the
234882a4538fSEric Badger 			 * SIGUSR1 handler.
234982a4538fSEric Badger 			 */
235082a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
235182a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
235282a4538fSEric Badger 			break;
235382a4538fSEric Badger 		}
235482a4538fSEric Badger 	}
235582a4538fSEric Badger 
235682a4538fSEric Badger 	wpid = wait(&status);
235782a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
235882a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
235982a4538fSEric Badger }
236082a4538fSEric Badger 
236182a4538fSEric Badger /*
236282a4538fSEric Badger  * Verify that, after stopping due to a signal, that signal can be
236382a4538fSEric Badger  * replaced with another signal.
236482a4538fSEric Badger  */
236582a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
236682a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
236782a4538fSEric Badger {
236882a4538fSEric Badger 	struct ptrace_lwpinfo pl;
236982a4538fSEric Badger 	pid_t fpid, wpid;
237082a4538fSEric Badger 	int status;
237182a4538fSEric Badger 
237282a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
237382a4538fSEric Badger 	if (fpid == 0) {
237482a4538fSEric Badger 		trace_me();
237582a4538fSEric Badger 		sleep(20);
237682a4538fSEric Badger 		exit(1);
237782a4538fSEric Badger 	}
237882a4538fSEric Badger 
237982a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
238082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
238182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
238282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
238382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
238482a4538fSEric Badger 
238582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
238682a4538fSEric Badger 
238782a4538fSEric Badger 	/* Send a signal without ptrace. */
238882a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGINT) == 0);
238982a4538fSEric Badger 
239082a4538fSEric Badger 	/* The second wait() should report a SIGINT was received. */
239182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
239282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
239382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
239482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGINT);
239582a4538fSEric Badger 
239682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
239782a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
239882a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGINT);
239982a4538fSEric Badger 
240082a4538fSEric Badger 	/* Continue the child process with a different signal. */
240182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM) == 0);
240282a4538fSEric Badger 
240382a4538fSEric Badger 	/*
240482a4538fSEric Badger 	 * The last wait() should report having died due to the new
240582a4538fSEric Badger 	 * signal, SIGTERM.
240682a4538fSEric Badger 	 */
240782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
240882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
240982a4538fSEric Badger 	ATF_REQUIRE(WIFSIGNALED(status));
241082a4538fSEric Badger 	ATF_REQUIRE(WTERMSIG(status) == SIGTERM);
241182a4538fSEric Badger 
241282a4538fSEric Badger 	wpid = wait(&status);
241382a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
241482a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
241582a4538fSEric Badger }
241682a4538fSEric Badger 
241782a4538fSEric Badger /*
241882a4538fSEric Badger  * Verify that a signal can be passed through to the child even when there
241982a4538fSEric Badger  * was no true signal originally. Such cases arise when a SIGTRAP is
242082a4538fSEric Badger  * invented for e.g, system call stops.
242182a4538fSEric Badger  */
242282a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
242382a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
242482a4538fSEric Badger {
242582a4538fSEric Badger 	struct ptrace_lwpinfo pl;
242682a4538fSEric Badger 	pid_t fpid, wpid;
242782a4538fSEric Badger 	int status;
242882a4538fSEric Badger 
242982a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
243082a4538fSEric Badger 	if (fpid == 0) {
243182a4538fSEric Badger 		trace_me();
243282a4538fSEric Badger 		getpid();
243382a4538fSEric Badger 		exit(1);
243482a4538fSEric Badger 	}
243582a4538fSEric Badger 
243682a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
243782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
243882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
243982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
244082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
244182a4538fSEric Badger 
244282a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
244382a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
244482a4538fSEric Badger 
244582a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
244682a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
244782a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
244882a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
244982a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
245082a4538fSEric Badger 
245182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
245282a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
245382a4538fSEric Badger 
245482a4538fSEric Badger 	/* Continue the child process with a SIGTRAP. */
245582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP) == 0);
245682a4538fSEric Badger 
245782a4538fSEric Badger 	for (;;) {
245882a4538fSEric Badger 		/*
245982a4538fSEric Badger 		 * The last wait() should report exit due to SIGTRAP.  In the
246082a4538fSEric Badger 		 * meantime, catch and proceed past any syscall stops.
246182a4538fSEric Badger 		 */
246282a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
246382a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
246482a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
246582a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
246682a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
246782a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
246882a4538fSEric Badger 		} else {
246982a4538fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status));
247082a4538fSEric Badger 			ATF_REQUIRE(WTERMSIG(status) == SIGTRAP);
247182a4538fSEric Badger 			break;
247282a4538fSEric Badger 		}
247382a4538fSEric Badger 	}
247482a4538fSEric Badger 
247582a4538fSEric Badger 	wpid = wait(&status);
247682a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
247782a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
247882a4538fSEric Badger 
247982a4538fSEric Badger }
248082a4538fSEric Badger 
248182a4538fSEric Badger /*
248282a4538fSEric Badger  * A mixed bag PT_CONTINUE with signal test.
248382a4538fSEric Badger  */
248482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
248582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
248682a4538fSEric Badger {
248782a4538fSEric Badger 	struct ptrace_lwpinfo pl;
248882a4538fSEric Badger 	pid_t fpid, wpid;
248982a4538fSEric Badger 	int status;
249082a4538fSEric Badger 
249182a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
249282a4538fSEric Badger 
249382a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
249482a4538fSEric Badger 	if (fpid == 0) {
249582a4538fSEric Badger 		trace_me();
249682a4538fSEric Badger 		getpid();
249782a4538fSEric Badger 		exit(1);
249882a4538fSEric Badger 	}
249982a4538fSEric Badger 
250082a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
250182a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
250282a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
250382a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
250482a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
250582a4538fSEric Badger 
250682a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
250782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
250882a4538fSEric Badger 
250982a4538fSEric Badger 	/* The second wait() should report a system call entry for getpid(). */
251082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
251182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
251282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
251382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
251482a4538fSEric Badger 
251582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
251682a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
251782a4538fSEric Badger 
251882a4538fSEric Badger 	/* Continue with the first SIGUSR1. */
251982a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
252082a4538fSEric Badger 
252182a4538fSEric Badger 	/* The next wait() should report a system call exit for getpid(). */
252282a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
252382a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
252482a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
252582a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
252682a4538fSEric Badger 
252782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
252882a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
252982a4538fSEric Badger 
253082a4538fSEric Badger 	/* Send an ABRT without ptrace. */
253182a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGABRT) == 0);
253282a4538fSEric Badger 
253382a4538fSEric Badger 	/* Continue normally. */
253482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
253582a4538fSEric Badger 
253682a4538fSEric Badger 	/* The next wait() should report the SIGABRT. */
253782a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
253882a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
253982a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
254082a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
254182a4538fSEric Badger 
254282a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
254382a4538fSEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
254482a4538fSEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
254582a4538fSEric Badger 
254682a4538fSEric Badger 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
254782a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
254882a4538fSEric Badger 
254982a4538fSEric Badger 	for (;;) {
255082a4538fSEric Badger 		/*
255182a4538fSEric Badger 		 * The last wait() should report exit 2, i.e., a normal _exit
255282a4538fSEric Badger 		 * from the signal handler. In the meantime, catch and proceed
255382a4538fSEric Badger 		 * past any syscall stops.
255482a4538fSEric Badger 		 */
255582a4538fSEric Badger 		wpid = waitpid(fpid, &status, 0);
255682a4538fSEric Badger 		ATF_REQUIRE(wpid == fpid);
255782a4538fSEric Badger 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
255882a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
255982a4538fSEric Badger 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
256082a4538fSEric Badger 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
256182a4538fSEric Badger 		} else {
256282a4538fSEric Badger 			ATF_REQUIRE(WIFEXITED(status));
256382a4538fSEric Badger 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
256482a4538fSEric Badger 			break;
256582a4538fSEric Badger 		}
256682a4538fSEric Badger 	}
256782a4538fSEric Badger 
256882a4538fSEric Badger 	wpid = wait(&status);
256982a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
257082a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
257182a4538fSEric Badger 
257282a4538fSEric Badger }
257382a4538fSEric Badger 
257482a4538fSEric Badger /*
257582a4538fSEric Badger  * Verify a signal delivered by ptrace is noticed by kevent(2).
257682a4538fSEric Badger  */
257782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
257882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
257982a4538fSEric Badger {
258082a4538fSEric Badger 	pid_t fpid, wpid;
258182a4538fSEric Badger 	int status, kq, nevents;
258282a4538fSEric Badger 	struct kevent kev;
258382a4538fSEric Badger 
258482a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
258582a4538fSEric Badger 
258682a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
258782a4538fSEric Badger 	if (fpid == 0) {
258882a4538fSEric Badger 		CHILD_REQUIRE((kq = kqueue()) > 0);
258982a4538fSEric Badger 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
259082a4538fSEric Badger 		CHILD_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0);
259182a4538fSEric Badger 
259282a4538fSEric Badger 		trace_me();
259382a4538fSEric Badger 
259482a4538fSEric Badger 		for (;;) {
259582a4538fSEric Badger 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
259682a4538fSEric Badger 			if (nevents == -1 && errno == EINTR)
259782a4538fSEric Badger 				continue;
259882a4538fSEric Badger 			CHILD_REQUIRE(nevents > 0);
259982a4538fSEric Badger 			CHILD_REQUIRE(kev.filter == EVFILT_SIGNAL);
260082a4538fSEric Badger 			CHILD_REQUIRE(kev.ident == SIGUSR1);
260182a4538fSEric Badger 			break;
260282a4538fSEric Badger 		}
260382a4538fSEric Badger 
260482a4538fSEric Badger 		exit(1);
260582a4538fSEric Badger 	}
260682a4538fSEric Badger 
260782a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
260882a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
260982a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
261082a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
261182a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
261282a4538fSEric Badger 
261382a4538fSEric Badger 	/* Continue with the SIGUSR1. */
261482a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
261582a4538fSEric Badger 
261682a4538fSEric Badger 	/*
261782a4538fSEric Badger 	 * The last wait() should report normal exit with code 1.
261882a4538fSEric Badger 	 */
261982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
262082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
262182a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
262282a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
262382a4538fSEric Badger 
262482a4538fSEric Badger 	wpid = wait(&status);
262582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
262682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
262782a4538fSEric Badger }
262882a4538fSEric Badger 
262982a4538fSEric Badger static sem_t sigusr1_sem;
263082a4538fSEric Badger 
263182a4538fSEric Badger static void
263282a4538fSEric Badger sigusr1_sempost_handler(int sig __unused)
263382a4538fSEric Badger {
263482a4538fSEric Badger 
263582a4538fSEric Badger 	CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0);
263682a4538fSEric Badger }
263782a4538fSEric Badger 
263882a4538fSEric Badger static void *
263982a4538fSEric Badger signal_thread(void *arg)
264082a4538fSEric Badger {
264182a4538fSEric Badger 	int err;
264282a4538fSEric Badger 	sigset_t sigmask;
264382a4538fSEric Badger 
264482a4538fSEric Badger 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
264582a4538fSEric Badger 
264682a4538fSEric Badger 	/* Wait for this thread to receive a SIGUSR1. */
264782a4538fSEric Badger 	do {
264882a4538fSEric Badger 		err = sem_wait(&sigusr1_sem);
264982a4538fSEric Badger 		CHILD_REQUIRE(err == 0 || errno == EINTR);
265082a4538fSEric Badger 	} while (err != 0 && errno == EINTR);
265182a4538fSEric Badger 
265282a4538fSEric Badger 	/* Free our companion thread from the barrier. */
265382a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
265482a4538fSEric Badger 
265582a4538fSEric Badger 	/*
265682a4538fSEric Badger 	 * Swap ignore duties; the next SIGUSR1 should go to the
265782a4538fSEric Badger 	 * other thread.
265882a4538fSEric Badger 	 */
265982a4538fSEric Badger 	CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
266082a4538fSEric Badger 	CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
266182a4538fSEric Badger 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
266282a4538fSEric Badger 
266382a4538fSEric Badger 	/* Sync up threads after swapping signal masks. */
266482a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
266582a4538fSEric Badger 
266682a4538fSEric Badger 	/* Wait until our companion has received its SIGUSR1. */
266782a4538fSEric Badger 	pthread_barrier_wait(pbarrier);
266882a4538fSEric Badger 
266982a4538fSEric Badger 	return (NULL);
267082a4538fSEric Badger }
267182a4538fSEric Badger 
267282a4538fSEric Badger /*
267382a4538fSEric Badger  * Verify that if ptrace stops due to a signal but continues with
267482a4538fSEric Badger  * a different signal that the new signal is routed to a thread
267582a4538fSEric Badger  * that can accept it, and that that thread is awakened by the signal
267682a4538fSEric Badger  * in a timely manner.
267782a4538fSEric Badger  */
267882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
267982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
268082a4538fSEric Badger {
268182a4538fSEric Badger 	pid_t fpid, wpid;
268282a4538fSEric Badger 	int status, err;
268382a4538fSEric Badger 	pthread_t t;
268482a4538fSEric Badger 	sigset_t sigmask;
268582a4538fSEric Badger 	pthread_barrier_t barrier;
268682a4538fSEric Badger 
268782a4538fSEric Badger 	ATF_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
268882a4538fSEric Badger 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
268982a4538fSEric Badger 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
269082a4538fSEric Badger 
269182a4538fSEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
269282a4538fSEric Badger 	if (fpid == 0) {
269382a4538fSEric Badger 		CHILD_REQUIRE(pthread_create(&t, NULL, signal_thread, (void*)&barrier) == 0);
269482a4538fSEric Badger 
269582a4538fSEric Badger 		/* The other thread should receive the first SIGUSR1. */
269682a4538fSEric Badger 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
269782a4538fSEric Badger 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
269882a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
269982a4538fSEric Badger 
270082a4538fSEric Badger 		trace_me();
270182a4538fSEric Badger 
270282a4538fSEric Badger 		/* Wait until other thread has received its SIGUSR1. */
270382a4538fSEric Badger 		pthread_barrier_wait(&barrier);
270482a4538fSEric Badger 
270582a4538fSEric Badger 		/*
270682a4538fSEric Badger 		 * Swap ignore duties; the next SIGUSR1 should go to this
270782a4538fSEric Badger 		 * thread.
270882a4538fSEric Badger 		 */
270982a4538fSEric Badger 		CHILD_REQUIRE(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
271082a4538fSEric Badger 
271182a4538fSEric Badger 		/* Sync up threads after swapping signal masks. */
271282a4538fSEric Badger 		pthread_barrier_wait(&barrier);
271382a4538fSEric Badger 
271482a4538fSEric Badger 		/*
271582a4538fSEric Badger 		 * Sync up with test code; we're ready for the next SIGUSR1
271682a4538fSEric Badger 		 * now.
271782a4538fSEric Badger 		 */
271882a4538fSEric Badger 		raise(SIGSTOP);
271982a4538fSEric Badger 
272082a4538fSEric Badger 		/* Wait for this thread to receive a SIGUSR1. */
272182a4538fSEric Badger 		do {
272282a4538fSEric Badger 			err = sem_wait(&sigusr1_sem);
272382a4538fSEric Badger 			CHILD_REQUIRE(err == 0 || errno == EINTR);
272482a4538fSEric Badger 		} while (err != 0 && errno == EINTR);
272582a4538fSEric Badger 
272682a4538fSEric Badger 		/* Free the other thread from the barrier. */
272782a4538fSEric Badger 		pthread_barrier_wait(&barrier);
272882a4538fSEric Badger 
272982a4538fSEric Badger 		CHILD_REQUIRE(pthread_join(t, NULL) == 0);
273082a4538fSEric Badger 
273182a4538fSEric Badger 		exit(1);
273282a4538fSEric Badger 	}
273382a4538fSEric Badger 
273482a4538fSEric Badger 	/* The first wait() should report the stop from SIGSTOP. */
273582a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
273682a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
273782a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
273882a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
273982a4538fSEric Badger 
274082a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
274182a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
274282a4538fSEric Badger 
274382a4538fSEric Badger 	/*
274482a4538fSEric Badger 	 * Send a signal without ptrace that either thread will accept (USR2,
274582a4538fSEric Badger 	 * in this case).
274682a4538fSEric Badger 	 */
274782a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
274882a4538fSEric Badger 
274982a4538fSEric Badger 	/* The second wait() should report a SIGUSR2 was received. */
275082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
275182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
275282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
275382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
275482a4538fSEric Badger 
275582a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
275682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
275782a4538fSEric Badger 
275882a4538fSEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
275982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
276082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
276182a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
276282a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
276382a4538fSEric Badger 
276482a4538fSEric Badger 	/* Continue the child ignoring the SIGSTOP. */
276582a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
276682a4538fSEric Badger 
276782a4538fSEric Badger 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
276882a4538fSEric Badger 
276982a4538fSEric Badger 	/* The next wait() should report a SIGUSR2 was received. */
277082a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
277182a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
277282a4538fSEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
277382a4538fSEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
277482a4538fSEric Badger 
277582a4538fSEric Badger 	/* Continue the child, changing the signal to USR1. */
277682a4538fSEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
277782a4538fSEric Badger 
277882a4538fSEric Badger 	/* The last wait() should report normal exit with code 1. */
277982a4538fSEric Badger 	wpid = waitpid(fpid, &status, 0);
278082a4538fSEric Badger 	ATF_REQUIRE(wpid == fpid);
278182a4538fSEric Badger 	ATF_REQUIRE(WIFEXITED(status));
278282a4538fSEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
278382a4538fSEric Badger 
278482a4538fSEric Badger 	wpid = wait(&status);
278582a4538fSEric Badger 	ATF_REQUIRE(wpid == -1);
278682a4538fSEric Badger 	ATF_REQUIRE(errno == ECHILD);
278782a4538fSEric Badger }
278882a4538fSEric Badger 
2789b38bd91fSEric Badger static void *
2790b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused)
2791b38bd91fSEric Badger {
2792b38bd91fSEric Badger 
2793b38bd91fSEric Badger 	raise(SIGSTOP);
2794b38bd91fSEric Badger 	return NULL;
2795b38bd91fSEric Badger }
2796b38bd91fSEric Badger 
2797b38bd91fSEric Badger static void *
2798b38bd91fSEric Badger sleep_thread(void *arg __unused)
2799b38bd91fSEric Badger {
2800b38bd91fSEric Badger 
2801b38bd91fSEric Badger 	sleep(60);
2802b38bd91fSEric Badger 	return NULL;
2803b38bd91fSEric Badger }
2804b38bd91fSEric Badger 
2805b38bd91fSEric Badger static void
2806b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread)
2807b38bd91fSEric Badger {
2808b38bd91fSEric Badger 	pid_t fpid, wpid;
2809b38bd91fSEric Badger 	int status, i;
2810b38bd91fSEric Badger 	cpuset_t setmask;
2811b38bd91fSEric Badger 	cpusetid_t setid;
2812b38bd91fSEric Badger 	pthread_t t;
2813b38bd91fSEric Badger 
2814b38bd91fSEric Badger 	/*
2815b38bd91fSEric Badger 	 * Become the reaper for this process tree. We need to be able to check
2816b38bd91fSEric Badger 	 * that both child and grandchild have died.
2817b38bd91fSEric Badger 	 */
2818b38bd91fSEric Badger 	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
2819b38bd91fSEric Badger 
2820b38bd91fSEric Badger 	fpid = fork();
2821b38bd91fSEric Badger 	ATF_REQUIRE(fpid >= 0);
2822b38bd91fSEric Badger 	if (fpid == 0) {
2823b38bd91fSEric Badger 		fpid = fork();
2824b38bd91fSEric Badger 		CHILD_REQUIRE(fpid >= 0);
2825b38bd91fSEric Badger 		if (fpid == 0) {
2826b38bd91fSEric Badger 			trace_me();
2827b38bd91fSEric Badger 
2828b38bd91fSEric Badger 			/* Pin to CPU 0 to serialize thread execution. */
2829b38bd91fSEric Badger 			CPU_ZERO(&setmask);
2830b38bd91fSEric Badger 			CPU_SET(0, &setmask);
2831b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset(&setid) == 0);
2832b38bd91fSEric Badger 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
2833b38bd91fSEric Badger 			    CPU_WHICH_CPUSET, setid,
2834b38bd91fSEric Badger 			    sizeof(setmask), &setmask) == 0);
2835b38bd91fSEric Badger 
2836b38bd91fSEric Badger 			if (sigstop_from_main_thread) {
2837b38bd91fSEric Badger 				/*
2838b38bd91fSEric Badger 				 * We expect the SIGKILL sent when our parent
2839b38bd91fSEric Badger 				 * dies to be delivered to the new thread.
2840b38bd91fSEric Badger 				 * Raise the SIGSTOP in this thread so the
2841b38bd91fSEric Badger 				 * threads compete.
2842b38bd91fSEric Badger 				 */
2843b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
2844b38bd91fSEric Badger 				    sleep_thread, NULL) == 0);
2845b38bd91fSEric Badger 				raise(SIGSTOP);
2846b38bd91fSEric Badger 			} else {
2847b38bd91fSEric Badger 				/*
2848b38bd91fSEric Badger 				 * We expect the SIGKILL to be delivered to
2849b38bd91fSEric Badger 				 * this thread. After creating the new thread,
2850b38bd91fSEric Badger 				 * just get off the CPU so the other thread can
2851b38bd91fSEric Badger 				 * raise the SIGSTOP.
2852b38bd91fSEric Badger 				 */
2853b38bd91fSEric Badger 				CHILD_REQUIRE(pthread_create(&t, NULL,
2854b38bd91fSEric Badger 				    raise_sigstop_thread, NULL) == 0);
2855b38bd91fSEric Badger 				sleep(60);
2856b38bd91fSEric Badger 			}
2857b38bd91fSEric Badger 
2858b38bd91fSEric Badger 			exit(0);
2859b38bd91fSEric Badger 		}
2860b38bd91fSEric Badger 		/* First stop is trace_me() immediately after fork. */
2861b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
2862b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
2863b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
2864b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2865b38bd91fSEric Badger 
2866b38bd91fSEric Badger 		CHILD_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2867b38bd91fSEric Badger 
2868b38bd91fSEric Badger 		/* Second stop is from the raise(SIGSTOP). */
2869b38bd91fSEric Badger 		wpid = waitpid(fpid, &status, 0);
2870b38bd91fSEric Badger 		CHILD_REQUIRE(wpid == fpid);
2871b38bd91fSEric Badger 		CHILD_REQUIRE(WIFSTOPPED(status));
2872b38bd91fSEric Badger 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2873b38bd91fSEric Badger 
2874b38bd91fSEric Badger 		/*
2875b38bd91fSEric Badger 		 * Terminate tracing process without detaching. Our child
2876b38bd91fSEric Badger 		 * should be killed.
2877b38bd91fSEric Badger 		 */
2878b38bd91fSEric Badger 		exit(0);
2879b38bd91fSEric Badger 	}
2880b38bd91fSEric Badger 
2881b38bd91fSEric Badger 	/*
2882b38bd91fSEric Badger 	 * We should get a normal exit from our immediate child and a SIGKILL
2883b38bd91fSEric Badger 	 * exit from our grandchild. The latter case is the interesting one.
2884b38bd91fSEric Badger 	 * Our grandchild should not have stopped due to the SIGSTOP that was
2885b38bd91fSEric Badger 	 * left dangling when its parent died.
2886b38bd91fSEric Badger 	 */
2887b38bd91fSEric Badger 	for (i = 0; i < 2; ++i) {
2888b38bd91fSEric Badger 		wpid = wait(&status);
2889b38bd91fSEric Badger 		if (wpid == fpid)
2890b38bd91fSEric Badger 			ATF_REQUIRE(WIFEXITED(status) &&
2891b38bd91fSEric Badger 			    WEXITSTATUS(status) == 0);
2892b38bd91fSEric Badger 		else
2893b38bd91fSEric Badger 			ATF_REQUIRE(WIFSIGNALED(status) &&
2894b38bd91fSEric Badger 			    WTERMSIG(status) == SIGKILL);
2895b38bd91fSEric Badger 	}
2896b38bd91fSEric Badger }
2897b38bd91fSEric Badger 
2898b38bd91fSEric Badger /*
2899b38bd91fSEric Badger  * These two tests ensure that if the tracing process exits without detaching
2900b38bd91fSEric Badger  * just after the child received a SIGSTOP, the child is cleanly killed and
2901b38bd91fSEric Badger  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
2902b38bd91fSEric Badger  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
2903b38bd91fSEric Badger  * different threads, the SIGKILL must win.  There are two variants of this
2904b38bd91fSEric Badger  * test, designed to catch the case where the SIGKILL is delivered to the
2905b38bd91fSEric Badger  * younger thread (the first test) and the case where the SIGKILL is delivered
2906b38bd91fSEric Badger  * to the older thread (the second test). This behavior has changed in the
2907b38bd91fSEric Badger  * past, so make no assumption.
2908b38bd91fSEric Badger  */
2909b38bd91fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__parent_terminate_with_pending_sigstop1);
2910b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
2911b38bd91fSEric Badger {
2912b38bd91fSEric Badger 
2913b38bd91fSEric Badger 	terminate_with_pending_sigstop(true);
2914b38bd91fSEric Badger }
2915b38bd91fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__parent_terminate_with_pending_sigstop2);
2916b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
2917b38bd91fSEric Badger {
2918b38bd91fSEric Badger 
2919b38bd91fSEric Badger 	terminate_with_pending_sigstop(false);
2920b38bd91fSEric Badger }
2921b38bd91fSEric Badger 
2922*b4d33259SEric Badger /*
2923*b4d33259SEric Badger  * Verify that after ptrace() discards a SIGKILL signal, the event mask
2924*b4d33259SEric Badger  * is not modified.
2925*b4d33259SEric Badger  */
2926*b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
2927*b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
2928*b4d33259SEric Badger {
2929*b4d33259SEric Badger 	struct ptrace_lwpinfo pl;
2930*b4d33259SEric Badger 	pid_t fpid, wpid;
2931*b4d33259SEric Badger 	int status, event_mask, new_event_mask;
2932*b4d33259SEric Badger 
2933*b4d33259SEric Badger 	ATF_REQUIRE((fpid = fork()) != -1);
2934*b4d33259SEric Badger 	if (fpid == 0) {
2935*b4d33259SEric Badger 		trace_me();
2936*b4d33259SEric Badger 		raise(SIGSTOP);
2937*b4d33259SEric Badger 		exit(0);
2938*b4d33259SEric Badger 	}
2939*b4d33259SEric Badger 
2940*b4d33259SEric Badger 	/* The first wait() should report the stop from trace_me(). */
2941*b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
2942*b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
2943*b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2944*b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2945*b4d33259SEric Badger 
2946*b4d33259SEric Badger 	/* Set several unobtrusive event bits. */
2947*b4d33259SEric Badger 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
2948*b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
2949*b4d33259SEric Badger 	    sizeof(event_mask)) == 0);
2950*b4d33259SEric Badger 
2951*b4d33259SEric Badger 	/* Send a SIGKILL without using ptrace. */
2952*b4d33259SEric Badger 	ATF_REQUIRE(kill(fpid, SIGKILL) == 0);
2953*b4d33259SEric Badger 
2954*b4d33259SEric Badger 	/* Continue the child ignoring the SIGSTOP. */
2955*b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2956*b4d33259SEric Badger 
2957*b4d33259SEric Badger 	/* The next stop should be due to the SIGKILL. */
2958*b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
2959*b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
2960*b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2961*b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGKILL);
2962*b4d33259SEric Badger 
2963*b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
2964*b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
2965*b4d33259SEric Badger 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGKILL);
2966*b4d33259SEric Badger 
2967*b4d33259SEric Badger 	/* Continue the child ignoring the SIGKILL. */
2968*b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2969*b4d33259SEric Badger 
2970*b4d33259SEric Badger 	/* The next wait() should report the stop from SIGSTOP. */
2971*b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
2972*b4d33259SEric Badger 	ATF_REQUIRE(wpid == fpid);
2973*b4d33259SEric Badger 	ATF_REQUIRE(WIFSTOPPED(status));
2974*b4d33259SEric Badger 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
2975*b4d33259SEric Badger 
2976*b4d33259SEric Badger 	/* Check the current event mask. It should not have changed. */
2977*b4d33259SEric Badger 	new_event_mask = 0;
2978*b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
2979*b4d33259SEric Badger 	    sizeof(new_event_mask)) == 0);
2980*b4d33259SEric Badger 	ATF_REQUIRE(event_mask == new_event_mask);
2981*b4d33259SEric Badger 
2982*b4d33259SEric Badger 	/* Continue the child to let it exit. */
2983*b4d33259SEric Badger 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
2984*b4d33259SEric Badger 
2985*b4d33259SEric Badger 	/* The last event should be for the child process's exit. */
2986*b4d33259SEric Badger 	wpid = waitpid(fpid, &status, 0);
2987*b4d33259SEric Badger 	ATF_REQUIRE(WIFEXITED(status));
2988*b4d33259SEric Badger 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
2989*b4d33259SEric Badger 
2990*b4d33259SEric Badger 	wpid = wait(&status);
2991*b4d33259SEric Badger 	ATF_REQUIRE(wpid == -1);
2992*b4d33259SEric Badger 	ATF_REQUIRE(errno == ECHILD);
2993*b4d33259SEric Badger }
2994*b4d33259SEric Badger 
2995c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp)
2996c209e3e2SJohn Baldwin {
2997c209e3e2SJohn Baldwin 
2998c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
2999c209e3e2SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
300057c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
300157c74f5bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
300298685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
300398685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
300498685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
300598685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
300698685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
300798685dc8SJohn Baldwin 	    ptrace__follow_fork_child_detached_unrelated_debugger);
300898685dc8SJohn Baldwin 	ATF_TP_ADD_TC(tp,
300998685dc8SJohn Baldwin 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
3010368b2b1cSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__getppid);
3011189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
3012189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
3013189ac973SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
30145fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
30155fcfab6eSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
30163340c45bSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
30178d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
30188d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
30198d570f64SJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
3020fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
3021fc4f075aSJohn Baldwin 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
3022e2ebfbbfSEric Badger #if defined(__amd64__) || defined(__i386__) || defined(__sparc64__)
302382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
3024e2ebfbbfSEric Badger #endif
302582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
302682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
302782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
302882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
302982a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
303082a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
303182a4538fSEric Badger 	ATF_TP_ADD_TC(tp,
303282a4538fSEric Badger 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
303382a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
303482a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
303582a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
303682a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
303782a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
303882a4538fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
3039b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
3040b38bd91fSEric Badger 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
3041*b4d33259SEric Badger 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
3042c209e3e2SJohn Baldwin 
3043c209e3e2SJohn Baldwin 	return (atf_no_error());
3044c209e3e2SJohn Baldwin }
3045