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