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 /* 55403e331dSJohn Baldwin * Architectures with a user-visible breakpoint(). 56403e331dSJohn Baldwin */ 57*a9c91abdSJohn Baldwin #if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \ 58*a9c91abdSJohn Baldwin defined(__i386__) || defined(__mips__) || defined(__riscv) || \ 59*a9c91abdSJohn Baldwin defined(__sparc64__) 60403e331dSJohn Baldwin #define HAVE_BREAKPOINT 61403e331dSJohn Baldwin #endif 62403e331dSJohn Baldwin 63403e331dSJohn Baldwin /* 64403e331dSJohn Baldwin * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap. 65403e331dSJohn Baldwin */ 66403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT 67*a9c91abdSJohn Baldwin #if defined(__aarch64__) 68*a9c91abdSJohn Baldwin #define SKIP_BREAK(reg) ((reg)->elr += 4) 69*a9c91abdSJohn Baldwin #elif defined(__amd64__) || defined(__i386__) 70403e331dSJohn Baldwin #define SKIP_BREAK(reg) 71*a9c91abdSJohn Baldwin #elif defined(__arm__) 72*a9c91abdSJohn Baldwin #define SKIP_BREAK(reg) ((reg)->r_pc += 4) 73bd061c39SJohn Baldwin #elif defined(__mips__) 74bd061c39SJohn Baldwin #define SKIP_BREAK(reg) ((reg)->r_regs[PC] += 4) 75ca75fa17SJohn Baldwin #elif defined(__riscv) 76ca75fa17SJohn Baldwin #define SKIP_BREAK(reg) ((reg)->sepc += 4) 77403e331dSJohn Baldwin #elif defined(__sparc64__) 78403e331dSJohn Baldwin #define SKIP_BREAK(reg) do { \ 79403e331dSJohn Baldwin (reg)->r_tpc = (reg)->r_tnpc + 4; \ 80403e331dSJohn Baldwin (reg)->r_tnpc += 8; \ 81403e331dSJohn Baldwin } while (0) 82403e331dSJohn Baldwin #endif 83403e331dSJohn Baldwin #endif 84403e331dSJohn Baldwin 85403e331dSJohn Baldwin /* 86dfa8ba12SJohn Baldwin * A variant of ATF_REQUIRE that is suitable for use in child 87dfa8ba12SJohn Baldwin * processes. This only works if the parent process is tripped up by 88dfa8ba12SJohn Baldwin * the early exit and fails some requirement itself. 89dfa8ba12SJohn Baldwin */ 90dfa8ba12SJohn Baldwin #define CHILD_REQUIRE(exp) do { \ 91dfa8ba12SJohn Baldwin if (!(exp)) \ 92dfa8ba12SJohn Baldwin child_fail_require(__FILE__, __LINE__, \ 93dfa8ba12SJohn Baldwin #exp " not met"); \ 94dfa8ba12SJohn Baldwin } while (0) 95dfa8ba12SJohn Baldwin 9698685dc8SJohn Baldwin static __dead2 void 97dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str) 98dfa8ba12SJohn Baldwin { 99dfa8ba12SJohn Baldwin char buf[128]; 100dfa8ba12SJohn Baldwin 101dfa8ba12SJohn Baldwin snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str); 102dfa8ba12SJohn Baldwin write(2, buf, strlen(buf)); 103dfa8ba12SJohn Baldwin _exit(32); 104dfa8ba12SJohn Baldwin } 105dfa8ba12SJohn Baldwin 10698685dc8SJohn Baldwin static void 10798685dc8SJohn Baldwin trace_me(void) 10898685dc8SJohn Baldwin { 10998685dc8SJohn Baldwin 11098685dc8SJohn Baldwin /* Attach the parent process as a tracer of this process. */ 11198685dc8SJohn Baldwin CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11298685dc8SJohn Baldwin 11398685dc8SJohn Baldwin /* Trigger a stop. */ 11498685dc8SJohn Baldwin raise(SIGSTOP); 11598685dc8SJohn Baldwin } 11698685dc8SJohn Baldwin 11798685dc8SJohn Baldwin static void 11898685dc8SJohn Baldwin attach_child(pid_t pid) 11998685dc8SJohn Baldwin { 12098685dc8SJohn Baldwin pid_t wpid; 12198685dc8SJohn Baldwin int status; 12298685dc8SJohn Baldwin 12398685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0); 12498685dc8SJohn Baldwin 12598685dc8SJohn Baldwin wpid = waitpid(pid, &status, 0); 12698685dc8SJohn Baldwin ATF_REQUIRE(wpid == pid); 12798685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 12898685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 12998685dc8SJohn Baldwin } 13098685dc8SJohn Baldwin 13198685dc8SJohn Baldwin static void 13298685dc8SJohn Baldwin wait_for_zombie(pid_t pid) 13398685dc8SJohn Baldwin { 13498685dc8SJohn Baldwin 13598685dc8SJohn Baldwin /* 13698685dc8SJohn Baldwin * Wait for a process to exit. This is kind of gross, but 13798685dc8SJohn Baldwin * there is not a better way. 1383a014c56SJohn Baldwin * 1393a014c56SJohn Baldwin * Prior to r325719, the kern.proc.pid.<pid> sysctl failed 1403a014c56SJohn Baldwin * with ESRCH. After that change, a valid struct kinfo_proc 1413a014c56SJohn Baldwin * is returned for zombies with ki_stat set to SZOMB. 14298685dc8SJohn Baldwin */ 14398685dc8SJohn Baldwin for (;;) { 14498685dc8SJohn Baldwin struct kinfo_proc kp; 14598685dc8SJohn Baldwin size_t len; 14698685dc8SJohn Baldwin int mib[4]; 14798685dc8SJohn Baldwin 14898685dc8SJohn Baldwin mib[0] = CTL_KERN; 14998685dc8SJohn Baldwin mib[1] = KERN_PROC; 15098685dc8SJohn Baldwin mib[2] = KERN_PROC_PID; 15198685dc8SJohn Baldwin mib[3] = pid; 15298685dc8SJohn Baldwin len = sizeof(kp); 15398685dc8SJohn Baldwin if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) { 15498685dc8SJohn Baldwin ATF_REQUIRE(errno == ESRCH); 15598685dc8SJohn Baldwin break; 15698685dc8SJohn Baldwin } 1573a014c56SJohn Baldwin if (kp.ki_stat == SZOMB) 1583a014c56SJohn Baldwin break; 15998685dc8SJohn Baldwin usleep(5000); 16098685dc8SJohn Baldwin } 16198685dc8SJohn Baldwin } 16298685dc8SJohn Baldwin 163dfa8ba12SJohn Baldwin /* 164c209e3e2SJohn Baldwin * Verify that a parent debugger process "sees" the exit of a debugged 165c209e3e2SJohn Baldwin * process exactly once when attached via PT_TRACE_ME. 166c209e3e2SJohn Baldwin */ 167c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me); 168c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc) 169c209e3e2SJohn Baldwin { 170c209e3e2SJohn Baldwin pid_t child, wpid; 171c209e3e2SJohn Baldwin int status; 172c209e3e2SJohn Baldwin 173c209e3e2SJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 174c209e3e2SJohn Baldwin if (child == 0) { 175c209e3e2SJohn Baldwin /* Child process. */ 17698685dc8SJohn Baldwin trace_me(); 177c209e3e2SJohn Baldwin 178b98cb919SJohn Baldwin _exit(1); 179c209e3e2SJohn Baldwin } 180c209e3e2SJohn Baldwin 181c209e3e2SJohn Baldwin /* Parent process. */ 182c209e3e2SJohn Baldwin 183c209e3e2SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 184c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 185c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 186c209e3e2SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 187c209e3e2SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 188c209e3e2SJohn Baldwin 189c209e3e2SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 190c209e3e2SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 191c209e3e2SJohn Baldwin 192c209e3e2SJohn Baldwin /* The second wait() should report the exit status. */ 193c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 194c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 195c209e3e2SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 196c209e3e2SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 197c209e3e2SJohn Baldwin 198c209e3e2SJohn Baldwin /* The child should no longer exist. */ 199c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 200c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == -1); 201c209e3e2SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 202c209e3e2SJohn Baldwin } 203c209e3e2SJohn Baldwin 204c209e3e2SJohn Baldwin /* 205c209e3e2SJohn Baldwin * Verify that a parent debugger process "sees" the exit of a debugged 206c209e3e2SJohn Baldwin * process exactly once when attached via PT_ATTACH. 207c209e3e2SJohn Baldwin */ 208c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach); 209c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc) 210c209e3e2SJohn Baldwin { 211c209e3e2SJohn Baldwin pid_t child, wpid; 212c209e3e2SJohn Baldwin int cpipe[2], status; 213c209e3e2SJohn Baldwin char c; 214c209e3e2SJohn Baldwin 215c209e3e2SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 216c209e3e2SJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 217c209e3e2SJohn Baldwin if (child == 0) { 218c209e3e2SJohn Baldwin /* Child process. */ 219c209e3e2SJohn Baldwin close(cpipe[0]); 220c209e3e2SJohn Baldwin 221c209e3e2SJohn Baldwin /* Wait for the parent to attach. */ 222dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0); 223c209e3e2SJohn Baldwin 224b98cb919SJohn Baldwin _exit(1); 225c209e3e2SJohn Baldwin } 226c209e3e2SJohn Baldwin close(cpipe[1]); 227c209e3e2SJohn Baldwin 228c209e3e2SJohn Baldwin /* Parent process. */ 229c209e3e2SJohn Baldwin 230c209e3e2SJohn Baldwin /* Attach to the child process. */ 23198685dc8SJohn Baldwin attach_child(child); 232c209e3e2SJohn Baldwin 233c209e3e2SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 234c209e3e2SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 235c209e3e2SJohn Baldwin 236c209e3e2SJohn Baldwin /* Signal the child to exit. */ 237c209e3e2SJohn Baldwin close(cpipe[0]); 238c209e3e2SJohn Baldwin 239c209e3e2SJohn Baldwin /* The second wait() should report the exit status. */ 240c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 241c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 242c209e3e2SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 243c209e3e2SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 244c209e3e2SJohn Baldwin 245c209e3e2SJohn Baldwin /* The child should no longer exist. */ 246c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 247c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == -1); 248c209e3e2SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 249c209e3e2SJohn Baldwin } 250c209e3e2SJohn Baldwin 25157c74f5bSJohn Baldwin /* 25257c74f5bSJohn Baldwin * Verify that a parent process "sees" the exit of a debugged process only 25357c74f5bSJohn Baldwin * after the debugger has seen it. 25457c74f5bSJohn Baldwin */ 25557c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger); 25657c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc) 25757c74f5bSJohn Baldwin { 25857c74f5bSJohn Baldwin pid_t child, debugger, wpid; 25957c74f5bSJohn Baldwin int cpipe[2], dpipe[2], status; 26057c74f5bSJohn Baldwin char c; 26157c74f5bSJohn Baldwin 26257c74f5bSJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 26357c74f5bSJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 26457c74f5bSJohn Baldwin 26557c74f5bSJohn Baldwin if (child == 0) { 26657c74f5bSJohn Baldwin /* Child process. */ 26757c74f5bSJohn Baldwin close(cpipe[0]); 26857c74f5bSJohn Baldwin 26957c74f5bSJohn Baldwin /* Wait for parent to be ready. */ 270dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 27157c74f5bSJohn Baldwin 272b98cb919SJohn Baldwin _exit(1); 27357c74f5bSJohn Baldwin } 27457c74f5bSJohn Baldwin close(cpipe[1]); 27557c74f5bSJohn Baldwin 27657c74f5bSJohn Baldwin ATF_REQUIRE(pipe(dpipe) == 0); 27757c74f5bSJohn Baldwin ATF_REQUIRE((debugger = fork()) != -1); 27857c74f5bSJohn Baldwin 27957c74f5bSJohn Baldwin if (debugger == 0) { 28057c74f5bSJohn Baldwin /* Debugger process. */ 28157c74f5bSJohn Baldwin close(dpipe[0]); 28257c74f5bSJohn Baldwin 283dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 28457c74f5bSJohn Baldwin 28557c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 286dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 287dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFSTOPPED(status)); 288dfa8ba12SJohn Baldwin CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 28957c74f5bSJohn Baldwin 290dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 29157c74f5bSJohn Baldwin 29257c74f5bSJohn Baldwin /* Signal parent that debugger is attached. */ 293dfa8ba12SJohn Baldwin CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 29457c74f5bSJohn Baldwin 29557c74f5bSJohn Baldwin /* Wait for parent's failed wait. */ 296dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0); 29757c74f5bSJohn Baldwin 29857c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 299dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 300dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 301dfa8ba12SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 1); 30257c74f5bSJohn Baldwin 303b98cb919SJohn Baldwin _exit(0); 30457c74f5bSJohn Baldwin } 30557c74f5bSJohn Baldwin close(dpipe[1]); 30657c74f5bSJohn Baldwin 30757c74f5bSJohn Baldwin /* Parent process. */ 30857c74f5bSJohn Baldwin 30957c74f5bSJohn Baldwin /* Wait for the debugger to attach to the child. */ 31057c74f5bSJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 31157c74f5bSJohn Baldwin 31257c74f5bSJohn Baldwin /* Release the child. */ 31357c74f5bSJohn Baldwin ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 31457c74f5bSJohn Baldwin ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0); 31557c74f5bSJohn Baldwin close(cpipe[0]); 31657c74f5bSJohn Baldwin 31798685dc8SJohn Baldwin wait_for_zombie(child); 31857c74f5bSJohn Baldwin 31957c74f5bSJohn Baldwin /* 3202f021998SJohn Baldwin * This wait should return a pid of 0 to indicate no status to 3212f021998SJohn Baldwin * report. The parent should see the child as non-exited 3222f021998SJohn Baldwin * until the debugger sees the exit. 32357c74f5bSJohn Baldwin */ 32457c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 32557c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 32657c74f5bSJohn Baldwin 32757c74f5bSJohn Baldwin /* Signal the debugger to wait for the child. */ 32857c74f5bSJohn Baldwin close(dpipe[0]); 32957c74f5bSJohn Baldwin 33057c74f5bSJohn Baldwin /* Wait for the debugger. */ 33157c74f5bSJohn Baldwin wpid = waitpid(debugger, &status, 0); 33257c74f5bSJohn Baldwin ATF_REQUIRE(wpid == debugger); 33357c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 33457c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 33557c74f5bSJohn Baldwin 33657c74f5bSJohn Baldwin /* The child process should now be ready. */ 33757c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 33857c74f5bSJohn Baldwin ATF_REQUIRE(wpid == child); 33957c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 34057c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 34157c74f5bSJohn Baldwin } 34257c74f5bSJohn Baldwin 34357c74f5bSJohn Baldwin /* 34457c74f5bSJohn Baldwin * Verify that a parent process "sees" the exit of a debugged process 34557c74f5bSJohn Baldwin * only after a non-direct-child debugger has seen it. In particular, 34657c74f5bSJohn Baldwin * various wait() calls in the parent must avoid failing with ESRCH by 34757c74f5bSJohn Baldwin * checking the parent's orphan list for the debugee. 34857c74f5bSJohn Baldwin */ 34957c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger); 35057c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc) 35157c74f5bSJohn Baldwin { 35257c74f5bSJohn Baldwin pid_t child, debugger, fpid, wpid; 35357c74f5bSJohn Baldwin int cpipe[2], dpipe[2], status; 35457c74f5bSJohn Baldwin char c; 35557c74f5bSJohn Baldwin 35657c74f5bSJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 35757c74f5bSJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 35857c74f5bSJohn Baldwin 35957c74f5bSJohn Baldwin if (child == 0) { 36057c74f5bSJohn Baldwin /* Child process. */ 36157c74f5bSJohn Baldwin close(cpipe[0]); 36257c74f5bSJohn Baldwin 36357c74f5bSJohn Baldwin /* Wait for parent to be ready. */ 364dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 36557c74f5bSJohn Baldwin 366b98cb919SJohn Baldwin _exit(1); 36757c74f5bSJohn Baldwin } 36857c74f5bSJohn Baldwin close(cpipe[1]); 36957c74f5bSJohn Baldwin 37057c74f5bSJohn Baldwin ATF_REQUIRE(pipe(dpipe) == 0); 37157c74f5bSJohn Baldwin ATF_REQUIRE((debugger = fork()) != -1); 37257c74f5bSJohn Baldwin 37357c74f5bSJohn Baldwin if (debugger == 0) { 37457c74f5bSJohn Baldwin /* Debugger parent. */ 37557c74f5bSJohn Baldwin 37657c74f5bSJohn Baldwin /* 37757c74f5bSJohn Baldwin * Fork again and drop the debugger parent so that the 37857c74f5bSJohn Baldwin * debugger is not a child of the main parent. 37957c74f5bSJohn Baldwin */ 380dfa8ba12SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 38157c74f5bSJohn Baldwin if (fpid != 0) 382b98cb919SJohn Baldwin _exit(2); 38357c74f5bSJohn Baldwin 38457c74f5bSJohn Baldwin /* Debugger process. */ 38557c74f5bSJohn Baldwin close(dpipe[0]); 38657c74f5bSJohn Baldwin 387dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 38857c74f5bSJohn Baldwin 38957c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 390dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 391dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFSTOPPED(status)); 392dfa8ba12SJohn Baldwin CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 39357c74f5bSJohn Baldwin 394dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 39557c74f5bSJohn Baldwin 39657c74f5bSJohn Baldwin /* Signal parent that debugger is attached. */ 397dfa8ba12SJohn Baldwin CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 39857c74f5bSJohn Baldwin 39957c74f5bSJohn Baldwin /* Wait for parent's failed wait. */ 400dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c)); 40157c74f5bSJohn Baldwin 40257c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 403dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 404dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 405dfa8ba12SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 1); 40657c74f5bSJohn Baldwin 407b98cb919SJohn Baldwin _exit(0); 40857c74f5bSJohn Baldwin } 409eddb85c6SJohn Baldwin close(dpipe[1]); 41057c74f5bSJohn Baldwin 41157c74f5bSJohn Baldwin /* Parent process. */ 41257c74f5bSJohn Baldwin 41357c74f5bSJohn Baldwin /* Wait for the debugger parent process to exit. */ 41457c74f5bSJohn Baldwin wpid = waitpid(debugger, &status, 0); 41557c74f5bSJohn Baldwin ATF_REQUIRE(wpid == debugger); 41657c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 41757c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 41857c74f5bSJohn Baldwin 41957c74f5bSJohn Baldwin /* A WNOHANG wait here should see the non-exited child. */ 42057c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 42157c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 42257c74f5bSJohn Baldwin 42357c74f5bSJohn Baldwin /* Wait for the debugger to attach to the child. */ 42457c74f5bSJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 42557c74f5bSJohn Baldwin 42657c74f5bSJohn Baldwin /* Release the child. */ 42757c74f5bSJohn Baldwin ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 42857c74f5bSJohn Baldwin ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0); 42957c74f5bSJohn Baldwin close(cpipe[0]); 43057c74f5bSJohn Baldwin 43198685dc8SJohn Baldwin wait_for_zombie(child); 43257c74f5bSJohn Baldwin 43357c74f5bSJohn Baldwin /* 4342f021998SJohn Baldwin * This wait should return a pid of 0 to indicate no status to 4352f021998SJohn Baldwin * report. The parent should see the child as non-exited 4362f021998SJohn Baldwin * until the debugger sees the exit. 43757c74f5bSJohn Baldwin */ 43857c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 43957c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 44057c74f5bSJohn Baldwin 44157c74f5bSJohn Baldwin /* Signal the debugger to wait for the child. */ 442eddb85c6SJohn Baldwin ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c)); 44357c74f5bSJohn Baldwin 44457c74f5bSJohn Baldwin /* Wait for the debugger. */ 445eddb85c6SJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0); 446eddb85c6SJohn Baldwin close(dpipe[0]); 44757c74f5bSJohn Baldwin 44857c74f5bSJohn Baldwin /* The child process should now be ready. */ 44957c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 45057c74f5bSJohn Baldwin ATF_REQUIRE(wpid == child); 45157c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 45257c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 45357c74f5bSJohn Baldwin } 45457c74f5bSJohn Baldwin 45598685dc8SJohn Baldwin /* 45698685dc8SJohn Baldwin * The parent process should always act the same regardless of how the 45798685dc8SJohn Baldwin * debugger is attached to it. 45898685dc8SJohn Baldwin */ 45998685dc8SJohn Baldwin static __dead2 void 460189ac973SJohn Baldwin follow_fork_parent(bool use_vfork) 46198685dc8SJohn Baldwin { 46298685dc8SJohn Baldwin pid_t fpid, wpid; 46398685dc8SJohn Baldwin int status; 46498685dc8SJohn Baldwin 465189ac973SJohn Baldwin if (use_vfork) 466189ac973SJohn Baldwin CHILD_REQUIRE((fpid = vfork()) != -1); 467189ac973SJohn Baldwin else 46898685dc8SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 46998685dc8SJohn Baldwin 47098685dc8SJohn Baldwin if (fpid == 0) 47198685dc8SJohn Baldwin /* Child */ 472b98cb919SJohn Baldwin _exit(2); 47398685dc8SJohn Baldwin 47498685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 47598685dc8SJohn Baldwin CHILD_REQUIRE(wpid == fpid); 47698685dc8SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 47798685dc8SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 2); 47898685dc8SJohn Baldwin 479b98cb919SJohn Baldwin _exit(1); 48098685dc8SJohn Baldwin } 48198685dc8SJohn Baldwin 48298685dc8SJohn Baldwin /* 48398685dc8SJohn Baldwin * Helper routine for follow fork tests. This waits for two stops 48498685dc8SJohn Baldwin * that report both "sides" of a fork. It returns the pid of the new 48598685dc8SJohn Baldwin * child process. 48698685dc8SJohn Baldwin */ 48798685dc8SJohn Baldwin static pid_t 488189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl) 48998685dc8SJohn Baldwin { 49098685dc8SJohn Baldwin struct ptrace_lwpinfo pl; 49198685dc8SJohn Baldwin bool fork_reported[2]; 49298685dc8SJohn Baldwin pid_t child, wpid; 49398685dc8SJohn Baldwin int i, status; 49498685dc8SJohn Baldwin 49598685dc8SJohn Baldwin fork_reported[0] = false; 49698685dc8SJohn Baldwin fork_reported[1] = false; 49798685dc8SJohn Baldwin child = -1; 49898685dc8SJohn Baldwin 49998685dc8SJohn Baldwin /* 50098685dc8SJohn Baldwin * Each process should report a fork event. The parent should 50198685dc8SJohn Baldwin * report a PL_FLAG_FORKED event, and the child should report 50298685dc8SJohn Baldwin * a PL_FLAG_CHILD event. 50398685dc8SJohn Baldwin */ 50498685dc8SJohn Baldwin for (i = 0; i < 2; i++) { 50598685dc8SJohn Baldwin wpid = wait(&status); 50698685dc8SJohn Baldwin ATF_REQUIRE(wpid > 0); 50798685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 50898685dc8SJohn Baldwin 50998685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 51098685dc8SJohn Baldwin sizeof(pl)) != -1); 51198685dc8SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) != 51298685dc8SJohn Baldwin 0); 51398685dc8SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) != 51498685dc8SJohn Baldwin (PL_FLAG_FORKED | PL_FLAG_CHILD)); 51598685dc8SJohn Baldwin if (pl.pl_flags & PL_FLAG_CHILD) { 51698685dc8SJohn Baldwin ATF_REQUIRE(wpid != parent); 51798685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 51898685dc8SJohn Baldwin ATF_REQUIRE(!fork_reported[1]); 51998685dc8SJohn Baldwin if (child == -1) 52098685dc8SJohn Baldwin child = wpid; 52198685dc8SJohn Baldwin else 52298685dc8SJohn Baldwin ATF_REQUIRE(child == wpid); 523189ac973SJohn Baldwin if (ppl != NULL) 524189ac973SJohn Baldwin ppl[1] = pl; 52598685dc8SJohn Baldwin fork_reported[1] = true; 52698685dc8SJohn Baldwin } else { 52798685dc8SJohn Baldwin ATF_REQUIRE(wpid == parent); 52898685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 52998685dc8SJohn Baldwin ATF_REQUIRE(!fork_reported[0]); 53098685dc8SJohn Baldwin if (child == -1) 53198685dc8SJohn Baldwin child = pl.pl_child_pid; 53298685dc8SJohn Baldwin else 53398685dc8SJohn Baldwin ATF_REQUIRE(child == pl.pl_child_pid); 534189ac973SJohn Baldwin if (ppl != NULL) 535189ac973SJohn Baldwin ppl[0] = pl; 53698685dc8SJohn Baldwin fork_reported[0] = true; 53798685dc8SJohn Baldwin } 53898685dc8SJohn Baldwin } 53998685dc8SJohn Baldwin 54098685dc8SJohn Baldwin return (child); 54198685dc8SJohn Baldwin } 54298685dc8SJohn Baldwin 54398685dc8SJohn Baldwin /* 54498685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork and 54598685dc8SJohn Baldwin * that the traced parent sees the exit of the child after the debugger 54698685dc8SJohn Baldwin * when both processes remain attached to the debugger. 54798685dc8SJohn Baldwin */ 54898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached); 54998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc) 55098685dc8SJohn Baldwin { 551479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 55298685dc8SJohn Baldwin int status; 55398685dc8SJohn Baldwin 55498685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 55598685dc8SJohn Baldwin if (fpid == 0) { 55698685dc8SJohn Baldwin trace_me(); 557189ac973SJohn Baldwin follow_fork_parent(false); 55898685dc8SJohn Baldwin } 55998685dc8SJohn Baldwin 56098685dc8SJohn Baldwin /* Parent process. */ 56198685dc8SJohn Baldwin children[0] = fpid; 56298685dc8SJohn Baldwin 56398685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 56498685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 56598685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 56698685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 56798685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 56898685dc8SJohn Baldwin 56998685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 57098685dc8SJohn Baldwin 57198685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 57298685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 57398685dc8SJohn Baldwin 574189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 57598685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 57698685dc8SJohn Baldwin 57798685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 57898685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 57998685dc8SJohn Baldwin 58098685dc8SJohn Baldwin /* 58198685dc8SJohn Baldwin * The child can't exit until the grandchild reports status, so the 58298685dc8SJohn Baldwin * grandchild should report its exit first to the debugger. 58398685dc8SJohn Baldwin */ 58498685dc8SJohn Baldwin wpid = wait(&status); 58598685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 58698685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 58798685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 58898685dc8SJohn Baldwin 58998685dc8SJohn Baldwin wpid = wait(&status); 59098685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 59198685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 59298685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 59398685dc8SJohn Baldwin 59498685dc8SJohn Baldwin wpid = wait(&status); 59598685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 59698685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 59798685dc8SJohn Baldwin } 59898685dc8SJohn Baldwin 59998685dc8SJohn Baldwin /* 60098685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 60198685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the new 60298685dc8SJohn Baldwin * child process is detached after it reports its fork. 60398685dc8SJohn Baldwin */ 60498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached); 60598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc) 60698685dc8SJohn Baldwin { 607479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 60898685dc8SJohn Baldwin int status; 60998685dc8SJohn Baldwin 61098685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 61198685dc8SJohn Baldwin if (fpid == 0) { 61298685dc8SJohn Baldwin trace_me(); 613189ac973SJohn Baldwin follow_fork_parent(false); 61498685dc8SJohn Baldwin } 61598685dc8SJohn Baldwin 61698685dc8SJohn Baldwin /* Parent process. */ 61798685dc8SJohn Baldwin children[0] = fpid; 61898685dc8SJohn Baldwin 61998685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 62098685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 62198685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 62298685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 62398685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 62498685dc8SJohn Baldwin 62598685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 62698685dc8SJohn Baldwin 62798685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 62898685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 62998685dc8SJohn Baldwin 630189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 63198685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 63298685dc8SJohn Baldwin 63398685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 63498685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1); 63598685dc8SJohn Baldwin 63698685dc8SJohn Baldwin /* 63798685dc8SJohn Baldwin * Should not see any status from the grandchild now, only the 63898685dc8SJohn Baldwin * child. 63998685dc8SJohn Baldwin */ 64098685dc8SJohn Baldwin wpid = wait(&status); 64198685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 64298685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 64398685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 64498685dc8SJohn Baldwin 64598685dc8SJohn Baldwin wpid = wait(&status); 64698685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 64798685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 64898685dc8SJohn Baldwin } 64998685dc8SJohn Baldwin 65098685dc8SJohn Baldwin /* 65198685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 65298685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the 65398685dc8SJohn Baldwin * traced parent is detached after the fork. 65498685dc8SJohn Baldwin */ 65598685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached); 65698685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc) 65798685dc8SJohn Baldwin { 658479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 65998685dc8SJohn Baldwin int status; 66098685dc8SJohn Baldwin 66198685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 66298685dc8SJohn Baldwin if (fpid == 0) { 66398685dc8SJohn Baldwin trace_me(); 664189ac973SJohn Baldwin follow_fork_parent(false); 66598685dc8SJohn Baldwin } 66698685dc8SJohn Baldwin 66798685dc8SJohn Baldwin /* Parent process. */ 66898685dc8SJohn Baldwin children[0] = fpid; 66998685dc8SJohn Baldwin 67098685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 67198685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 67298685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 67398685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 67498685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 67598685dc8SJohn Baldwin 67698685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 67798685dc8SJohn Baldwin 67898685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 67998685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 68098685dc8SJohn Baldwin 681189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 68298685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 68398685dc8SJohn Baldwin 68498685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1); 68598685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 68698685dc8SJohn Baldwin 68798685dc8SJohn Baldwin /* 68898685dc8SJohn Baldwin * The child can't exit until the grandchild reports status, so the 68998685dc8SJohn Baldwin * grandchild should report its exit first to the debugger. 69098685dc8SJohn Baldwin * 69198685dc8SJohn Baldwin * Even though the child process is detached, it is still a 69298685dc8SJohn Baldwin * child of the debugger, so it will still report it's exit 69398685dc8SJohn Baldwin * after the grandchild. 69498685dc8SJohn Baldwin */ 69598685dc8SJohn Baldwin wpid = wait(&status); 69698685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 69798685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 69898685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 69998685dc8SJohn Baldwin 70098685dc8SJohn Baldwin wpid = wait(&status); 70198685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 70298685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 70398685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 70498685dc8SJohn Baldwin 70598685dc8SJohn Baldwin wpid = wait(&status); 70698685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 70798685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 70898685dc8SJohn Baldwin } 70998685dc8SJohn Baldwin 71098685dc8SJohn Baldwin static void 71198685dc8SJohn Baldwin attach_fork_parent(int cpipe[2]) 71298685dc8SJohn Baldwin { 71398685dc8SJohn Baldwin pid_t fpid; 71498685dc8SJohn Baldwin 71598685dc8SJohn Baldwin close(cpipe[0]); 71698685dc8SJohn Baldwin 71798685dc8SJohn Baldwin /* Double-fork to disassociate from the debugger. */ 71898685dc8SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 71998685dc8SJohn Baldwin if (fpid != 0) 720b98cb919SJohn Baldwin _exit(3); 72198685dc8SJohn Baldwin 72298685dc8SJohn Baldwin /* Send the pid of the disassociated child to the debugger. */ 72398685dc8SJohn Baldwin fpid = getpid(); 72498685dc8SJohn Baldwin CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid)); 72598685dc8SJohn Baldwin 72698685dc8SJohn Baldwin /* Wait for the debugger to attach. */ 72798685dc8SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0); 72898685dc8SJohn Baldwin } 72998685dc8SJohn Baldwin 73098685dc8SJohn Baldwin /* 73198685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork and 73298685dc8SJohn Baldwin * that the traced parent sees the exit of the child after the debugger 73398685dc8SJohn Baldwin * when both processes remain attached to the debugger. In this test 73498685dc8SJohn Baldwin * the parent that forks is not a direct child of the debugger. 73598685dc8SJohn Baldwin */ 73698685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger); 73798685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc) 73898685dc8SJohn Baldwin { 739479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 74098685dc8SJohn Baldwin int cpipe[2], status; 74198685dc8SJohn Baldwin 74298685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 74398685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 74498685dc8SJohn Baldwin if (fpid == 0) { 74598685dc8SJohn Baldwin attach_fork_parent(cpipe); 746189ac973SJohn Baldwin follow_fork_parent(false); 74798685dc8SJohn Baldwin } 74898685dc8SJohn Baldwin 74998685dc8SJohn Baldwin /* Parent process. */ 75098685dc8SJohn Baldwin close(cpipe[1]); 75198685dc8SJohn Baldwin 75298685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 75398685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 75498685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 75598685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 75698685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 75798685dc8SJohn Baldwin 75898685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 75998685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 76098685dc8SJohn Baldwin sizeof(children[0])); 76198685dc8SJohn Baldwin 76298685dc8SJohn Baldwin /* Attach to the fork parent. */ 76398685dc8SJohn Baldwin attach_child(children[0]); 76498685dc8SJohn Baldwin 76598685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 76698685dc8SJohn Baldwin 76798685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 76898685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 76998685dc8SJohn Baldwin 77098685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 77198685dc8SJohn Baldwin close(cpipe[0]); 77298685dc8SJohn Baldwin 773189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 77498685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 77598685dc8SJohn Baldwin 77698685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 77798685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 77898685dc8SJohn Baldwin 77998685dc8SJohn Baldwin /* 78098685dc8SJohn Baldwin * The fork parent can't exit until the child reports status, 78198685dc8SJohn Baldwin * so the child should report its exit first to the debugger. 78298685dc8SJohn Baldwin */ 78398685dc8SJohn Baldwin wpid = wait(&status); 78498685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 78598685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 78698685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 78798685dc8SJohn Baldwin 78898685dc8SJohn Baldwin wpid = wait(&status); 78998685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 79098685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 79198685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 79298685dc8SJohn Baldwin 79398685dc8SJohn Baldwin wpid = wait(&status); 79498685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 79598685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 79698685dc8SJohn Baldwin } 79798685dc8SJohn Baldwin 79898685dc8SJohn Baldwin /* 79998685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 80098685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the new 80198685dc8SJohn Baldwin * child process is detached after it reports its fork. In this test 80298685dc8SJohn Baldwin * the parent that forks is not a direct child of the debugger. 80398685dc8SJohn Baldwin */ 80498685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger); 80598685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc) 80698685dc8SJohn Baldwin { 807479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 80898685dc8SJohn Baldwin int cpipe[2], status; 80998685dc8SJohn Baldwin 81098685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 81198685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 81298685dc8SJohn Baldwin if (fpid == 0) { 81398685dc8SJohn Baldwin attach_fork_parent(cpipe); 814189ac973SJohn Baldwin follow_fork_parent(false); 81598685dc8SJohn Baldwin } 81698685dc8SJohn Baldwin 81798685dc8SJohn Baldwin /* Parent process. */ 81898685dc8SJohn Baldwin close(cpipe[1]); 81998685dc8SJohn Baldwin 82098685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 82198685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 82298685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 82398685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 82498685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 82598685dc8SJohn Baldwin 82698685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 82798685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 82898685dc8SJohn Baldwin sizeof(children[0])); 82998685dc8SJohn Baldwin 83098685dc8SJohn Baldwin /* Attach to the fork parent. */ 83198685dc8SJohn Baldwin attach_child(children[0]); 83298685dc8SJohn Baldwin 83398685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 83498685dc8SJohn Baldwin 83598685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 83698685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 83798685dc8SJohn Baldwin 83898685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 83998685dc8SJohn Baldwin close(cpipe[0]); 84098685dc8SJohn Baldwin 841189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 84298685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 84398685dc8SJohn Baldwin 84498685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 84598685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1); 84698685dc8SJohn Baldwin 84798685dc8SJohn Baldwin /* 84898685dc8SJohn Baldwin * Should not see any status from the child now, only the fork 84998685dc8SJohn Baldwin * parent. 85098685dc8SJohn Baldwin */ 85198685dc8SJohn Baldwin wpid = wait(&status); 85298685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 85398685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 85498685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 85598685dc8SJohn Baldwin 85698685dc8SJohn Baldwin wpid = wait(&status); 85798685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 85898685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 85998685dc8SJohn Baldwin } 86098685dc8SJohn Baldwin 86198685dc8SJohn Baldwin /* 86298685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 86398685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the 86498685dc8SJohn Baldwin * traced parent is detached after the fork. In this test the parent 86598685dc8SJohn Baldwin * that forks is not a direct child of the debugger. 86698685dc8SJohn Baldwin */ 86798685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger); 86898685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc) 86998685dc8SJohn Baldwin { 870479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 87198685dc8SJohn Baldwin int cpipe[2], status; 87298685dc8SJohn Baldwin 87398685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 87498685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 87598685dc8SJohn Baldwin if (fpid == 0) { 87698685dc8SJohn Baldwin attach_fork_parent(cpipe); 877189ac973SJohn Baldwin follow_fork_parent(false); 87898685dc8SJohn Baldwin } 87998685dc8SJohn Baldwin 88098685dc8SJohn Baldwin /* Parent process. */ 88198685dc8SJohn Baldwin close(cpipe[1]); 88298685dc8SJohn Baldwin 88398685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 88498685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 88598685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 88698685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 88798685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 88898685dc8SJohn Baldwin 88998685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 89098685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 89198685dc8SJohn Baldwin sizeof(children[0])); 89298685dc8SJohn Baldwin 89398685dc8SJohn Baldwin /* Attach to the fork parent. */ 89498685dc8SJohn Baldwin attach_child(children[0]); 89598685dc8SJohn Baldwin 89698685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 89798685dc8SJohn Baldwin 89898685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 89998685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 90098685dc8SJohn Baldwin 90198685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 90298685dc8SJohn Baldwin close(cpipe[0]); 90398685dc8SJohn Baldwin 904189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 90598685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 90698685dc8SJohn Baldwin 90798685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1); 90898685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 90998685dc8SJohn Baldwin 91098685dc8SJohn Baldwin /* 91198685dc8SJohn Baldwin * Should not see any status from the fork parent now, only 91298685dc8SJohn Baldwin * the child. 91398685dc8SJohn Baldwin */ 91498685dc8SJohn Baldwin wpid = wait(&status); 91598685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 91698685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 91798685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 91898685dc8SJohn Baldwin 91998685dc8SJohn Baldwin wpid = wait(&status); 92098685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 92198685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 92298685dc8SJohn Baldwin } 92398685dc8SJohn Baldwin 924368b2b1cSJohn Baldwin /* 925368b2b1cSJohn Baldwin * Verify that a child process does not see an unrelated debugger as its 926368b2b1cSJohn Baldwin * parent but sees its original parent process. 927368b2b1cSJohn Baldwin */ 928368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid); 929368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc) 930368b2b1cSJohn Baldwin { 931368b2b1cSJohn Baldwin pid_t child, debugger, ppid, wpid; 932368b2b1cSJohn Baldwin int cpipe[2], dpipe[2], status; 933368b2b1cSJohn Baldwin char c; 934368b2b1cSJohn Baldwin 935368b2b1cSJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 936368b2b1cSJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 937368b2b1cSJohn Baldwin 938368b2b1cSJohn Baldwin if (child == 0) { 939368b2b1cSJohn Baldwin /* Child process. */ 940368b2b1cSJohn Baldwin close(cpipe[0]); 941368b2b1cSJohn Baldwin 942368b2b1cSJohn Baldwin /* Wait for parent to be ready. */ 943368b2b1cSJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 944368b2b1cSJohn Baldwin 945368b2b1cSJohn Baldwin /* Report the parent PID to the parent. */ 946368b2b1cSJohn Baldwin ppid = getppid(); 947368b2b1cSJohn Baldwin CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) == 948368b2b1cSJohn Baldwin sizeof(ppid)); 949368b2b1cSJohn Baldwin 950368b2b1cSJohn Baldwin _exit(1); 951368b2b1cSJohn Baldwin } 952368b2b1cSJohn Baldwin close(cpipe[1]); 953368b2b1cSJohn Baldwin 954368b2b1cSJohn Baldwin ATF_REQUIRE(pipe(dpipe) == 0); 955368b2b1cSJohn Baldwin ATF_REQUIRE((debugger = fork()) != -1); 956368b2b1cSJohn Baldwin 957368b2b1cSJohn Baldwin if (debugger == 0) { 958368b2b1cSJohn Baldwin /* Debugger process. */ 959368b2b1cSJohn Baldwin close(dpipe[0]); 960368b2b1cSJohn Baldwin 961368b2b1cSJohn Baldwin CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 962368b2b1cSJohn Baldwin 963368b2b1cSJohn Baldwin wpid = waitpid(child, &status, 0); 964368b2b1cSJohn Baldwin CHILD_REQUIRE(wpid == child); 965368b2b1cSJohn Baldwin CHILD_REQUIRE(WIFSTOPPED(status)); 966368b2b1cSJohn Baldwin CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 967368b2b1cSJohn Baldwin 968368b2b1cSJohn Baldwin CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 969368b2b1cSJohn Baldwin 970368b2b1cSJohn Baldwin /* Signal parent that debugger is attached. */ 971368b2b1cSJohn Baldwin CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 972368b2b1cSJohn Baldwin 973368b2b1cSJohn Baldwin /* Wait for traced child to exit. */ 974368b2b1cSJohn Baldwin wpid = waitpid(child, &status, 0); 975368b2b1cSJohn Baldwin CHILD_REQUIRE(wpid == child); 976368b2b1cSJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 977368b2b1cSJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 1); 978368b2b1cSJohn Baldwin 979368b2b1cSJohn Baldwin _exit(0); 980368b2b1cSJohn Baldwin } 981368b2b1cSJohn Baldwin close(dpipe[1]); 982368b2b1cSJohn Baldwin 983368b2b1cSJohn Baldwin /* Parent process. */ 984368b2b1cSJohn Baldwin 985368b2b1cSJohn Baldwin /* Wait for the debugger to attach to the child. */ 986368b2b1cSJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 987368b2b1cSJohn Baldwin 988368b2b1cSJohn Baldwin /* Release the child. */ 989368b2b1cSJohn Baldwin ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 990368b2b1cSJohn Baldwin 991368b2b1cSJohn Baldwin /* Read the parent PID from the child. */ 992368b2b1cSJohn Baldwin ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid)); 993368b2b1cSJohn Baldwin close(cpipe[0]); 994368b2b1cSJohn Baldwin 995368b2b1cSJohn Baldwin ATF_REQUIRE(ppid == getpid()); 996368b2b1cSJohn Baldwin 997368b2b1cSJohn Baldwin /* Wait for the debugger. */ 998368b2b1cSJohn Baldwin wpid = waitpid(debugger, &status, 0); 999368b2b1cSJohn Baldwin ATF_REQUIRE(wpid == debugger); 1000368b2b1cSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1001368b2b1cSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 1002368b2b1cSJohn Baldwin 1003368b2b1cSJohn Baldwin /* The child process should now be ready. */ 1004368b2b1cSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 1005368b2b1cSJohn Baldwin ATF_REQUIRE(wpid == child); 1006368b2b1cSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1007368b2b1cSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1008368b2b1cSJohn Baldwin } 1009368b2b1cSJohn Baldwin 1010189ac973SJohn Baldwin /* 1011189ac973SJohn Baldwin * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new 1012189ac973SJohn Baldwin * child process created via fork() reports the correct value. 1013189ac973SJohn Baldwin */ 1014189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork); 1015189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc) 1016189ac973SJohn Baldwin { 1017189ac973SJohn Baldwin struct ptrace_lwpinfo pl[2]; 1018189ac973SJohn Baldwin pid_t children[2], fpid, wpid; 1019189ac973SJohn Baldwin int status; 1020189ac973SJohn Baldwin 1021189ac973SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 1022189ac973SJohn Baldwin if (fpid == 0) { 1023189ac973SJohn Baldwin trace_me(); 1024189ac973SJohn Baldwin follow_fork_parent(false); 1025189ac973SJohn Baldwin } 1026189ac973SJohn Baldwin 1027189ac973SJohn Baldwin /* Parent process. */ 1028189ac973SJohn Baldwin children[0] = fpid; 1029189ac973SJohn Baldwin 1030189ac973SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 1031189ac973SJohn Baldwin wpid = waitpid(children[0], &status, 0); 1032189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1033189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1034189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 1035189ac973SJohn Baldwin 1036189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 1037189ac973SJohn Baldwin 1038189ac973SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 1039189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1040189ac973SJohn Baldwin 1041189ac973SJohn Baldwin /* Wait for both halves of the fork event to get reported. */ 1042189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], pl); 1043189ac973SJohn Baldwin ATF_REQUIRE(children[1] > 0); 1044189ac973SJohn Baldwin 1045189ac973SJohn Baldwin ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0); 1046189ac973SJohn Baldwin ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0); 1047189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork); 1048189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code); 1049189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg); 1050189ac973SJohn Baldwin 1051189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1052189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 1053189ac973SJohn Baldwin 1054189ac973SJohn Baldwin /* 1055189ac973SJohn Baldwin * The child can't exit until the grandchild reports status, so the 1056189ac973SJohn Baldwin * grandchild should report its exit first to the debugger. 1057189ac973SJohn Baldwin */ 1058189ac973SJohn Baldwin wpid = wait(&status); 1059189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 1060189ac973SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1061189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 1062189ac973SJohn Baldwin 1063189ac973SJohn Baldwin wpid = wait(&status); 1064189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1065189ac973SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1066189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1067189ac973SJohn Baldwin 1068189ac973SJohn Baldwin wpid = wait(&status); 1069189ac973SJohn Baldwin ATF_REQUIRE(wpid == -1); 1070189ac973SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 1071189ac973SJohn Baldwin } 1072189ac973SJohn Baldwin 1073189ac973SJohn Baldwin /* 1074189ac973SJohn Baldwin * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new 1075189ac973SJohn Baldwin * child process created via vfork() reports the correct value. 1076189ac973SJohn Baldwin */ 1077189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork); 1078189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc) 1079189ac973SJohn Baldwin { 1080189ac973SJohn Baldwin struct ptrace_lwpinfo pl[2]; 1081189ac973SJohn Baldwin pid_t children[2], fpid, wpid; 1082189ac973SJohn Baldwin int status; 1083189ac973SJohn Baldwin 1084189ac973SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 1085189ac973SJohn Baldwin if (fpid == 0) { 1086189ac973SJohn Baldwin trace_me(); 1087189ac973SJohn Baldwin follow_fork_parent(true); 1088189ac973SJohn Baldwin } 1089189ac973SJohn Baldwin 1090189ac973SJohn Baldwin /* Parent process. */ 1091189ac973SJohn Baldwin children[0] = fpid; 1092189ac973SJohn Baldwin 1093189ac973SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 1094189ac973SJohn Baldwin wpid = waitpid(children[0], &status, 0); 1095189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1096189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1097189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 1098189ac973SJohn Baldwin 1099189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 1100189ac973SJohn Baldwin 1101189ac973SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 1102189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1103189ac973SJohn Baldwin 1104189ac973SJohn Baldwin /* Wait for both halves of the fork event to get reported. */ 1105189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], pl); 1106189ac973SJohn Baldwin ATF_REQUIRE(children[1] > 0); 1107189ac973SJohn Baldwin 1108189ac973SJohn Baldwin ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0); 1109189ac973SJohn Baldwin ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0); 1110189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork); 1111189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code); 1112189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg); 1113189ac973SJohn Baldwin 1114189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1115189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 1116189ac973SJohn Baldwin 1117189ac973SJohn Baldwin /* 1118189ac973SJohn Baldwin * The child can't exit until the grandchild reports status, so the 1119189ac973SJohn Baldwin * grandchild should report its exit first to the debugger. 1120189ac973SJohn Baldwin */ 1121189ac973SJohn Baldwin wpid = wait(&status); 1122189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 1123189ac973SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1124189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 1125189ac973SJohn Baldwin 1126189ac973SJohn Baldwin wpid = wait(&status); 1127189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1128189ac973SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1129189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1130189ac973SJohn Baldwin 1131189ac973SJohn Baldwin wpid = wait(&status); 1132189ac973SJohn Baldwin ATF_REQUIRE(wpid == -1); 1133189ac973SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 1134189ac973SJohn Baldwin } 1135189ac973SJohn Baldwin 1136189ac973SJohn Baldwin static void * 1137189ac973SJohn Baldwin simple_thread(void *arg __unused) 1138189ac973SJohn Baldwin { 1139189ac973SJohn Baldwin 1140189ac973SJohn Baldwin pthread_exit(NULL); 1141189ac973SJohn Baldwin } 1142189ac973SJohn Baldwin 11435fcfab6eSJohn Baldwin static __dead2 void 11445fcfab6eSJohn Baldwin simple_thread_main(void) 11455fcfab6eSJohn Baldwin { 11465fcfab6eSJohn Baldwin pthread_t thread; 11475fcfab6eSJohn Baldwin 11485fcfab6eSJohn Baldwin CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, NULL) == 0); 11495fcfab6eSJohn Baldwin CHILD_REQUIRE(pthread_join(thread, NULL) == 0); 11505fcfab6eSJohn Baldwin exit(1); 11515fcfab6eSJohn Baldwin } 11525fcfab6eSJohn Baldwin 1153189ac973SJohn Baldwin /* 1154189ac973SJohn Baldwin * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new 1155189ac973SJohn Baldwin * thread reports the correct value. 1156189ac973SJohn Baldwin */ 1157189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread); 1158189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc) 1159189ac973SJohn Baldwin { 1160189ac973SJohn Baldwin struct ptrace_lwpinfo pl; 1161189ac973SJohn Baldwin pid_t fpid, wpid; 1162e72879e5SJohn Baldwin lwpid_t mainlwp; 1163189ac973SJohn Baldwin int status; 1164189ac973SJohn Baldwin 1165189ac973SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 1166189ac973SJohn Baldwin if (fpid == 0) { 1167189ac973SJohn Baldwin trace_me(); 11685fcfab6eSJohn Baldwin simple_thread_main(); 1169189ac973SJohn Baldwin } 1170189ac973SJohn Baldwin 1171189ac973SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 1172189ac973SJohn Baldwin wpid = waitpid(fpid, &status, 0); 1173189ac973SJohn Baldwin ATF_REQUIRE(wpid == fpid); 1174189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1175189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 1176189ac973SJohn Baldwin 1177189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 1178189ac973SJohn Baldwin sizeof(pl)) != -1); 1179e72879e5SJohn Baldwin mainlwp = pl.pl_lwpid; 1180189ac973SJohn Baldwin 1181189ac973SJohn Baldwin /* 1182189ac973SJohn Baldwin * Continue the child ignoring the SIGSTOP and tracing all 1183189ac973SJohn Baldwin * system call exits. 1184189ac973SJohn Baldwin */ 1185189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1); 1186189ac973SJohn Baldwin 1187189ac973SJohn Baldwin /* 1188189ac973SJohn Baldwin * Wait for the new thread to arrive. pthread_create() might 1189189ac973SJohn Baldwin * invoke any number of system calls. For now we just wait 1190189ac973SJohn Baldwin * for the new thread to arrive and make sure it reports a 1191189ac973SJohn Baldwin * valid system call code. If ptrace grows thread event 1192189ac973SJohn Baldwin * reporting then this test can be made more precise. 1193189ac973SJohn Baldwin */ 1194189ac973SJohn Baldwin for (;;) { 1195189ac973SJohn Baldwin wpid = waitpid(fpid, &status, 0); 1196189ac973SJohn Baldwin ATF_REQUIRE(wpid == fpid); 1197189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1198189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 1199189ac973SJohn Baldwin 1200189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 1201189ac973SJohn Baldwin sizeof(pl)) != -1); 1202189ac973SJohn Baldwin ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0); 1203189ac973SJohn Baldwin ATF_REQUIRE(pl.pl_syscall_code != 0); 1204e72879e5SJohn Baldwin if (pl.pl_lwpid != mainlwp) 1205189ac973SJohn Baldwin /* New thread seen. */ 1206189ac973SJohn Baldwin break; 1207189ac973SJohn Baldwin 1208189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 1209189ac973SJohn Baldwin } 1210189ac973SJohn Baldwin 1211189ac973SJohn Baldwin /* Wait for the child to exit. */ 1212189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 1213189ac973SJohn Baldwin for (;;) { 1214189ac973SJohn Baldwin wpid = waitpid(fpid, &status, 0); 1215189ac973SJohn Baldwin ATF_REQUIRE(wpid == fpid); 1216189ac973SJohn Baldwin if (WIFEXITED(status)) 1217189ac973SJohn Baldwin break; 1218189ac973SJohn Baldwin 1219189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1220189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 1221189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 1222189ac973SJohn Baldwin } 1223189ac973SJohn Baldwin 1224189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1225189ac973SJohn Baldwin 1226189ac973SJohn Baldwin wpid = wait(&status); 1227189ac973SJohn Baldwin ATF_REQUIRE(wpid == -1); 1228189ac973SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 1229189ac973SJohn Baldwin } 1230189ac973SJohn Baldwin 12315fcfab6eSJohn Baldwin /* 12325fcfab6eSJohn Baldwin * Verify that the expected LWP events are reported for a child thread. 12335fcfab6eSJohn Baldwin */ 12345fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events); 12355fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events, tc) 12365fcfab6eSJohn Baldwin { 12375fcfab6eSJohn Baldwin struct ptrace_lwpinfo pl; 12385fcfab6eSJohn Baldwin pid_t fpid, wpid; 12395fcfab6eSJohn Baldwin lwpid_t lwps[2]; 12405fcfab6eSJohn Baldwin int status; 12415fcfab6eSJohn Baldwin 12425fcfab6eSJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 12435fcfab6eSJohn Baldwin if (fpid == 0) { 12445fcfab6eSJohn Baldwin trace_me(); 12455fcfab6eSJohn Baldwin simple_thread_main(); 12465fcfab6eSJohn Baldwin } 12475fcfab6eSJohn Baldwin 12485fcfab6eSJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 12495fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 12505fcfab6eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 12515fcfab6eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 12525fcfab6eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 12535fcfab6eSJohn Baldwin 12545fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 12555fcfab6eSJohn Baldwin sizeof(pl)) != -1); 12565fcfab6eSJohn Baldwin lwps[0] = pl.pl_lwpid; 12575fcfab6eSJohn Baldwin 12585fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0); 12595fcfab6eSJohn Baldwin 12605fcfab6eSJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 12615fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 12625fcfab6eSJohn Baldwin 12635fcfab6eSJohn Baldwin /* The first event should be for the child thread's birth. */ 12645fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 12655fcfab6eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 12665fcfab6eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 12675fcfab6eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 12685fcfab6eSJohn Baldwin 12695fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 12705fcfab6eSJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) == 12715fcfab6eSJohn Baldwin (PL_FLAG_BORN | PL_FLAG_SCX)); 12725fcfab6eSJohn Baldwin ATF_REQUIRE(pl.pl_lwpid != lwps[0]); 12735fcfab6eSJohn Baldwin lwps[1] = pl.pl_lwpid; 12745fcfab6eSJohn Baldwin 12755fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 12765fcfab6eSJohn Baldwin 12775fcfab6eSJohn Baldwin /* The next event should be for the child thread's death. */ 12785fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 12795fcfab6eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 12805fcfab6eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 12815fcfab6eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 12825fcfab6eSJohn Baldwin 12835fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 12845fcfab6eSJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) == 12855fcfab6eSJohn Baldwin (PL_FLAG_EXITED | PL_FLAG_SCE)); 12865fcfab6eSJohn Baldwin ATF_REQUIRE(pl.pl_lwpid == lwps[1]); 12875fcfab6eSJohn Baldwin 12885fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 12895fcfab6eSJohn Baldwin 12905fcfab6eSJohn Baldwin /* The last event should be for the child process's exit. */ 12915fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 12925fcfab6eSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 12935fcfab6eSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 12945fcfab6eSJohn Baldwin 12955fcfab6eSJohn Baldwin wpid = wait(&status); 12965fcfab6eSJohn Baldwin ATF_REQUIRE(wpid == -1); 12975fcfab6eSJohn Baldwin ATF_REQUIRE(errno == ECHILD); 12985fcfab6eSJohn Baldwin } 12995fcfab6eSJohn Baldwin 13005fcfab6eSJohn Baldwin static void * 13015fcfab6eSJohn Baldwin exec_thread(void *arg __unused) 13025fcfab6eSJohn Baldwin { 13035fcfab6eSJohn Baldwin 13045fcfab6eSJohn Baldwin execl("/usr/bin/true", "true", NULL); 13055fcfab6eSJohn Baldwin exit(127); 13065fcfab6eSJohn Baldwin } 13075fcfab6eSJohn Baldwin 13085fcfab6eSJohn Baldwin static __dead2 void 13095fcfab6eSJohn Baldwin exec_thread_main(void) 13105fcfab6eSJohn Baldwin { 13115fcfab6eSJohn Baldwin pthread_t thread; 13125fcfab6eSJohn Baldwin 13135fcfab6eSJohn Baldwin CHILD_REQUIRE(pthread_create(&thread, NULL, exec_thread, NULL) == 0); 13145fcfab6eSJohn Baldwin for (;;) 13155fcfab6eSJohn Baldwin sleep(60); 13165fcfab6eSJohn Baldwin exit(1); 13175fcfab6eSJohn Baldwin } 13185fcfab6eSJohn Baldwin 13195fcfab6eSJohn Baldwin /* 13205fcfab6eSJohn Baldwin * Verify that the expected LWP events are reported for a multithreaded 13215fcfab6eSJohn Baldwin * process that calls execve(2). 13225fcfab6eSJohn Baldwin */ 13235fcfab6eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec); 13245fcfab6eSJohn Baldwin ATF_TC_BODY(ptrace__lwp_events_exec, tc) 13255fcfab6eSJohn Baldwin { 13265fcfab6eSJohn Baldwin struct ptrace_lwpinfo pl; 13275fcfab6eSJohn Baldwin pid_t fpid, wpid; 13285fcfab6eSJohn Baldwin lwpid_t lwps[2]; 13295fcfab6eSJohn Baldwin int status; 13305fcfab6eSJohn Baldwin 13315fcfab6eSJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 13325fcfab6eSJohn Baldwin if (fpid == 0) { 13335fcfab6eSJohn Baldwin trace_me(); 13345fcfab6eSJohn Baldwin exec_thread_main(); 13355fcfab6eSJohn Baldwin } 13365fcfab6eSJohn Baldwin 13375fcfab6eSJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 13385fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 13395fcfab6eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 13405fcfab6eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 13415fcfab6eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 13425fcfab6eSJohn Baldwin 13435fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 13445fcfab6eSJohn Baldwin sizeof(pl)) != -1); 13455fcfab6eSJohn Baldwin lwps[0] = pl.pl_lwpid; 13465fcfab6eSJohn Baldwin 13475fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0); 13485fcfab6eSJohn Baldwin 13495fcfab6eSJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 13505fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 13515fcfab6eSJohn Baldwin 13525fcfab6eSJohn Baldwin /* The first event should be for the child thread's birth. */ 13535fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 13545fcfab6eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 13555fcfab6eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 13565fcfab6eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 13575fcfab6eSJohn Baldwin 13585fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 13595fcfab6eSJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) == 13605fcfab6eSJohn Baldwin (PL_FLAG_BORN | PL_FLAG_SCX)); 13615fcfab6eSJohn Baldwin ATF_REQUIRE(pl.pl_lwpid != lwps[0]); 13625fcfab6eSJohn Baldwin lwps[1] = pl.pl_lwpid; 13635fcfab6eSJohn Baldwin 13645fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 13655fcfab6eSJohn Baldwin 13665fcfab6eSJohn Baldwin /* 13675fcfab6eSJohn Baldwin * The next event should be for the main thread's death due to 13685fcfab6eSJohn Baldwin * single threading from execve(). 13695fcfab6eSJohn Baldwin */ 13705fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 13715fcfab6eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 13725fcfab6eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 13735fcfab6eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 13745fcfab6eSJohn Baldwin 13755fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 13765fcfab6eSJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) == 13775fcfab6eSJohn Baldwin (PL_FLAG_EXITED)); 13785fcfab6eSJohn Baldwin ATF_REQUIRE(pl.pl_lwpid == lwps[0]); 13795fcfab6eSJohn Baldwin 13805fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 13815fcfab6eSJohn Baldwin 13825fcfab6eSJohn Baldwin /* The next event should be for the child process's exec. */ 13835fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 13845fcfab6eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 13855fcfab6eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 13865fcfab6eSJohn Baldwin 13875fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 13885fcfab6eSJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) == 13895fcfab6eSJohn Baldwin (PL_FLAG_EXEC | PL_FLAG_SCX)); 13905fcfab6eSJohn Baldwin ATF_REQUIRE(pl.pl_lwpid == lwps[1]); 13915fcfab6eSJohn Baldwin 13925fcfab6eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 13935fcfab6eSJohn Baldwin 13945fcfab6eSJohn Baldwin /* The last event should be for the child process's exit. */ 13955fcfab6eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 13965fcfab6eSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 13975fcfab6eSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 13985fcfab6eSJohn Baldwin 13995fcfab6eSJohn Baldwin wpid = wait(&status); 14005fcfab6eSJohn Baldwin ATF_REQUIRE(wpid == -1); 14015fcfab6eSJohn Baldwin ATF_REQUIRE(errno == ECHILD); 14025fcfab6eSJohn Baldwin } 14035fcfab6eSJohn Baldwin 14043340c45bSJohn Baldwin static void 14053340c45bSJohn Baldwin handler(int sig __unused) 14063340c45bSJohn Baldwin { 14073340c45bSJohn Baldwin } 14083340c45bSJohn Baldwin 14093340c45bSJohn Baldwin static void 14103340c45bSJohn Baldwin signal_main(void) 14113340c45bSJohn Baldwin { 14123340c45bSJohn Baldwin 14133340c45bSJohn Baldwin signal(SIGINFO, handler); 14143340c45bSJohn Baldwin raise(SIGINFO); 14153340c45bSJohn Baldwin exit(0); 14163340c45bSJohn Baldwin } 14173340c45bSJohn Baldwin 14183340c45bSJohn Baldwin /* 14193340c45bSJohn Baldwin * Verify that the expected ptrace event is reported for a signal. 14203340c45bSJohn Baldwin */ 14213340c45bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__siginfo); 14223340c45bSJohn Baldwin ATF_TC_BODY(ptrace__siginfo, tc) 14233340c45bSJohn Baldwin { 14243340c45bSJohn Baldwin struct ptrace_lwpinfo pl; 14253340c45bSJohn Baldwin pid_t fpid, wpid; 14263340c45bSJohn Baldwin int status; 14273340c45bSJohn Baldwin 14283340c45bSJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 14293340c45bSJohn Baldwin if (fpid == 0) { 14303340c45bSJohn Baldwin trace_me(); 14313340c45bSJohn Baldwin signal_main(); 14323340c45bSJohn Baldwin } 14333340c45bSJohn Baldwin 14343340c45bSJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 14353340c45bSJohn Baldwin wpid = waitpid(fpid, &status, 0); 14363340c45bSJohn Baldwin ATF_REQUIRE(wpid == fpid); 14373340c45bSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 14383340c45bSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 14393340c45bSJohn Baldwin 14403340c45bSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 14413340c45bSJohn Baldwin 14423340c45bSJohn Baldwin /* The next event should be for the SIGINFO. */ 14433340c45bSJohn Baldwin wpid = waitpid(fpid, &status, 0); 14443340c45bSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 14453340c45bSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGINFO); 14463340c45bSJohn Baldwin 14473340c45bSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 14483340c45bSJohn Baldwin ATF_REQUIRE(pl.pl_event == PL_EVENT_SIGNAL); 14493340c45bSJohn Baldwin ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); 14503340c45bSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_code == SI_LWP); 14513340c45bSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_pid == wpid); 14523340c45bSJohn Baldwin 14533340c45bSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 14543340c45bSJohn Baldwin 14553340c45bSJohn Baldwin /* The last event should be for the child process's exit. */ 14563340c45bSJohn Baldwin wpid = waitpid(fpid, &status, 0); 14573340c45bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 14583340c45bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 14593340c45bSJohn Baldwin 14603340c45bSJohn Baldwin wpid = wait(&status); 14613340c45bSJohn Baldwin ATF_REQUIRE(wpid == -1); 14623340c45bSJohn Baldwin ATF_REQUIRE(errno == ECHILD); 14633340c45bSJohn Baldwin } 14643340c45bSJohn Baldwin 14658d570f64SJohn Baldwin /* 14668d570f64SJohn Baldwin * Verify that the expected ptrace events are reported for PTRACE_EXEC. 14678d570f64SJohn Baldwin */ 14688d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable); 14698d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_disable, tc) 14708d570f64SJohn Baldwin { 14718d570f64SJohn Baldwin pid_t fpid, wpid; 14728d570f64SJohn Baldwin int events, status; 14738d570f64SJohn Baldwin 14748d570f64SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 14758d570f64SJohn Baldwin if (fpid == 0) { 14768d570f64SJohn Baldwin trace_me(); 14778d570f64SJohn Baldwin exec_thread(NULL); 14788d570f64SJohn Baldwin } 14798d570f64SJohn Baldwin 14808d570f64SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 14818d570f64SJohn Baldwin wpid = waitpid(fpid, &status, 0); 14828d570f64SJohn Baldwin ATF_REQUIRE(wpid == fpid); 14838d570f64SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 14848d570f64SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 14858d570f64SJohn Baldwin 14868d570f64SJohn Baldwin events = 0; 14878d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events, 14888d570f64SJohn Baldwin sizeof(events)) == 0); 14898d570f64SJohn Baldwin 14908d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 14918d570f64SJohn Baldwin 14928d570f64SJohn Baldwin /* Should get one event at exit. */ 14938d570f64SJohn Baldwin wpid = waitpid(fpid, &status, 0); 14948d570f64SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 14958d570f64SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 14968d570f64SJohn Baldwin 14978d570f64SJohn Baldwin wpid = wait(&status); 14988d570f64SJohn Baldwin ATF_REQUIRE(wpid == -1); 14998d570f64SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 15008d570f64SJohn Baldwin } 15018d570f64SJohn Baldwin 15028d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable); 15038d570f64SJohn Baldwin ATF_TC_BODY(ptrace__ptrace_exec_enable, tc) 15048d570f64SJohn Baldwin { 15058d570f64SJohn Baldwin struct ptrace_lwpinfo pl; 15068d570f64SJohn Baldwin pid_t fpid, wpid; 15078d570f64SJohn Baldwin int events, status; 15088d570f64SJohn Baldwin 15098d570f64SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 15108d570f64SJohn Baldwin if (fpid == 0) { 15118d570f64SJohn Baldwin trace_me(); 15128d570f64SJohn Baldwin exec_thread(NULL); 15138d570f64SJohn Baldwin } 15148d570f64SJohn Baldwin 15158d570f64SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 15168d570f64SJohn Baldwin wpid = waitpid(fpid, &status, 0); 15178d570f64SJohn Baldwin ATF_REQUIRE(wpid == fpid); 15188d570f64SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 15198d570f64SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 15208d570f64SJohn Baldwin 15218d570f64SJohn Baldwin events = PTRACE_EXEC; 15228d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events, 15238d570f64SJohn Baldwin sizeof(events)) == 0); 15248d570f64SJohn Baldwin 15258d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 15268d570f64SJohn Baldwin 15278d570f64SJohn Baldwin /* The next event should be for the child process's exec. */ 15288d570f64SJohn Baldwin wpid = waitpid(fpid, &status, 0); 15298d570f64SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 15308d570f64SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 15318d570f64SJohn Baldwin 15328d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 15338d570f64SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) == 15348d570f64SJohn Baldwin (PL_FLAG_EXEC | PL_FLAG_SCX)); 15358d570f64SJohn Baldwin 15368d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 15378d570f64SJohn Baldwin 15388d570f64SJohn Baldwin /* The last event should be for the child process's exit. */ 15398d570f64SJohn Baldwin wpid = waitpid(fpid, &status, 0); 15408d570f64SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 15418d570f64SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 15428d570f64SJohn Baldwin 15438d570f64SJohn Baldwin wpid = wait(&status); 15448d570f64SJohn Baldwin ATF_REQUIRE(wpid == -1); 15458d570f64SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 15468d570f64SJohn Baldwin } 15478d570f64SJohn Baldwin 15488d570f64SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__event_mask); 15498d570f64SJohn Baldwin ATF_TC_BODY(ptrace__event_mask, tc) 15508d570f64SJohn Baldwin { 15518d570f64SJohn Baldwin pid_t fpid, wpid; 15528d570f64SJohn Baldwin int events, status; 15538d570f64SJohn Baldwin 15548d570f64SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 15558d570f64SJohn Baldwin if (fpid == 0) { 15568d570f64SJohn Baldwin trace_me(); 15578d570f64SJohn Baldwin exit(0); 15588d570f64SJohn Baldwin } 15598d570f64SJohn Baldwin 15608d570f64SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 15618d570f64SJohn Baldwin wpid = waitpid(fpid, &status, 0); 15628d570f64SJohn Baldwin ATF_REQUIRE(wpid == fpid); 15638d570f64SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 15648d570f64SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 15658d570f64SJohn Baldwin 15668d570f64SJohn Baldwin /* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */ 15678d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1); 15688d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events, 15698d570f64SJohn Baldwin sizeof(events)) == 0); 15708d570f64SJohn Baldwin ATF_REQUIRE(events & PTRACE_FORK); 15718d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1); 15728d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events, 15738d570f64SJohn Baldwin sizeof(events)) == 0); 15748d570f64SJohn Baldwin ATF_REQUIRE(!(events & PTRACE_FORK)); 15758d570f64SJohn Baldwin 15768d570f64SJohn Baldwin /* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */ 15778d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1); 15788d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events, 15798d570f64SJohn Baldwin sizeof(events)) == 0); 15808d570f64SJohn Baldwin ATF_REQUIRE(events & PTRACE_LWP); 15818d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1); 15828d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events, 15838d570f64SJohn Baldwin sizeof(events)) == 0); 15848d570f64SJohn Baldwin ATF_REQUIRE(!(events & PTRACE_LWP)); 15858d570f64SJohn Baldwin 15868d570f64SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 15878d570f64SJohn Baldwin 15888d570f64SJohn Baldwin /* Should get one event at exit. */ 15898d570f64SJohn Baldwin wpid = waitpid(fpid, &status, 0); 15908d570f64SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 15918d570f64SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 15928d570f64SJohn Baldwin 15938d570f64SJohn Baldwin wpid = wait(&status); 15948d570f64SJohn Baldwin ATF_REQUIRE(wpid == -1); 15958d570f64SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 15968d570f64SJohn Baldwin } 15978d570f64SJohn Baldwin 1598fc4f075aSJohn Baldwin /* 1599fc4f075aSJohn Baldwin * Verify that the expected ptrace events are reported for PTRACE_VFORK. 1600fc4f075aSJohn Baldwin */ 1601fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork); 1602fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork, tc) 1603fc4f075aSJohn Baldwin { 1604fc4f075aSJohn Baldwin struct ptrace_lwpinfo pl; 1605fc4f075aSJohn Baldwin pid_t fpid, wpid; 1606fc4f075aSJohn Baldwin int events, status; 1607fc4f075aSJohn Baldwin 1608fc4f075aSJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 1609fc4f075aSJohn Baldwin if (fpid == 0) { 1610fc4f075aSJohn Baldwin trace_me(); 1611fc4f075aSJohn Baldwin follow_fork_parent(true); 1612fc4f075aSJohn Baldwin } 1613fc4f075aSJohn Baldwin 1614fc4f075aSJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 1615fc4f075aSJohn Baldwin wpid = waitpid(fpid, &status, 0); 1616fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == fpid); 1617fc4f075aSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1618fc4f075aSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 1619fc4f075aSJohn Baldwin 1620fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events, 1621fc4f075aSJohn Baldwin sizeof(events)) == 0); 1622fc4f075aSJohn Baldwin events |= PTRACE_VFORK; 1623fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events, 1624fc4f075aSJohn Baldwin sizeof(events)) == 0); 1625fc4f075aSJohn Baldwin 1626fc4f075aSJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 1627fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1); 1628fc4f075aSJohn Baldwin 1629fc4f075aSJohn Baldwin /* The next event should report the end of the vfork. */ 1630fc4f075aSJohn Baldwin wpid = wait(&status); 1631fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == fpid); 1632fc4f075aSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1633fc4f075aSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 1634fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 1635fc4f075aSJohn Baldwin ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0); 1636fc4f075aSJohn Baldwin 1637fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1); 1638fc4f075aSJohn Baldwin 1639fc4f075aSJohn Baldwin wpid = wait(&status); 1640fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == fpid); 1641fc4f075aSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1642fc4f075aSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1643fc4f075aSJohn Baldwin 1644fc4f075aSJohn Baldwin wpid = wait(&status); 1645fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == -1); 1646fc4f075aSJohn Baldwin ATF_REQUIRE(errno == ECHILD); 1647fc4f075aSJohn Baldwin } 1648fc4f075aSJohn Baldwin 1649fc4f075aSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow); 1650fc4f075aSJohn Baldwin ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc) 1651fc4f075aSJohn Baldwin { 1652fc4f075aSJohn Baldwin struct ptrace_lwpinfo pl[2]; 1653fc4f075aSJohn Baldwin pid_t children[2], fpid, wpid; 1654fc4f075aSJohn Baldwin int events, status; 1655fc4f075aSJohn Baldwin 1656fc4f075aSJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 1657fc4f075aSJohn Baldwin if (fpid == 0) { 1658fc4f075aSJohn Baldwin trace_me(); 1659fc4f075aSJohn Baldwin follow_fork_parent(true); 1660fc4f075aSJohn Baldwin } 1661fc4f075aSJohn Baldwin 1662fc4f075aSJohn Baldwin /* Parent process. */ 1663fc4f075aSJohn Baldwin children[0] = fpid; 1664fc4f075aSJohn Baldwin 1665fc4f075aSJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 1666fc4f075aSJohn Baldwin wpid = waitpid(children[0], &status, 0); 1667fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1668fc4f075aSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1669fc4f075aSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 1670fc4f075aSJohn Baldwin 1671fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events, 1672fc4f075aSJohn Baldwin sizeof(events)) == 0); 1673fc4f075aSJohn Baldwin events |= PTRACE_FORK | PTRACE_VFORK; 1674fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events, 1675fc4f075aSJohn Baldwin sizeof(events)) == 0); 1676fc4f075aSJohn Baldwin 1677fc4f075aSJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 1678fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1679fc4f075aSJohn Baldwin 1680fc4f075aSJohn Baldwin /* Wait for both halves of the fork event to get reported. */ 1681fc4f075aSJohn Baldwin children[1] = handle_fork_events(children[0], pl); 1682fc4f075aSJohn Baldwin ATF_REQUIRE(children[1] > 0); 1683fc4f075aSJohn Baldwin 1684fc4f075aSJohn Baldwin ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0); 1685fc4f075aSJohn Baldwin 1686fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1687fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 1688fc4f075aSJohn Baldwin 1689fc4f075aSJohn Baldwin /* 1690fc4f075aSJohn Baldwin * The child can't exit until the grandchild reports status, so the 1691fc4f075aSJohn Baldwin * grandchild should report its exit first to the debugger. 1692fc4f075aSJohn Baldwin */ 1693fc4f075aSJohn Baldwin wpid = waitpid(children[1], &status, 0); 1694fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == children[1]); 1695fc4f075aSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1696fc4f075aSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 1697fc4f075aSJohn Baldwin 1698fc4f075aSJohn Baldwin /* 1699fc4f075aSJohn Baldwin * The child should report it's vfork() completion before it 1700fc4f075aSJohn Baldwin * exits. 1701fc4f075aSJohn Baldwin */ 1702fc4f075aSJohn Baldwin wpid = wait(&status); 1703fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1704fc4f075aSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1705fc4f075aSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 1706fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) != 1707fc4f075aSJohn Baldwin -1); 1708fc4f075aSJohn Baldwin ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0); 1709fc4f075aSJohn Baldwin 1710fc4f075aSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1711fc4f075aSJohn Baldwin 1712fc4f075aSJohn Baldwin wpid = wait(&status); 1713fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1714fc4f075aSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1715fc4f075aSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1716fc4f075aSJohn Baldwin 1717fc4f075aSJohn Baldwin wpid = wait(&status); 1718fc4f075aSJohn Baldwin ATF_REQUIRE(wpid == -1); 1719fc4f075aSJohn Baldwin ATF_REQUIRE(errno == ECHILD); 1720fc4f075aSJohn Baldwin } 1721fc4f075aSJohn Baldwin 1722403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT 1723e2ebfbbfSEric Badger /* 172482a4538fSEric Badger * Verify that no more events are reported after PT_KILL except for the 172582a4538fSEric Badger * process exit when stopped due to a breakpoint trap. 172682a4538fSEric Badger */ 172782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint); 172882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc) 172982a4538fSEric Badger { 173082a4538fSEric Badger pid_t fpid, wpid; 173182a4538fSEric Badger int status; 173282a4538fSEric Badger 173382a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 173482a4538fSEric Badger if (fpid == 0) { 173582a4538fSEric Badger trace_me(); 17369e0d1159SEric Badger breakpoint(); 173782a4538fSEric Badger exit(1); 173882a4538fSEric Badger } 173982a4538fSEric Badger 174082a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 174182a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 174282a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 174382a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 174482a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 174582a4538fSEric Badger 174682a4538fSEric Badger /* Continue the child ignoring the SIGSTOP. */ 174782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 174882a4538fSEric Badger 174982a4538fSEric Badger /* The second wait() should report hitting the breakpoint. */ 175082a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 175182a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 175282a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 175382a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 175482a4538fSEric Badger 175582a4538fSEric Badger /* Kill the child process. */ 175682a4538fSEric Badger ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0); 175782a4538fSEric Badger 175882a4538fSEric Badger /* The last wait() should report the SIGKILL. */ 175982a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 176082a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 176182a4538fSEric Badger ATF_REQUIRE(WIFSIGNALED(status)); 176282a4538fSEric Badger ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 176382a4538fSEric Badger 176482a4538fSEric Badger wpid = wait(&status); 176582a4538fSEric Badger ATF_REQUIRE(wpid == -1); 176682a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 176782a4538fSEric Badger } 1768403e331dSJohn Baldwin #endif /* HAVE_BREAKPOINT */ 176982a4538fSEric Badger 177082a4538fSEric Badger /* 177182a4538fSEric Badger * Verify that no more events are reported after PT_KILL except for the 177282a4538fSEric Badger * process exit when stopped inside of a system call. 177382a4538fSEric Badger */ 177482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call); 177582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_system_call, tc) 177682a4538fSEric Badger { 177782a4538fSEric Badger struct ptrace_lwpinfo pl; 177882a4538fSEric Badger pid_t fpid, wpid; 177982a4538fSEric Badger int status; 178082a4538fSEric Badger 178182a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 178282a4538fSEric Badger if (fpid == 0) { 178382a4538fSEric Badger trace_me(); 178482a4538fSEric Badger getpid(); 178582a4538fSEric Badger exit(1); 178682a4538fSEric Badger } 178782a4538fSEric Badger 178882a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 178982a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 179082a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 179182a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 179282a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 179382a4538fSEric Badger 179482a4538fSEric Badger /* Continue the child ignoring the SIGSTOP and tracing system calls. */ 179582a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 179682a4538fSEric Badger 179782a4538fSEric Badger /* The second wait() should report a system call entry for getpid(). */ 179882a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 179982a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 180082a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 180182a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 180282a4538fSEric Badger 180382a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 180482a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE); 180582a4538fSEric Badger 180682a4538fSEric Badger /* Kill the child process. */ 180782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0); 180882a4538fSEric Badger 180982a4538fSEric Badger /* The last wait() should report the SIGKILL. */ 181082a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 181182a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 181282a4538fSEric Badger ATF_REQUIRE(WIFSIGNALED(status)); 181382a4538fSEric Badger ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 181482a4538fSEric Badger 181582a4538fSEric Badger wpid = wait(&status); 181682a4538fSEric Badger ATF_REQUIRE(wpid == -1); 181782a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 181882a4538fSEric Badger } 181982a4538fSEric Badger 182082a4538fSEric Badger /* 182182a4538fSEric Badger * Verify that no more events are reported after PT_KILL except for the 182282a4538fSEric Badger * process exit when killing a multithreaded process. 182382a4538fSEric Badger */ 182482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads); 182582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_threads, tc) 182682a4538fSEric Badger { 182782a4538fSEric Badger struct ptrace_lwpinfo pl; 182882a4538fSEric Badger pid_t fpid, wpid; 182982a4538fSEric Badger lwpid_t main_lwp; 183082a4538fSEric Badger int status; 183182a4538fSEric Badger 183282a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 183382a4538fSEric Badger if (fpid == 0) { 183482a4538fSEric Badger trace_me(); 183582a4538fSEric Badger simple_thread_main(); 183682a4538fSEric Badger } 183782a4538fSEric Badger 183882a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 183982a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 184082a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 184182a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 184282a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 184382a4538fSEric Badger 184482a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 184582a4538fSEric Badger sizeof(pl)) != -1); 184682a4538fSEric Badger main_lwp = pl.pl_lwpid; 184782a4538fSEric Badger 184882a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0); 184982a4538fSEric Badger 185082a4538fSEric Badger /* Continue the child ignoring the SIGSTOP. */ 185182a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 185282a4538fSEric Badger 185382a4538fSEric Badger /* The first event should be for the child thread's birth. */ 185482a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 185582a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 185682a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 185782a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 185882a4538fSEric Badger 185982a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 186082a4538fSEric Badger ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) == 186182a4538fSEric Badger (PL_FLAG_BORN | PL_FLAG_SCX)); 186282a4538fSEric Badger ATF_REQUIRE(pl.pl_lwpid != main_lwp); 186382a4538fSEric Badger 186482a4538fSEric Badger /* Kill the child process. */ 186582a4538fSEric Badger ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0); 186682a4538fSEric Badger 186782a4538fSEric Badger /* The last wait() should report the SIGKILL. */ 186882a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 186982a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 187082a4538fSEric Badger ATF_REQUIRE(WIFSIGNALED(status)); 187182a4538fSEric Badger ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 187282a4538fSEric Badger 187382a4538fSEric Badger wpid = wait(&status); 187482a4538fSEric Badger ATF_REQUIRE(wpid == -1); 187582a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 187682a4538fSEric Badger } 187782a4538fSEric Badger 187882a4538fSEric Badger static void * 187982a4538fSEric Badger mask_usr1_thread(void *arg) 188082a4538fSEric Badger { 188182a4538fSEric Badger pthread_barrier_t *pbarrier; 188282a4538fSEric Badger sigset_t sigmask; 188382a4538fSEric Badger 188482a4538fSEric Badger pbarrier = (pthread_barrier_t*)arg; 188582a4538fSEric Badger 188682a4538fSEric Badger sigemptyset(&sigmask); 188782a4538fSEric Badger sigaddset(&sigmask, SIGUSR1); 188882a4538fSEric Badger CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0); 188982a4538fSEric Badger 189082a4538fSEric Badger /* Sync up with other thread after sigmask updated. */ 189182a4538fSEric Badger pthread_barrier_wait(pbarrier); 189282a4538fSEric Badger 189382a4538fSEric Badger for (;;) 189482a4538fSEric Badger sleep(60); 189582a4538fSEric Badger 189682a4538fSEric Badger return (NULL); 189782a4538fSEric Badger } 189882a4538fSEric Badger 189982a4538fSEric Badger /* 190082a4538fSEric Badger * Verify that the SIGKILL from PT_KILL takes priority over other signals 190182a4538fSEric Badger * and prevents spurious stops due to those other signals. 190282a4538fSEric Badger */ 19033cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_signal); 19043cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc) 19053cf56bb4SEnji Cooper { 19063cf56bb4SEnji Cooper 19073cf56bb4SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 19083cf56bb4SEnji Cooper } 190982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc) 191082a4538fSEric Badger { 191182a4538fSEric Badger pid_t fpid, wpid; 191282a4538fSEric Badger int status; 191382a4538fSEric Badger cpuset_t setmask; 191482a4538fSEric Badger pthread_t t; 191582a4538fSEric Badger pthread_barrier_t barrier; 1916bc2be1d3SEric Badger struct sched_param sched_param; 191782a4538fSEric Badger 191882a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 191982a4538fSEric Badger if (fpid == 0) { 1920bc2be1d3SEric Badger /* Bind to one CPU so only one thread at a time will run. */ 192182a4538fSEric Badger CPU_ZERO(&setmask); 192282a4538fSEric Badger CPU_SET(0, &setmask); 192382a4538fSEric Badger cpusetid_t setid; 192482a4538fSEric Badger CHILD_REQUIRE(cpuset(&setid) == 0); 192582a4538fSEric Badger CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET, 192682a4538fSEric Badger CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0); 192782a4538fSEric Badger 192882a4538fSEric Badger CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0); 192982a4538fSEric Badger 193082a4538fSEric Badger CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread, 193182a4538fSEric Badger (void*)&barrier) == 0); 193282a4538fSEric Badger 1933bc2be1d3SEric Badger /* 1934bc2be1d3SEric Badger * Give the main thread higher priority. The test always 1935bc2be1d3SEric Badger * assumes that, if both threads are able to run, the main 1936bc2be1d3SEric Badger * thread runs first. 1937bc2be1d3SEric Badger */ 1938bc2be1d3SEric Badger sched_param.sched_priority = 1939bc2be1d3SEric Badger (sched_get_priority_max(SCHED_FIFO) + 1940bc2be1d3SEric Badger sched_get_priority_min(SCHED_FIFO)) / 2; 1941bc2be1d3SEric Badger CHILD_REQUIRE(pthread_setschedparam(pthread_self(), 1942bc2be1d3SEric Badger SCHED_FIFO, &sched_param) == 0); 1943bc2be1d3SEric Badger sched_param.sched_priority -= RQ_PPQ; 1944bc2be1d3SEric Badger CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO, 1945bc2be1d3SEric Badger &sched_param) == 0); 1946bc2be1d3SEric Badger 194782a4538fSEric Badger sigset_t sigmask; 194882a4538fSEric Badger sigemptyset(&sigmask); 194982a4538fSEric Badger sigaddset(&sigmask, SIGUSR2); 195082a4538fSEric Badger CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0); 195182a4538fSEric Badger 195282a4538fSEric Badger /* Sync up with other thread after sigmask updated. */ 195382a4538fSEric Badger pthread_barrier_wait(&barrier); 195482a4538fSEric Badger 195582a4538fSEric Badger trace_me(); 195682a4538fSEric Badger 195782a4538fSEric Badger for (;;) 195882a4538fSEric Badger sleep(60); 195982a4538fSEric Badger 196082a4538fSEric Badger exit(1); 196182a4538fSEric Badger } 196282a4538fSEric Badger 196382a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 196482a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 196582a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 196682a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 196782a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 196882a4538fSEric Badger 196982a4538fSEric Badger /* Continue the child ignoring the SIGSTOP. */ 197082a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 197182a4538fSEric Badger 197282a4538fSEric Badger /* Send a signal that only the second thread can handle. */ 197382a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGUSR2) == 0); 197482a4538fSEric Badger 197582a4538fSEric Badger /* The second wait() should report the SIGUSR2. */ 197682a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 197782a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 197882a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 197982a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2); 198082a4538fSEric Badger 198182a4538fSEric Badger /* Send a signal that only the first thread can handle. */ 198282a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGUSR1) == 0); 198382a4538fSEric Badger 198482a4538fSEric Badger /* Replace the SIGUSR2 with a kill. */ 198582a4538fSEric Badger ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0); 198682a4538fSEric Badger 198782a4538fSEric Badger /* The last wait() should report the SIGKILL (not the SIGUSR signal). */ 198882a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 198982a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 199082a4538fSEric Badger ATF_REQUIRE(WIFSIGNALED(status)); 199182a4538fSEric Badger ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 199282a4538fSEric Badger 199382a4538fSEric Badger wpid = wait(&status); 199482a4538fSEric Badger ATF_REQUIRE(wpid == -1); 199582a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 199682a4538fSEric Badger } 199782a4538fSEric Badger 199882a4538fSEric Badger /* 199982a4538fSEric Badger * Verify that the SIGKILL from PT_KILL takes priority over other stop events 200082a4538fSEric Badger * and prevents spurious stops caused by those events. 200182a4538fSEric Badger */ 20023cf56bb4SEnji Cooper ATF_TC(ptrace__PT_KILL_competing_stop); 20033cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc) 20043cf56bb4SEnji Cooper { 20053cf56bb4SEnji Cooper 20063cf56bb4SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 20073cf56bb4SEnji Cooper } 200882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc) 200982a4538fSEric Badger { 201082a4538fSEric Badger pid_t fpid, wpid; 2011bc2be1d3SEric Badger int status; 201282a4538fSEric Badger cpuset_t setmask; 201382a4538fSEric Badger pthread_t t; 201482a4538fSEric Badger pthread_barrier_t barrier; 201582a4538fSEric Badger lwpid_t main_lwp; 201682a4538fSEric Badger struct ptrace_lwpinfo pl; 2017bc2be1d3SEric Badger struct sched_param sched_param; 201882a4538fSEric Badger 201982a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 202082a4538fSEric Badger if (fpid == 0) { 202182a4538fSEric Badger trace_me(); 202282a4538fSEric Badger 2023bc2be1d3SEric Badger /* Bind to one CPU so only one thread at a time will run. */ 202482a4538fSEric Badger CPU_ZERO(&setmask); 202582a4538fSEric Badger CPU_SET(0, &setmask); 202682a4538fSEric Badger cpusetid_t setid; 202782a4538fSEric Badger CHILD_REQUIRE(cpuset(&setid) == 0); 202882a4538fSEric Badger CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET, 202982a4538fSEric Badger CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0); 203082a4538fSEric Badger 203182a4538fSEric Badger CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0); 203282a4538fSEric Badger 203382a4538fSEric Badger CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread, 203482a4538fSEric Badger (void*)&barrier) == 0); 203582a4538fSEric Badger 2036bc2be1d3SEric Badger /* 2037bc2be1d3SEric Badger * Give the main thread higher priority. The test always 2038bc2be1d3SEric Badger * assumes that, if both threads are able to run, the main 2039bc2be1d3SEric Badger * thread runs first. 2040bc2be1d3SEric Badger */ 2041bc2be1d3SEric Badger sched_param.sched_priority = 2042bc2be1d3SEric Badger (sched_get_priority_max(SCHED_FIFO) + 2043bc2be1d3SEric Badger sched_get_priority_min(SCHED_FIFO)) / 2; 2044bc2be1d3SEric Badger CHILD_REQUIRE(pthread_setschedparam(pthread_self(), 2045bc2be1d3SEric Badger SCHED_FIFO, &sched_param) == 0); 2046bc2be1d3SEric Badger sched_param.sched_priority -= RQ_PPQ; 2047bc2be1d3SEric Badger CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO, 2048bc2be1d3SEric Badger &sched_param) == 0); 2049bc2be1d3SEric Badger 205082a4538fSEric Badger sigset_t sigmask; 205182a4538fSEric Badger sigemptyset(&sigmask); 205282a4538fSEric Badger sigaddset(&sigmask, SIGUSR2); 205382a4538fSEric Badger CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0); 205482a4538fSEric Badger 205582a4538fSEric Badger /* Sync up with other thread after sigmask updated. */ 205682a4538fSEric Badger pthread_barrier_wait(&barrier); 205782a4538fSEric Badger 205882a4538fSEric Badger /* Sync up with the test before doing the getpid(). */ 205982a4538fSEric Badger raise(SIGSTOP); 206082a4538fSEric Badger 206182a4538fSEric Badger getpid(); 206282a4538fSEric Badger exit(1); 206382a4538fSEric Badger } 206482a4538fSEric Badger 206582a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 206682a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 206782a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 206882a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 206982a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 207082a4538fSEric Badger 207182a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 207282a4538fSEric Badger main_lwp = pl.pl_lwpid; 207382a4538fSEric Badger 207482a4538fSEric Badger /* Continue the child ignoring the SIGSTOP and tracing system calls. */ 207582a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 207682a4538fSEric Badger 207782a4538fSEric Badger /* 207882a4538fSEric Badger * Continue until child is done with setup, which is indicated with 207982a4538fSEric Badger * SIGSTOP. Ignore system calls in the meantime. 208082a4538fSEric Badger */ 208182a4538fSEric Badger for (;;) { 208282a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 208382a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 208482a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 208582a4538fSEric Badger if (WSTOPSIG(status) == SIGTRAP) { 208682a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 208782a4538fSEric Badger sizeof(pl)) != -1); 208882a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)); 208982a4538fSEric Badger } else { 209082a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 209182a4538fSEric Badger break; 209282a4538fSEric Badger } 209382a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 209482a4538fSEric Badger } 209582a4538fSEric Badger 2096bc2be1d3SEric Badger /* Proceed, allowing main thread to hit syscall entry for getpid(). */ 209782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 209882a4538fSEric Badger 209982a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 210082a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 210182a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 210282a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 210382a4538fSEric Badger 210482a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 210582a4538fSEric Badger sizeof(pl)) != -1); 2106bc2be1d3SEric Badger ATF_REQUIRE(pl.pl_lwpid == main_lwp); 210782a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE); 2108bc2be1d3SEric Badger /* Prevent the main thread from hitting its syscall exit for now. */ 210982a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0); 211082a4538fSEric Badger 2111bc2be1d3SEric Badger /* 2112bc2be1d3SEric Badger * Proceed, allowing second thread to hit syscall exit for 2113bc2be1d3SEric Badger * pthread_barrier_wait(). 2114bc2be1d3SEric Badger */ 2115bc2be1d3SEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 2116bc2be1d3SEric Badger 2117bc2be1d3SEric Badger wpid = waitpid(fpid, &status, 0); 2118bc2be1d3SEric Badger ATF_REQUIRE(wpid == fpid); 2119bc2be1d3SEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 2120bc2be1d3SEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 2121bc2be1d3SEric Badger 2122bc2be1d3SEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 2123bc2be1d3SEric Badger sizeof(pl)) != -1); 2124bc2be1d3SEric Badger ATF_REQUIRE(pl.pl_lwpid != main_lwp); 2125bc2be1d3SEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX); 212682a4538fSEric Badger 212782a4538fSEric Badger /* Send a signal that only the second thread can handle. */ 212882a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGUSR2) == 0); 212982a4538fSEric Badger 213082a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 213182a4538fSEric Badger 2132bc2be1d3SEric Badger /* The next wait() should report the SIGUSR2. */ 213382a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 213482a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 213582a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 213682a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2); 213782a4538fSEric Badger 213882a4538fSEric Badger /* Allow the main thread to try to finish its system call. */ 213982a4538fSEric Badger ATF_REQUIRE(ptrace(PT_RESUME, main_lwp, 0, 0) == 0); 214082a4538fSEric Badger 214182a4538fSEric Badger /* 214282a4538fSEric Badger * At this point, the main thread is in the middle of a system call and 2143bc2be1d3SEric Badger * has been resumed. The second thread has taken a SIGUSR2 which will 2144bc2be1d3SEric Badger * be replaced with a SIGKILL below. The main thread will get to run 2145bc2be1d3SEric Badger * first. It should notice the kill request (even though the signal 2146bc2be1d3SEric Badger * replacement occurred in the other thread) and exit accordingly. It 2147bc2be1d3SEric Badger * should not stop for the system call exit event. 214882a4538fSEric Badger */ 214982a4538fSEric Badger 215082a4538fSEric Badger /* Replace the SIGUSR2 with a kill. */ 215182a4538fSEric Badger ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0); 215282a4538fSEric Badger 215382a4538fSEric Badger /* The last wait() should report the SIGKILL (not a syscall exit). */ 215482a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 215582a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 215682a4538fSEric Badger ATF_REQUIRE(WIFSIGNALED(status)); 215782a4538fSEric Badger ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 215882a4538fSEric Badger 215982a4538fSEric Badger wpid = wait(&status); 216082a4538fSEric Badger ATF_REQUIRE(wpid == -1); 216182a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 216282a4538fSEric Badger } 216382a4538fSEric Badger 216482a4538fSEric Badger static void 216582a4538fSEric Badger sigusr1_handler(int sig) 216682a4538fSEric Badger { 216782a4538fSEric Badger 216882a4538fSEric Badger CHILD_REQUIRE(sig == SIGUSR1); 216982a4538fSEric Badger _exit(2); 217082a4538fSEric Badger } 217182a4538fSEric Badger 217282a4538fSEric Badger /* 217382a4538fSEric Badger * Verify that even if the signal queue is full for a child process, 217482a4538fSEric Badger * a PT_KILL will kill the process. 217582a4538fSEric Badger */ 217682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue); 217782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc) 217882a4538fSEric Badger { 217982a4538fSEric Badger pid_t fpid, wpid; 218082a4538fSEric Badger int status; 218182a4538fSEric Badger int max_pending_per_proc; 218282a4538fSEric Badger size_t len; 218382a4538fSEric Badger int i; 218482a4538fSEric Badger 218582a4538fSEric Badger ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR); 218682a4538fSEric Badger 218782a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 218882a4538fSEric Badger if (fpid == 0) { 218982a4538fSEric Badger trace_me(); 219082a4538fSEric Badger exit(1); 219182a4538fSEric Badger } 219282a4538fSEric Badger 219382a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 219482a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 219582a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 219682a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 219782a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 219882a4538fSEric Badger 219982a4538fSEric Badger len = sizeof(max_pending_per_proc); 220082a4538fSEric Badger ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc", 220182a4538fSEric Badger &max_pending_per_proc, &len, NULL, 0) == 0); 220282a4538fSEric Badger 220382a4538fSEric Badger /* Fill the signal queue. */ 220482a4538fSEric Badger for (i = 0; i < max_pending_per_proc; ++i) 220582a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGUSR1) == 0); 220682a4538fSEric Badger 220782a4538fSEric Badger /* Kill the child process. */ 220882a4538fSEric Badger ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0); 220982a4538fSEric Badger 221082a4538fSEric Badger /* The last wait() should report the SIGKILL. */ 221182a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 221282a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 221382a4538fSEric Badger ATF_REQUIRE(WIFSIGNALED(status)); 221482a4538fSEric Badger ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 221582a4538fSEric Badger 221682a4538fSEric Badger wpid = wait(&status); 221782a4538fSEric Badger ATF_REQUIRE(wpid == -1); 221882a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 221982a4538fSEric Badger } 222082a4538fSEric Badger 222182a4538fSEric Badger /* 222282a4538fSEric Badger * Verify that when stopped at a system call entry, a signal can be 222382a4538fSEric Badger * requested with PT_CONTINUE which will be delivered once the system 222482a4538fSEric Badger * call is complete. 222582a4538fSEric Badger */ 222682a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry); 222782a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc) 222882a4538fSEric Badger { 222982a4538fSEric Badger struct ptrace_lwpinfo pl; 223082a4538fSEric Badger pid_t fpid, wpid; 223182a4538fSEric Badger int status; 223282a4538fSEric Badger 223382a4538fSEric Badger ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR); 223482a4538fSEric Badger 223582a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 223682a4538fSEric Badger if (fpid == 0) { 223782a4538fSEric Badger trace_me(); 223882a4538fSEric Badger getpid(); 223982a4538fSEric Badger exit(1); 224082a4538fSEric Badger } 224182a4538fSEric Badger 224282a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 224382a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 224482a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 224582a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 224682a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 224782a4538fSEric Badger 224882a4538fSEric Badger /* Continue the child ignoring the SIGSTOP and tracing system calls. */ 224982a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 225082a4538fSEric Badger 225182a4538fSEric Badger /* The second wait() should report a system call entry for getpid(). */ 225282a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 225382a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 225482a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 225582a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 225682a4538fSEric Badger 225782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 225882a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE); 225982a4538fSEric Badger 226082a4538fSEric Badger /* Continue the child process with a signal. */ 226182a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 226282a4538fSEric Badger 226382a4538fSEric Badger for (;;) { 226482a4538fSEric Badger /* 226582a4538fSEric Badger * The last wait() should report exit 2, i.e., a normal _exit 226682a4538fSEric Badger * from the signal handler. In the meantime, catch and proceed 226782a4538fSEric Badger * past any syscall stops. 226882a4538fSEric Badger */ 226982a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 227082a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 227182a4538fSEric Badger if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { 227282a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 227382a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)); 227482a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 227582a4538fSEric Badger } else { 227682a4538fSEric Badger ATF_REQUIRE(WIFEXITED(status)); 227782a4538fSEric Badger ATF_REQUIRE(WEXITSTATUS(status) == 2); 227882a4538fSEric Badger break; 227982a4538fSEric Badger } 228082a4538fSEric Badger } 228182a4538fSEric Badger 228282a4538fSEric Badger wpid = wait(&status); 228382a4538fSEric Badger ATF_REQUIRE(wpid == -1); 228482a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 228582a4538fSEric Badger } 228682a4538fSEric Badger 228782a4538fSEric Badger static void 228882a4538fSEric Badger sigusr1_counting_handler(int sig) 228982a4538fSEric Badger { 229082a4538fSEric Badger static int counter = 0; 229182a4538fSEric Badger 229282a4538fSEric Badger CHILD_REQUIRE(sig == SIGUSR1); 229382a4538fSEric Badger counter++; 229482a4538fSEric Badger if (counter == 2) 229582a4538fSEric Badger _exit(2); 229682a4538fSEric Badger } 229782a4538fSEric Badger 229882a4538fSEric Badger /* 229982a4538fSEric Badger * Verify that, when continuing from a stop at system call entry and exit, 230082a4538fSEric Badger * a signal can be requested from both stops, and both will be delivered when 230182a4538fSEric Badger * the system call is complete. 230282a4538fSEric Badger */ 230382a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit); 230482a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc) 230582a4538fSEric Badger { 230682a4538fSEric Badger struct ptrace_lwpinfo pl; 230782a4538fSEric Badger pid_t fpid, wpid; 230882a4538fSEric Badger int status; 230982a4538fSEric Badger 231082a4538fSEric Badger ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR); 231182a4538fSEric Badger 231282a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 231382a4538fSEric Badger if (fpid == 0) { 231482a4538fSEric Badger trace_me(); 231582a4538fSEric Badger getpid(); 231682a4538fSEric Badger exit(1); 231782a4538fSEric Badger } 231882a4538fSEric Badger 231982a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 232082a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 232182a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 232282a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 232382a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 232482a4538fSEric Badger 232582a4538fSEric Badger /* Continue the child ignoring the SIGSTOP and tracing system calls. */ 232682a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 232782a4538fSEric Badger 232882a4538fSEric Badger /* The second wait() should report a system call entry for getpid(). */ 232982a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 233082a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 233182a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 233282a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 233382a4538fSEric Badger 233482a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 233582a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE); 233682a4538fSEric Badger 233782a4538fSEric Badger /* Continue the child process with a signal. */ 233882a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 233982a4538fSEric Badger 234082a4538fSEric Badger /* The third wait() should report a system call exit for getpid(). */ 234182a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 234282a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 234382a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 234482a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 234582a4538fSEric Badger 234682a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 234782a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX); 234882a4538fSEric Badger 234982a4538fSEric Badger /* Continue the child process with a signal. */ 235082a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 235182a4538fSEric Badger 235282a4538fSEric Badger for (;;) { 235382a4538fSEric Badger /* 235482a4538fSEric Badger * The last wait() should report exit 2, i.e., a normal _exit 235582a4538fSEric Badger * from the signal handler. In the meantime, catch and proceed 235682a4538fSEric Badger * past any syscall stops. 235782a4538fSEric Badger */ 235882a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 235982a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 236082a4538fSEric Badger if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { 236182a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 236282a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)); 236382a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 236482a4538fSEric Badger } else { 236582a4538fSEric Badger ATF_REQUIRE(WIFEXITED(status)); 236682a4538fSEric Badger ATF_REQUIRE(WEXITSTATUS(status) == 2); 236782a4538fSEric Badger break; 236882a4538fSEric Badger } 236982a4538fSEric Badger } 237082a4538fSEric Badger 237182a4538fSEric Badger wpid = wait(&status); 237282a4538fSEric Badger ATF_REQUIRE(wpid == -1); 237382a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 237482a4538fSEric Badger } 237582a4538fSEric Badger 237682a4538fSEric Badger /* 237782a4538fSEric Badger * Verify that even if the signal queue is full for a child process, 237882a4538fSEric Badger * a PT_CONTINUE with a signal will not result in loss of that signal. 237982a4538fSEric Badger */ 238082a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue); 238182a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc) 238282a4538fSEric Badger { 238382a4538fSEric Badger pid_t fpid, wpid; 238482a4538fSEric Badger int status; 238582a4538fSEric Badger int max_pending_per_proc; 238682a4538fSEric Badger size_t len; 238782a4538fSEric Badger int i; 238882a4538fSEric Badger 238982a4538fSEric Badger ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR); 239082a4538fSEric Badger ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR); 239182a4538fSEric Badger 239282a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 239382a4538fSEric Badger if (fpid == 0) { 239482a4538fSEric Badger trace_me(); 239582a4538fSEric Badger exit(1); 239682a4538fSEric Badger } 239782a4538fSEric Badger 239882a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 239982a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 240082a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 240182a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 240282a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 240382a4538fSEric Badger 240482a4538fSEric Badger len = sizeof(max_pending_per_proc); 240582a4538fSEric Badger ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc", 240682a4538fSEric Badger &max_pending_per_proc, &len, NULL, 0) == 0); 240782a4538fSEric Badger 240882a4538fSEric Badger /* Fill the signal queue. */ 240982a4538fSEric Badger for (i = 0; i < max_pending_per_proc; ++i) 241082a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGUSR2) == 0); 241182a4538fSEric Badger 241282a4538fSEric Badger /* Continue with signal. */ 241382a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 241482a4538fSEric Badger 241582a4538fSEric Badger for (;;) { 241682a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 241782a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 241882a4538fSEric Badger if (WIFSTOPPED(status)) { 241982a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2); 242082a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 242182a4538fSEric Badger } else { 242282a4538fSEric Badger /* 242382a4538fSEric Badger * The last wait() should report normal _exit from the 242482a4538fSEric Badger * SIGUSR1 handler. 242582a4538fSEric Badger */ 242682a4538fSEric Badger ATF_REQUIRE(WIFEXITED(status)); 242782a4538fSEric Badger ATF_REQUIRE(WEXITSTATUS(status) == 2); 242882a4538fSEric Badger break; 242982a4538fSEric Badger } 243082a4538fSEric Badger } 243182a4538fSEric Badger 243282a4538fSEric Badger wpid = wait(&status); 243382a4538fSEric Badger ATF_REQUIRE(wpid == -1); 243482a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 243582a4538fSEric Badger } 243682a4538fSEric Badger 2437753e2922SBryan Drewery static sem_t sigusr1_sem; 2438753e2922SBryan Drewery static int got_usr1; 2439753e2922SBryan Drewery 2440753e2922SBryan Drewery static void 2441753e2922SBryan Drewery sigusr1_sempost_handler(int sig __unused) 2442753e2922SBryan Drewery { 2443753e2922SBryan Drewery 2444753e2922SBryan Drewery got_usr1++; 2445753e2922SBryan Drewery CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0); 2446753e2922SBryan Drewery } 2447753e2922SBryan Drewery 2448753e2922SBryan Drewery /* 2449753e2922SBryan Drewery * Verify that even if the signal queue is full for a child process, 2450753e2922SBryan Drewery * and the signal is masked, a PT_CONTINUE with a signal will not 2451753e2922SBryan Drewery * result in loss of that signal. 2452753e2922SBryan Drewery */ 2453753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue); 2454753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc) 2455753e2922SBryan Drewery { 2456753e2922SBryan Drewery struct ptrace_lwpinfo pl; 2457753e2922SBryan Drewery pid_t fpid, wpid; 2458753e2922SBryan Drewery int status, err; 2459753e2922SBryan Drewery int max_pending_per_proc; 2460753e2922SBryan Drewery size_t len; 2461753e2922SBryan Drewery int i; 2462753e2922SBryan Drewery sigset_t sigmask; 2463753e2922SBryan Drewery 2464753e2922SBryan Drewery ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR); 2465753e2922SBryan Drewery ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0); 2466753e2922SBryan Drewery ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR); 2467753e2922SBryan Drewery 2468753e2922SBryan Drewery got_usr1 = 0; 2469753e2922SBryan Drewery ATF_REQUIRE((fpid = fork()) != -1); 2470753e2922SBryan Drewery if (fpid == 0) { 2471753e2922SBryan Drewery CHILD_REQUIRE(sigemptyset(&sigmask) == 0); 2472753e2922SBryan Drewery CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0); 2473753e2922SBryan Drewery CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0); 2474753e2922SBryan Drewery 2475753e2922SBryan Drewery trace_me(); 2476753e2922SBryan Drewery CHILD_REQUIRE(got_usr1 == 0); 2477753e2922SBryan Drewery 2478753e2922SBryan Drewery /* Allow the pending SIGUSR1 in now. */ 2479753e2922SBryan Drewery CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0); 2480753e2922SBryan Drewery /* Wait to receive the SIGUSR1. */ 2481753e2922SBryan Drewery do { 2482753e2922SBryan Drewery err = sem_wait(&sigusr1_sem); 2483753e2922SBryan Drewery CHILD_REQUIRE(err == 0 || errno == EINTR); 2484753e2922SBryan Drewery } while (err != 0 && errno == EINTR); 2485753e2922SBryan Drewery CHILD_REQUIRE(got_usr1 == 1); 2486753e2922SBryan Drewery exit(1); 2487753e2922SBryan Drewery } 2488753e2922SBryan Drewery 2489753e2922SBryan Drewery /* The first wait() should report the stop from SIGSTOP. */ 2490753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2491753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2492753e2922SBryan Drewery ATF_REQUIRE(WIFSTOPPED(status)); 2493753e2922SBryan Drewery ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 2494753e2922SBryan Drewery 2495753e2922SBryan Drewery len = sizeof(max_pending_per_proc); 2496753e2922SBryan Drewery ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc", 2497753e2922SBryan Drewery &max_pending_per_proc, &len, NULL, 0) == 0); 2498753e2922SBryan Drewery 2499753e2922SBryan Drewery /* Fill the signal queue. */ 2500753e2922SBryan Drewery for (i = 0; i < max_pending_per_proc; ++i) 2501753e2922SBryan Drewery ATF_REQUIRE(kill(fpid, SIGUSR2) == 0); 2502753e2922SBryan Drewery 2503753e2922SBryan Drewery /* Continue with signal. */ 2504753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 2505753e2922SBryan Drewery 2506753e2922SBryan Drewery /* Collect and ignore all of the SIGUSR2. */ 2507753e2922SBryan Drewery for (i = 0; i < max_pending_per_proc; ++i) { 2508753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2509753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2510753e2922SBryan Drewery ATF_REQUIRE(WIFSTOPPED(status)); 2511753e2922SBryan Drewery ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2); 2512753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 2513753e2922SBryan Drewery } 2514753e2922SBryan Drewery 2515753e2922SBryan Drewery /* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */ 2516753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2517753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2518753e2922SBryan Drewery ATF_REQUIRE(WIFSTOPPED(status)); 2519753e2922SBryan Drewery ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1); 2520753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1); 2521753e2922SBryan Drewery ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1); 2522753e2922SBryan Drewery 2523753e2922SBryan Drewery /* Continue the child, ignoring the SIGUSR1. */ 2524753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 2525753e2922SBryan Drewery 2526753e2922SBryan Drewery /* The last wait() should report exit after receiving SIGUSR1. */ 2527753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2528753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2529753e2922SBryan Drewery ATF_REQUIRE(WIFEXITED(status)); 2530753e2922SBryan Drewery ATF_REQUIRE(WEXITSTATUS(status) == 1); 2531753e2922SBryan Drewery 2532753e2922SBryan Drewery wpid = wait(&status); 2533753e2922SBryan Drewery ATF_REQUIRE(wpid == -1); 2534753e2922SBryan Drewery ATF_REQUIRE(errno == ECHILD); 2535753e2922SBryan Drewery } 2536753e2922SBryan Drewery 253782a4538fSEric Badger /* 253882a4538fSEric Badger * Verify that, after stopping due to a signal, that signal can be 253982a4538fSEric Badger * replaced with another signal. 254082a4538fSEric Badger */ 254182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig); 254282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc) 254382a4538fSEric Badger { 254482a4538fSEric Badger struct ptrace_lwpinfo pl; 254582a4538fSEric Badger pid_t fpid, wpid; 254682a4538fSEric Badger int status; 254782a4538fSEric Badger 254882a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 254982a4538fSEric Badger if (fpid == 0) { 255082a4538fSEric Badger trace_me(); 255182a4538fSEric Badger sleep(20); 255282a4538fSEric Badger exit(1); 255382a4538fSEric Badger } 255482a4538fSEric Badger 255582a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 255682a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 255782a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 255882a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 255982a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 256082a4538fSEric Badger 256182a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 256282a4538fSEric Badger 256382a4538fSEric Badger /* Send a signal without ptrace. */ 256482a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGINT) == 0); 256582a4538fSEric Badger 256682a4538fSEric Badger /* The second wait() should report a SIGINT was received. */ 256782a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 256882a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 256982a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 257082a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGINT); 257182a4538fSEric Badger 257282a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 257382a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); 257482a4538fSEric Badger ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGINT); 257582a4538fSEric Badger 257682a4538fSEric Badger /* Continue the child process with a different signal. */ 257782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM) == 0); 257882a4538fSEric Badger 257982a4538fSEric Badger /* 258082a4538fSEric Badger * The last wait() should report having died due to the new 258182a4538fSEric Badger * signal, SIGTERM. 258282a4538fSEric Badger */ 258382a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 258482a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 258582a4538fSEric Badger ATF_REQUIRE(WIFSIGNALED(status)); 258682a4538fSEric Badger ATF_REQUIRE(WTERMSIG(status) == SIGTERM); 258782a4538fSEric Badger 258882a4538fSEric Badger wpid = wait(&status); 258982a4538fSEric Badger ATF_REQUIRE(wpid == -1); 259082a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 259182a4538fSEric Badger } 259282a4538fSEric Badger 259382a4538fSEric Badger /* 259482a4538fSEric Badger * Verify that a signal can be passed through to the child even when there 259582a4538fSEric Badger * was no true signal originally. Such cases arise when a SIGTRAP is 259682a4538fSEric Badger * invented for e.g, system call stops. 259782a4538fSEric Badger */ 259882a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry); 259982a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc) 260082a4538fSEric Badger { 260182a4538fSEric Badger struct ptrace_lwpinfo pl; 2602fc1e29dcSBryan Drewery struct rlimit rl; 260382a4538fSEric Badger pid_t fpid, wpid; 260482a4538fSEric Badger int status; 260582a4538fSEric Badger 260682a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 260782a4538fSEric Badger if (fpid == 0) { 260882a4538fSEric Badger trace_me(); 2609fc1e29dcSBryan Drewery /* SIGTRAP expected to cause exit on syscall entry. */ 2610fc1e29dcSBryan Drewery rl.rlim_cur = rl.rlim_max = 0; 2611fc1e29dcSBryan Drewery ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 261282a4538fSEric Badger getpid(); 261382a4538fSEric Badger exit(1); 261482a4538fSEric Badger } 261582a4538fSEric Badger 261682a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 261782a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 261882a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 261982a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 262082a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 262182a4538fSEric Badger 262282a4538fSEric Badger /* Continue the child ignoring the SIGSTOP and tracing system calls. */ 262382a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 262482a4538fSEric Badger 262582a4538fSEric Badger /* The second wait() should report a system call entry for getpid(). */ 262682a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 262782a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 262882a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 262982a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 263082a4538fSEric Badger 263182a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 263282a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE); 263382a4538fSEric Badger 263482a4538fSEric Badger /* Continue the child process with a SIGTRAP. */ 263582a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP) == 0); 263682a4538fSEric Badger 263782a4538fSEric Badger for (;;) { 263882a4538fSEric Badger /* 263982a4538fSEric Badger * The last wait() should report exit due to SIGTRAP. In the 264082a4538fSEric Badger * meantime, catch and proceed past any syscall stops. 264182a4538fSEric Badger */ 264282a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 264382a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 264482a4538fSEric Badger if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { 264582a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 264682a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)); 264782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 264882a4538fSEric Badger } else { 264982a4538fSEric Badger ATF_REQUIRE(WIFSIGNALED(status)); 265082a4538fSEric Badger ATF_REQUIRE(WTERMSIG(status) == SIGTRAP); 265182a4538fSEric Badger break; 265282a4538fSEric Badger } 265382a4538fSEric Badger } 265482a4538fSEric Badger 265582a4538fSEric Badger wpid = wait(&status); 265682a4538fSEric Badger ATF_REQUIRE(wpid == -1); 265782a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 265882a4538fSEric Badger 265982a4538fSEric Badger } 266082a4538fSEric Badger 266182a4538fSEric Badger /* 266282a4538fSEric Badger * A mixed bag PT_CONTINUE with signal test. 266382a4538fSEric Badger */ 266482a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix); 266582a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc) 266682a4538fSEric Badger { 266782a4538fSEric Badger struct ptrace_lwpinfo pl; 266882a4538fSEric Badger pid_t fpid, wpid; 266982a4538fSEric Badger int status; 267082a4538fSEric Badger 267182a4538fSEric Badger ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR); 267282a4538fSEric Badger 267382a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 267482a4538fSEric Badger if (fpid == 0) { 267582a4538fSEric Badger trace_me(); 267682a4538fSEric Badger getpid(); 267782a4538fSEric Badger exit(1); 267882a4538fSEric Badger } 267982a4538fSEric Badger 268082a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 268182a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 268282a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 268382a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 268482a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 268582a4538fSEric Badger 268682a4538fSEric Badger /* Continue the child ignoring the SIGSTOP and tracing system calls. */ 268782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); 268882a4538fSEric Badger 268982a4538fSEric Badger /* The second wait() should report a system call entry for getpid(). */ 269082a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 269182a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 269282a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 269382a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 269482a4538fSEric Badger 269582a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 269682a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE); 269782a4538fSEric Badger 269882a4538fSEric Badger /* Continue with the first SIGUSR1. */ 269982a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 270082a4538fSEric Badger 270182a4538fSEric Badger /* The next wait() should report a system call exit for getpid(). */ 270282a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 270382a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 270482a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 270582a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 270682a4538fSEric Badger 270782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 270882a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX); 270982a4538fSEric Badger 271082a4538fSEric Badger /* Send an ABRT without ptrace. */ 271182a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGABRT) == 0); 271282a4538fSEric Badger 271382a4538fSEric Badger /* Continue normally. */ 271482a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 271582a4538fSEric Badger 271682a4538fSEric Badger /* The next wait() should report the SIGABRT. */ 271782a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 271882a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 271982a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 272082a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGABRT); 272182a4538fSEric Badger 272282a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 272382a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); 272482a4538fSEric Badger ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT); 272582a4538fSEric Badger 272682a4538fSEric Badger /* Continue, replacing the SIGABRT with another SIGUSR1. */ 272782a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 272882a4538fSEric Badger 272982a4538fSEric Badger for (;;) { 273082a4538fSEric Badger /* 273182a4538fSEric Badger * The last wait() should report exit 2, i.e., a normal _exit 273282a4538fSEric Badger * from the signal handler. In the meantime, catch and proceed 273382a4538fSEric Badger * past any syscall stops. 273482a4538fSEric Badger */ 273582a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 273682a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 273782a4538fSEric Badger if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { 273882a4538fSEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 273982a4538fSEric Badger ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)); 274082a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 274182a4538fSEric Badger } else { 274282a4538fSEric Badger ATF_REQUIRE(WIFEXITED(status)); 274382a4538fSEric Badger ATF_REQUIRE(WEXITSTATUS(status) == 2); 274482a4538fSEric Badger break; 274582a4538fSEric Badger } 274682a4538fSEric Badger } 274782a4538fSEric Badger 274882a4538fSEric Badger wpid = wait(&status); 274982a4538fSEric Badger ATF_REQUIRE(wpid == -1); 275082a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 275182a4538fSEric Badger 275282a4538fSEric Badger } 275382a4538fSEric Badger 275482a4538fSEric Badger /* 275582a4538fSEric Badger * Verify a signal delivered by ptrace is noticed by kevent(2). 275682a4538fSEric Badger */ 275782a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue); 275882a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc) 275982a4538fSEric Badger { 276082a4538fSEric Badger pid_t fpid, wpid; 276182a4538fSEric Badger int status, kq, nevents; 276282a4538fSEric Badger struct kevent kev; 276382a4538fSEric Badger 276482a4538fSEric Badger ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR); 276582a4538fSEric Badger 276682a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 276782a4538fSEric Badger if (fpid == 0) { 276882a4538fSEric Badger CHILD_REQUIRE((kq = kqueue()) > 0); 276982a4538fSEric Badger EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0); 277082a4538fSEric Badger CHILD_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0); 277182a4538fSEric Badger 277282a4538fSEric Badger trace_me(); 277382a4538fSEric Badger 277482a4538fSEric Badger for (;;) { 277582a4538fSEric Badger nevents = kevent(kq, NULL, 0, &kev, 1, NULL); 277682a4538fSEric Badger if (nevents == -1 && errno == EINTR) 277782a4538fSEric Badger continue; 277882a4538fSEric Badger CHILD_REQUIRE(nevents > 0); 277982a4538fSEric Badger CHILD_REQUIRE(kev.filter == EVFILT_SIGNAL); 278082a4538fSEric Badger CHILD_REQUIRE(kev.ident == SIGUSR1); 278182a4538fSEric Badger break; 278282a4538fSEric Badger } 278382a4538fSEric Badger 278482a4538fSEric Badger exit(1); 278582a4538fSEric Badger } 278682a4538fSEric Badger 278782a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 278882a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 278982a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 279082a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 279182a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 279282a4538fSEric Badger 279382a4538fSEric Badger /* Continue with the SIGUSR1. */ 279482a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 279582a4538fSEric Badger 279682a4538fSEric Badger /* 279782a4538fSEric Badger * The last wait() should report normal exit with code 1. 279882a4538fSEric Badger */ 279982a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 280082a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 280182a4538fSEric Badger ATF_REQUIRE(WIFEXITED(status)); 280282a4538fSEric Badger ATF_REQUIRE(WEXITSTATUS(status) == 1); 280382a4538fSEric Badger 280482a4538fSEric Badger wpid = wait(&status); 280582a4538fSEric Badger ATF_REQUIRE(wpid == -1); 280682a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 280782a4538fSEric Badger } 280882a4538fSEric Badger 280982a4538fSEric Badger static void * 281082a4538fSEric Badger signal_thread(void *arg) 281182a4538fSEric Badger { 281282a4538fSEric Badger int err; 281382a4538fSEric Badger sigset_t sigmask; 281482a4538fSEric Badger 281582a4538fSEric Badger pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg; 281682a4538fSEric Badger 281782a4538fSEric Badger /* Wait for this thread to receive a SIGUSR1. */ 281882a4538fSEric Badger do { 281982a4538fSEric Badger err = sem_wait(&sigusr1_sem); 282082a4538fSEric Badger CHILD_REQUIRE(err == 0 || errno == EINTR); 282182a4538fSEric Badger } while (err != 0 && errno == EINTR); 282282a4538fSEric Badger 282382a4538fSEric Badger /* Free our companion thread from the barrier. */ 282482a4538fSEric Badger pthread_barrier_wait(pbarrier); 282582a4538fSEric Badger 282682a4538fSEric Badger /* 282782a4538fSEric Badger * Swap ignore duties; the next SIGUSR1 should go to the 282882a4538fSEric Badger * other thread. 282982a4538fSEric Badger */ 283082a4538fSEric Badger CHILD_REQUIRE(sigemptyset(&sigmask) == 0); 283182a4538fSEric Badger CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0); 283282a4538fSEric Badger CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0); 283382a4538fSEric Badger 283482a4538fSEric Badger /* Sync up threads after swapping signal masks. */ 283582a4538fSEric Badger pthread_barrier_wait(pbarrier); 283682a4538fSEric Badger 283782a4538fSEric Badger /* Wait until our companion has received its SIGUSR1. */ 283882a4538fSEric Badger pthread_barrier_wait(pbarrier); 283982a4538fSEric Badger 284082a4538fSEric Badger return (NULL); 284182a4538fSEric Badger } 284282a4538fSEric Badger 284382a4538fSEric Badger /* 2844753e2922SBryan Drewery * Verify that a traced process with blocked signal received the 2845753e2922SBryan Drewery * signal from kill() once unmasked. 2846753e2922SBryan Drewery */ 2847753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask); 2848753e2922SBryan Drewery ATF_TC_BODY(ptrace__killed_with_sigmask, tc) 2849753e2922SBryan Drewery { 2850753e2922SBryan Drewery struct ptrace_lwpinfo pl; 2851753e2922SBryan Drewery pid_t fpid, wpid; 2852753e2922SBryan Drewery int status, err; 2853753e2922SBryan Drewery sigset_t sigmask; 2854753e2922SBryan Drewery 2855753e2922SBryan Drewery ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0); 2856753e2922SBryan Drewery ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR); 2857753e2922SBryan Drewery got_usr1 = 0; 2858753e2922SBryan Drewery 2859753e2922SBryan Drewery ATF_REQUIRE((fpid = fork()) != -1); 2860753e2922SBryan Drewery if (fpid == 0) { 2861753e2922SBryan Drewery CHILD_REQUIRE(sigemptyset(&sigmask) == 0); 2862753e2922SBryan Drewery CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0); 2863753e2922SBryan Drewery CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0); 2864753e2922SBryan Drewery 2865753e2922SBryan Drewery trace_me(); 2866753e2922SBryan Drewery CHILD_REQUIRE(got_usr1 == 0); 2867753e2922SBryan Drewery 2868753e2922SBryan Drewery /* Allow the pending SIGUSR1 in now. */ 2869753e2922SBryan Drewery CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0); 2870753e2922SBryan Drewery /* Wait to receive a SIGUSR1. */ 2871753e2922SBryan Drewery do { 2872753e2922SBryan Drewery err = sem_wait(&sigusr1_sem); 2873753e2922SBryan Drewery CHILD_REQUIRE(err == 0 || errno == EINTR); 2874753e2922SBryan Drewery } while (err != 0 && errno == EINTR); 2875753e2922SBryan Drewery CHILD_REQUIRE(got_usr1 == 1); 2876753e2922SBryan Drewery exit(1); 2877753e2922SBryan Drewery } 2878753e2922SBryan Drewery 2879753e2922SBryan Drewery /* The first wait() should report the stop from SIGSTOP. */ 2880753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2881753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2882753e2922SBryan Drewery ATF_REQUIRE(WIFSTOPPED(status)); 2883753e2922SBryan Drewery ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 2884753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1); 2885753e2922SBryan Drewery ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP); 2886753e2922SBryan Drewery 2887753e2922SBryan Drewery /* Send blocked SIGUSR1 which should cause a stop. */ 2888753e2922SBryan Drewery ATF_REQUIRE(kill(fpid, SIGUSR1) == 0); 2889753e2922SBryan Drewery 2890753e2922SBryan Drewery /* Continue the child ignoring the SIGSTOP. */ 2891753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 2892753e2922SBryan Drewery 2893753e2922SBryan Drewery /* The next wait() should report the kill(SIGUSR1) was received. */ 2894753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2895753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2896753e2922SBryan Drewery ATF_REQUIRE(WIFSTOPPED(status)); 2897753e2922SBryan Drewery ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1); 2898753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1); 2899753e2922SBryan Drewery ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1); 2900753e2922SBryan Drewery 2901753e2922SBryan Drewery /* Continue the child, allowing in the SIGUSR1. */ 2902753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 2903753e2922SBryan Drewery 2904753e2922SBryan Drewery /* The last wait() should report normal exit with code 1. */ 2905753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2906753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2907753e2922SBryan Drewery ATF_REQUIRE(WIFEXITED(status)); 2908753e2922SBryan Drewery ATF_REQUIRE(WEXITSTATUS(status) == 1); 2909753e2922SBryan Drewery 2910753e2922SBryan Drewery wpid = wait(&status); 2911753e2922SBryan Drewery ATF_REQUIRE(wpid == -1); 2912753e2922SBryan Drewery ATF_REQUIRE(errno == ECHILD); 2913753e2922SBryan Drewery } 2914753e2922SBryan Drewery 2915753e2922SBryan Drewery /* 2916753e2922SBryan Drewery * Verify that a traced process with blocked signal received the 2917753e2922SBryan Drewery * signal from PT_CONTINUE once unmasked. 2918753e2922SBryan Drewery */ 2919753e2922SBryan Drewery ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask); 2920753e2922SBryan Drewery ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc) 2921753e2922SBryan Drewery { 2922753e2922SBryan Drewery struct ptrace_lwpinfo pl; 2923753e2922SBryan Drewery pid_t fpid, wpid; 2924753e2922SBryan Drewery int status, err; 2925753e2922SBryan Drewery sigset_t sigmask; 2926753e2922SBryan Drewery 2927753e2922SBryan Drewery ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0); 2928753e2922SBryan Drewery ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR); 2929753e2922SBryan Drewery got_usr1 = 0; 2930753e2922SBryan Drewery 2931753e2922SBryan Drewery ATF_REQUIRE((fpid = fork()) != -1); 2932753e2922SBryan Drewery if (fpid == 0) { 2933753e2922SBryan Drewery CHILD_REQUIRE(sigemptyset(&sigmask) == 0); 2934753e2922SBryan Drewery CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0); 2935753e2922SBryan Drewery CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0); 2936753e2922SBryan Drewery 2937753e2922SBryan Drewery trace_me(); 2938753e2922SBryan Drewery CHILD_REQUIRE(got_usr1 == 0); 2939753e2922SBryan Drewery 2940753e2922SBryan Drewery /* Allow the pending SIGUSR1 in now. */ 2941753e2922SBryan Drewery CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0); 2942753e2922SBryan Drewery /* Wait to receive a SIGUSR1. */ 2943753e2922SBryan Drewery do { 2944753e2922SBryan Drewery err = sem_wait(&sigusr1_sem); 2945753e2922SBryan Drewery CHILD_REQUIRE(err == 0 || errno == EINTR); 2946753e2922SBryan Drewery } while (err != 0 && errno == EINTR); 2947753e2922SBryan Drewery 2948753e2922SBryan Drewery CHILD_REQUIRE(got_usr1 == 1); 2949753e2922SBryan Drewery exit(1); 2950753e2922SBryan Drewery } 2951753e2922SBryan Drewery 2952753e2922SBryan Drewery /* The first wait() should report the stop from SIGSTOP. */ 2953753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2954753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2955753e2922SBryan Drewery ATF_REQUIRE(WIFSTOPPED(status)); 2956753e2922SBryan Drewery ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 2957753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1); 2958753e2922SBryan Drewery ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP); 2959753e2922SBryan Drewery 2960753e2922SBryan Drewery /* Continue the child replacing SIGSTOP with SIGUSR1. */ 2961753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 2962753e2922SBryan Drewery 2963753e2922SBryan Drewery /* The next wait() should report the SIGUSR1 was received. */ 2964753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2965753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2966753e2922SBryan Drewery ATF_REQUIRE(WIFSTOPPED(status)); 2967753e2922SBryan Drewery ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1); 2968753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1); 2969753e2922SBryan Drewery ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1); 2970753e2922SBryan Drewery 2971753e2922SBryan Drewery /* Continue the child, ignoring the SIGUSR1. */ 2972753e2922SBryan Drewery ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 2973753e2922SBryan Drewery 2974753e2922SBryan Drewery /* The last wait() should report normal exit with code 1. */ 2975753e2922SBryan Drewery wpid = waitpid(fpid, &status, 0); 2976753e2922SBryan Drewery ATF_REQUIRE(wpid == fpid); 2977753e2922SBryan Drewery ATF_REQUIRE(WIFEXITED(status)); 2978753e2922SBryan Drewery ATF_REQUIRE(WEXITSTATUS(status) == 1); 2979753e2922SBryan Drewery 2980753e2922SBryan Drewery wpid = wait(&status); 2981753e2922SBryan Drewery ATF_REQUIRE(wpid == -1); 2982753e2922SBryan Drewery ATF_REQUIRE(errno == ECHILD); 2983753e2922SBryan Drewery } 2984753e2922SBryan Drewery 2985753e2922SBryan Drewery /* 298682a4538fSEric Badger * Verify that if ptrace stops due to a signal but continues with 298782a4538fSEric Badger * a different signal that the new signal is routed to a thread 298899144520SEitan Adler * that can accept it, and that the thread is awakened by the signal 298982a4538fSEric Badger * in a timely manner. 299082a4538fSEric Badger */ 299182a4538fSEric Badger ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask); 299282a4538fSEric Badger ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc) 299382a4538fSEric Badger { 299482a4538fSEric Badger pid_t fpid, wpid; 299582a4538fSEric Badger int status, err; 299682a4538fSEric Badger pthread_t t; 299782a4538fSEric Badger sigset_t sigmask; 299882a4538fSEric Badger pthread_barrier_t barrier; 299982a4538fSEric Badger 300082a4538fSEric Badger ATF_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0); 300182a4538fSEric Badger ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0); 300282a4538fSEric Badger ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR); 300382a4538fSEric Badger 300482a4538fSEric Badger ATF_REQUIRE((fpid = fork()) != -1); 300582a4538fSEric Badger if (fpid == 0) { 300682a4538fSEric Badger CHILD_REQUIRE(pthread_create(&t, NULL, signal_thread, (void*)&barrier) == 0); 300782a4538fSEric Badger 300882a4538fSEric Badger /* The other thread should receive the first SIGUSR1. */ 300982a4538fSEric Badger CHILD_REQUIRE(sigemptyset(&sigmask) == 0); 301082a4538fSEric Badger CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0); 301182a4538fSEric Badger CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0); 301282a4538fSEric Badger 301382a4538fSEric Badger trace_me(); 301482a4538fSEric Badger 301582a4538fSEric Badger /* Wait until other thread has received its SIGUSR1. */ 301682a4538fSEric Badger pthread_barrier_wait(&barrier); 301782a4538fSEric Badger 301882a4538fSEric Badger /* 301982a4538fSEric Badger * Swap ignore duties; the next SIGUSR1 should go to this 302082a4538fSEric Badger * thread. 302182a4538fSEric Badger */ 302282a4538fSEric Badger CHILD_REQUIRE(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL) == 0); 302382a4538fSEric Badger 302482a4538fSEric Badger /* Sync up threads after swapping signal masks. */ 302582a4538fSEric Badger pthread_barrier_wait(&barrier); 302682a4538fSEric Badger 302782a4538fSEric Badger /* 302882a4538fSEric Badger * Sync up with test code; we're ready for the next SIGUSR1 302982a4538fSEric Badger * now. 303082a4538fSEric Badger */ 303182a4538fSEric Badger raise(SIGSTOP); 303282a4538fSEric Badger 303382a4538fSEric Badger /* Wait for this thread to receive a SIGUSR1. */ 303482a4538fSEric Badger do { 303582a4538fSEric Badger err = sem_wait(&sigusr1_sem); 303682a4538fSEric Badger CHILD_REQUIRE(err == 0 || errno == EINTR); 303782a4538fSEric Badger } while (err != 0 && errno == EINTR); 303882a4538fSEric Badger 303982a4538fSEric Badger /* Free the other thread from the barrier. */ 304082a4538fSEric Badger pthread_barrier_wait(&barrier); 304182a4538fSEric Badger 304282a4538fSEric Badger CHILD_REQUIRE(pthread_join(t, NULL) == 0); 304382a4538fSEric Badger 304482a4538fSEric Badger exit(1); 304582a4538fSEric Badger } 304682a4538fSEric Badger 304782a4538fSEric Badger /* The first wait() should report the stop from SIGSTOP. */ 304882a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 304982a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 305082a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 305182a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 305282a4538fSEric Badger 305382a4538fSEric Badger /* Continue the child ignoring the SIGSTOP. */ 305482a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 305582a4538fSEric Badger 305682a4538fSEric Badger /* 305782a4538fSEric Badger * Send a signal without ptrace that either thread will accept (USR2, 305882a4538fSEric Badger * in this case). 305982a4538fSEric Badger */ 306082a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGUSR2) == 0); 306182a4538fSEric Badger 306282a4538fSEric Badger /* The second wait() should report a SIGUSR2 was received. */ 306382a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 306482a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 306582a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 306682a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2); 306782a4538fSEric Badger 306882a4538fSEric Badger /* Continue the child, changing the signal to USR1. */ 306982a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 307082a4538fSEric Badger 307182a4538fSEric Badger /* The next wait() should report the stop from SIGSTOP. */ 307282a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 307382a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 307482a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 307582a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 307682a4538fSEric Badger 307782a4538fSEric Badger /* Continue the child ignoring the SIGSTOP. */ 307882a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 307982a4538fSEric Badger 308082a4538fSEric Badger ATF_REQUIRE(kill(fpid, SIGUSR2) == 0); 308182a4538fSEric Badger 308282a4538fSEric Badger /* The next wait() should report a SIGUSR2 was received. */ 308382a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 308482a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 308582a4538fSEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 308682a4538fSEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2); 308782a4538fSEric Badger 308882a4538fSEric Badger /* Continue the child, changing the signal to USR1. */ 308982a4538fSEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0); 309082a4538fSEric Badger 309182a4538fSEric Badger /* The last wait() should report normal exit with code 1. */ 309282a4538fSEric Badger wpid = waitpid(fpid, &status, 0); 309382a4538fSEric Badger ATF_REQUIRE(wpid == fpid); 309482a4538fSEric Badger ATF_REQUIRE(WIFEXITED(status)); 309582a4538fSEric Badger ATF_REQUIRE(WEXITSTATUS(status) == 1); 309682a4538fSEric Badger 309782a4538fSEric Badger wpid = wait(&status); 309882a4538fSEric Badger ATF_REQUIRE(wpid == -1); 309982a4538fSEric Badger ATF_REQUIRE(errno == ECHILD); 310082a4538fSEric Badger } 310182a4538fSEric Badger 3102b38bd91fSEric Badger static void * 3103b38bd91fSEric Badger raise_sigstop_thread(void *arg __unused) 3104b38bd91fSEric Badger { 3105b38bd91fSEric Badger 3106b38bd91fSEric Badger raise(SIGSTOP); 3107b38bd91fSEric Badger return NULL; 3108b38bd91fSEric Badger } 3109b38bd91fSEric Badger 3110b38bd91fSEric Badger static void * 3111b38bd91fSEric Badger sleep_thread(void *arg __unused) 3112b38bd91fSEric Badger { 3113b38bd91fSEric Badger 3114b38bd91fSEric Badger sleep(60); 3115b38bd91fSEric Badger return NULL; 3116b38bd91fSEric Badger } 3117b38bd91fSEric Badger 3118b38bd91fSEric Badger static void 3119b38bd91fSEric Badger terminate_with_pending_sigstop(bool sigstop_from_main_thread) 3120b38bd91fSEric Badger { 3121b38bd91fSEric Badger pid_t fpid, wpid; 3122b38bd91fSEric Badger int status, i; 3123b38bd91fSEric Badger cpuset_t setmask; 3124b38bd91fSEric Badger cpusetid_t setid; 3125b38bd91fSEric Badger pthread_t t; 3126b38bd91fSEric Badger 3127b38bd91fSEric Badger /* 3128b38bd91fSEric Badger * Become the reaper for this process tree. We need to be able to check 3129b38bd91fSEric Badger * that both child and grandchild have died. 3130b38bd91fSEric Badger */ 3131b38bd91fSEric Badger ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0); 3132b38bd91fSEric Badger 3133b38bd91fSEric Badger fpid = fork(); 3134b38bd91fSEric Badger ATF_REQUIRE(fpid >= 0); 3135b38bd91fSEric Badger if (fpid == 0) { 3136b38bd91fSEric Badger fpid = fork(); 3137b38bd91fSEric Badger CHILD_REQUIRE(fpid >= 0); 3138b38bd91fSEric Badger if (fpid == 0) { 3139b38bd91fSEric Badger trace_me(); 3140b38bd91fSEric Badger 3141b38bd91fSEric Badger /* Pin to CPU 0 to serialize thread execution. */ 3142b38bd91fSEric Badger CPU_ZERO(&setmask); 3143b38bd91fSEric Badger CPU_SET(0, &setmask); 3144b38bd91fSEric Badger CHILD_REQUIRE(cpuset(&setid) == 0); 3145b38bd91fSEric Badger CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET, 3146b38bd91fSEric Badger CPU_WHICH_CPUSET, setid, 3147b38bd91fSEric Badger sizeof(setmask), &setmask) == 0); 3148b38bd91fSEric Badger 3149b38bd91fSEric Badger if (sigstop_from_main_thread) { 3150b38bd91fSEric Badger /* 3151b38bd91fSEric Badger * We expect the SIGKILL sent when our parent 3152b38bd91fSEric Badger * dies to be delivered to the new thread. 3153b38bd91fSEric Badger * Raise the SIGSTOP in this thread so the 3154b38bd91fSEric Badger * threads compete. 3155b38bd91fSEric Badger */ 3156b38bd91fSEric Badger CHILD_REQUIRE(pthread_create(&t, NULL, 3157b38bd91fSEric Badger sleep_thread, NULL) == 0); 3158b38bd91fSEric Badger raise(SIGSTOP); 3159b38bd91fSEric Badger } else { 3160b38bd91fSEric Badger /* 3161b38bd91fSEric Badger * We expect the SIGKILL to be delivered to 3162b38bd91fSEric Badger * this thread. After creating the new thread, 3163b38bd91fSEric Badger * just get off the CPU so the other thread can 3164b38bd91fSEric Badger * raise the SIGSTOP. 3165b38bd91fSEric Badger */ 3166b38bd91fSEric Badger CHILD_REQUIRE(pthread_create(&t, NULL, 3167b38bd91fSEric Badger raise_sigstop_thread, NULL) == 0); 3168b38bd91fSEric Badger sleep(60); 3169b38bd91fSEric Badger } 3170b38bd91fSEric Badger 3171b38bd91fSEric Badger exit(0); 3172b38bd91fSEric Badger } 3173b38bd91fSEric Badger /* First stop is trace_me() immediately after fork. */ 3174b38bd91fSEric Badger wpid = waitpid(fpid, &status, 0); 3175b38bd91fSEric Badger CHILD_REQUIRE(wpid == fpid); 3176b38bd91fSEric Badger CHILD_REQUIRE(WIFSTOPPED(status)); 3177b38bd91fSEric Badger CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 3178b38bd91fSEric Badger 3179b38bd91fSEric Badger CHILD_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3180b38bd91fSEric Badger 3181b38bd91fSEric Badger /* Second stop is from the raise(SIGSTOP). */ 3182b38bd91fSEric Badger wpid = waitpid(fpid, &status, 0); 3183b38bd91fSEric Badger CHILD_REQUIRE(wpid == fpid); 3184b38bd91fSEric Badger CHILD_REQUIRE(WIFSTOPPED(status)); 3185b38bd91fSEric Badger CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 3186b38bd91fSEric Badger 3187b38bd91fSEric Badger /* 3188b38bd91fSEric Badger * Terminate tracing process without detaching. Our child 3189b38bd91fSEric Badger * should be killed. 3190b38bd91fSEric Badger */ 3191b38bd91fSEric Badger exit(0); 3192b38bd91fSEric Badger } 3193b38bd91fSEric Badger 3194b38bd91fSEric Badger /* 3195b38bd91fSEric Badger * We should get a normal exit from our immediate child and a SIGKILL 3196b38bd91fSEric Badger * exit from our grandchild. The latter case is the interesting one. 3197b38bd91fSEric Badger * Our grandchild should not have stopped due to the SIGSTOP that was 3198b38bd91fSEric Badger * left dangling when its parent died. 3199b38bd91fSEric Badger */ 3200b38bd91fSEric Badger for (i = 0; i < 2; ++i) { 3201b38bd91fSEric Badger wpid = wait(&status); 3202b38bd91fSEric Badger if (wpid == fpid) 3203b38bd91fSEric Badger ATF_REQUIRE(WIFEXITED(status) && 3204b38bd91fSEric Badger WEXITSTATUS(status) == 0); 3205b38bd91fSEric Badger else 3206b38bd91fSEric Badger ATF_REQUIRE(WIFSIGNALED(status) && 3207b38bd91fSEric Badger WTERMSIG(status) == SIGKILL); 3208b38bd91fSEric Badger } 3209b38bd91fSEric Badger } 3210b38bd91fSEric Badger 3211b38bd91fSEric Badger /* 3212b38bd91fSEric Badger * These two tests ensure that if the tracing process exits without detaching 3213b38bd91fSEric Badger * just after the child received a SIGSTOP, the child is cleanly killed and 3214b38bd91fSEric Badger * doesn't go to sleep due to the SIGSTOP. The parent's death will send a 3215b38bd91fSEric Badger * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by 3216b38bd91fSEric Badger * different threads, the SIGKILL must win. There are two variants of this 3217b38bd91fSEric Badger * test, designed to catch the case where the SIGKILL is delivered to the 3218b38bd91fSEric Badger * younger thread (the first test) and the case where the SIGKILL is delivered 3219b38bd91fSEric Badger * to the older thread (the second test). This behavior has changed in the 3220b38bd91fSEric Badger * past, so make no assumption. 3221b38bd91fSEric Badger */ 32223cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop1); 32233cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc) 32243cf56bb4SEnji Cooper { 32253cf56bb4SEnji Cooper 32263cf56bb4SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 32273cf56bb4SEnji Cooper } 3228b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc) 3229b38bd91fSEric Badger { 3230b38bd91fSEric Badger 3231b38bd91fSEric Badger terminate_with_pending_sigstop(true); 3232b38bd91fSEric Badger } 32333cf56bb4SEnji Cooper 32343cf56bb4SEnji Cooper ATF_TC(ptrace__parent_terminate_with_pending_sigstop2); 32353cf56bb4SEnji Cooper ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc) 32363cf56bb4SEnji Cooper { 32373cf56bb4SEnji Cooper 32383cf56bb4SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 32393cf56bb4SEnji Cooper } 3240b38bd91fSEric Badger ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc) 3241b38bd91fSEric Badger { 3242b38bd91fSEric Badger 3243b38bd91fSEric Badger terminate_with_pending_sigstop(false); 3244b38bd91fSEric Badger } 3245b38bd91fSEric Badger 3246b4d33259SEric Badger /* 3247b4d33259SEric Badger * Verify that after ptrace() discards a SIGKILL signal, the event mask 3248b4d33259SEric Badger * is not modified. 3249b4d33259SEric Badger */ 3250b4d33259SEric Badger ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard); 3251b4d33259SEric Badger ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc) 3252b4d33259SEric Badger { 3253b4d33259SEric Badger struct ptrace_lwpinfo pl; 3254b4d33259SEric Badger pid_t fpid, wpid; 3255b4d33259SEric Badger int status, event_mask, new_event_mask; 3256b4d33259SEric Badger 3257b4d33259SEric Badger ATF_REQUIRE((fpid = fork()) != -1); 3258b4d33259SEric Badger if (fpid == 0) { 3259b4d33259SEric Badger trace_me(); 3260b4d33259SEric Badger raise(SIGSTOP); 3261b4d33259SEric Badger exit(0); 3262b4d33259SEric Badger } 3263b4d33259SEric Badger 3264b4d33259SEric Badger /* The first wait() should report the stop from trace_me(). */ 3265b4d33259SEric Badger wpid = waitpid(fpid, &status, 0); 3266b4d33259SEric Badger ATF_REQUIRE(wpid == fpid); 3267b4d33259SEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 3268b4d33259SEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 3269b4d33259SEric Badger 3270b4d33259SEric Badger /* Set several unobtrusive event bits. */ 3271b4d33259SEric Badger event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP; 3272b4d33259SEric Badger ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask, 3273b4d33259SEric Badger sizeof(event_mask)) == 0); 3274b4d33259SEric Badger 3275b4d33259SEric Badger /* Send a SIGKILL without using ptrace. */ 3276b4d33259SEric Badger ATF_REQUIRE(kill(fpid, SIGKILL) == 0); 3277b4d33259SEric Badger 3278b4d33259SEric Badger /* Continue the child ignoring the SIGSTOP. */ 3279b4d33259SEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3280b4d33259SEric Badger 3281b4d33259SEric Badger /* The next stop should be due to the SIGKILL. */ 3282b4d33259SEric Badger wpid = waitpid(fpid, &status, 0); 3283b4d33259SEric Badger ATF_REQUIRE(wpid == fpid); 3284b4d33259SEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 3285b4d33259SEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGKILL); 3286b4d33259SEric Badger 3287b4d33259SEric Badger ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 3288b4d33259SEric Badger ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); 3289b4d33259SEric Badger ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGKILL); 3290b4d33259SEric Badger 3291b4d33259SEric Badger /* Continue the child ignoring the SIGKILL. */ 3292b4d33259SEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3293b4d33259SEric Badger 3294b4d33259SEric Badger /* The next wait() should report the stop from SIGSTOP. */ 3295b4d33259SEric Badger wpid = waitpid(fpid, &status, 0); 3296b4d33259SEric Badger ATF_REQUIRE(wpid == fpid); 3297b4d33259SEric Badger ATF_REQUIRE(WIFSTOPPED(status)); 3298b4d33259SEric Badger ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 3299b4d33259SEric Badger 3300b4d33259SEric Badger /* Check the current event mask. It should not have changed. */ 3301b4d33259SEric Badger new_event_mask = 0; 3302b4d33259SEric Badger ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask, 3303b4d33259SEric Badger sizeof(new_event_mask)) == 0); 3304b4d33259SEric Badger ATF_REQUIRE(event_mask == new_event_mask); 3305b4d33259SEric Badger 3306b4d33259SEric Badger /* Continue the child to let it exit. */ 3307b4d33259SEric Badger ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3308b4d33259SEric Badger 3309b4d33259SEric Badger /* The last event should be for the child process's exit. */ 3310b4d33259SEric Badger wpid = waitpid(fpid, &status, 0); 3311b4d33259SEric Badger ATF_REQUIRE(WIFEXITED(status)); 3312b4d33259SEric Badger ATF_REQUIRE(WEXITSTATUS(status) == 0); 3313b4d33259SEric Badger 3314b4d33259SEric Badger wpid = wait(&status); 3315b4d33259SEric Badger ATF_REQUIRE(wpid == -1); 3316b4d33259SEric Badger ATF_REQUIRE(errno == ECHILD); 3317b4d33259SEric Badger } 3318b4d33259SEric Badger 3319d74da94cSMark Johnston static void * 3320d74da94cSMark Johnston flock_thread(void *arg) 3321d74da94cSMark Johnston { 3322d74da94cSMark Johnston int fd; 3323d74da94cSMark Johnston 3324d74da94cSMark Johnston fd = *(int *)arg; 3325d74da94cSMark Johnston (void)flock(fd, LOCK_EX); 3326d74da94cSMark Johnston (void)flock(fd, LOCK_UN); 3327d74da94cSMark Johnston return (NULL); 3328d74da94cSMark Johnston } 3329d74da94cSMark Johnston 3330d74da94cSMark Johnston /* 3331d74da94cSMark Johnston * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section. 3332d74da94cSMark Johnston * We rely on the fact that the lockf implementation sets SBDRY before blocking 3333d74da94cSMark Johnston * on a lock. This is a regression test for r318191. 3334d74da94cSMark Johnston */ 3335d74da94cSMark Johnston ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread); 3336d74da94cSMark Johnston ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc) 3337d74da94cSMark Johnston { 3338d74da94cSMark Johnston pthread_barrier_t barrier; 3339d74da94cSMark Johnston pthread_barrierattr_t battr; 3340d74da94cSMark Johnston char tmpfile[64]; 3341d74da94cSMark Johnston pid_t child, wpid; 3342d74da94cSMark Johnston int error, fd, i, status; 3343d74da94cSMark Johnston 3344d74da94cSMark Johnston ATF_REQUIRE(pthread_barrierattr_init(&battr) == 0); 3345d74da94cSMark Johnston ATF_REQUIRE(pthread_barrierattr_setpshared(&battr, 3346d74da94cSMark Johnston PTHREAD_PROCESS_SHARED) == 0); 3347d74da94cSMark Johnston ATF_REQUIRE(pthread_barrier_init(&barrier, &battr, 2) == 0); 3348d74da94cSMark Johnston 3349d74da94cSMark Johnston (void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX"); 3350d74da94cSMark Johnston fd = mkstemp(tmpfile); 3351d74da94cSMark Johnston ATF_REQUIRE(fd >= 0); 3352d74da94cSMark Johnston 3353d74da94cSMark Johnston ATF_REQUIRE((child = fork()) != -1); 3354d74da94cSMark Johnston if (child == 0) { 3355d74da94cSMark Johnston pthread_t t[2]; 335696437391SBryan Drewery int cfd; 3357d74da94cSMark Johnston 3358d74da94cSMark Johnston error = pthread_barrier_wait(&barrier); 3359d74da94cSMark Johnston if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD) 3360d74da94cSMark Johnston _exit(1); 3361d74da94cSMark Johnston 3362d74da94cSMark Johnston cfd = open(tmpfile, O_RDONLY); 3363d74da94cSMark Johnston if (cfd < 0) 3364d74da94cSMark Johnston _exit(1); 3365d74da94cSMark Johnston 3366d74da94cSMark Johnston /* 3367d74da94cSMark Johnston * We want at least two threads blocked on the file lock since 3368d74da94cSMark Johnston * the SIGSTOP from PT_ATTACH may kick one of them out of 3369d74da94cSMark Johnston * sleep. 3370d74da94cSMark Johnston */ 3371d74da94cSMark Johnston if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0) 3372d74da94cSMark Johnston _exit(1); 3373d74da94cSMark Johnston if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0) 3374d74da94cSMark Johnston _exit(1); 3375d74da94cSMark Johnston if (pthread_join(t[0], NULL) != 0) 3376d74da94cSMark Johnston _exit(1); 3377d74da94cSMark Johnston if (pthread_join(t[1], NULL) != 0) 3378d74da94cSMark Johnston _exit(1); 3379d74da94cSMark Johnston _exit(0); 3380d74da94cSMark Johnston } 3381d74da94cSMark Johnston 3382d74da94cSMark Johnston ATF_REQUIRE(flock(fd, LOCK_EX) == 0); 3383d74da94cSMark Johnston 3384d74da94cSMark Johnston error = pthread_barrier_wait(&barrier); 3385d74da94cSMark Johnston ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD); 3386d74da94cSMark Johnston 3387d74da94cSMark Johnston /* 3388d74da94cSMark Johnston * Give the child some time to block. Is there a better way to do this? 3389d74da94cSMark Johnston */ 3390d74da94cSMark Johnston sleep(1); 3391d74da94cSMark Johnston 3392d74da94cSMark Johnston /* 3393d74da94cSMark Johnston * Attach and give the child 3 seconds to stop. 3394d74da94cSMark Johnston */ 3395d74da94cSMark Johnston ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0); 3396d74da94cSMark Johnston for (i = 0; i < 3; i++) { 3397d74da94cSMark Johnston wpid = waitpid(child, &status, WNOHANG); 3398d74da94cSMark Johnston if (wpid == child && WIFSTOPPED(status) && 3399d74da94cSMark Johnston WSTOPSIG(status) == SIGSTOP) 3400d74da94cSMark Johnston break; 3401d74da94cSMark Johnston sleep(1); 3402d74da94cSMark Johnston } 3403d74da94cSMark Johnston ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH"); 3404d74da94cSMark Johnston 3405d74da94cSMark Johnston ATF_REQUIRE(ptrace(PT_DETACH, child, NULL, 0) == 0); 3406d74da94cSMark Johnston 3407d74da94cSMark Johnston ATF_REQUIRE(flock(fd, LOCK_UN) == 0); 3408d74da94cSMark Johnston ATF_REQUIRE(unlink(tmpfile) == 0); 3409d74da94cSMark Johnston ATF_REQUIRE(close(fd) == 0); 3410d74da94cSMark Johnston } 3411d74da94cSMark Johnston 341254cfb29eSJohn Baldwin static void 341354cfb29eSJohn Baldwin sigusr1_step_handler(int sig) 341454cfb29eSJohn Baldwin { 341554cfb29eSJohn Baldwin 341654cfb29eSJohn Baldwin CHILD_REQUIRE(sig == SIGUSR1); 341754cfb29eSJohn Baldwin raise(SIGABRT); 341854cfb29eSJohn Baldwin } 341954cfb29eSJohn Baldwin 342054cfb29eSJohn Baldwin /* 342154cfb29eSJohn Baldwin * Verify that PT_STEP with a signal invokes the signal before 342254cfb29eSJohn Baldwin * stepping the next instruction (and that the next instruction is 342354cfb29eSJohn Baldwin * stepped correctly). 342454cfb29eSJohn Baldwin */ 342554cfb29eSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal); 342654cfb29eSJohn Baldwin ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc) 342754cfb29eSJohn Baldwin { 342854cfb29eSJohn Baldwin struct ptrace_lwpinfo pl; 342954cfb29eSJohn Baldwin pid_t fpid, wpid; 343054cfb29eSJohn Baldwin int status; 343154cfb29eSJohn Baldwin 343254cfb29eSJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 343354cfb29eSJohn Baldwin if (fpid == 0) { 343454cfb29eSJohn Baldwin trace_me(); 343554cfb29eSJohn Baldwin signal(SIGUSR1, sigusr1_step_handler); 343654cfb29eSJohn Baldwin raise(SIGABRT); 343754cfb29eSJohn Baldwin exit(1); 343854cfb29eSJohn Baldwin } 343954cfb29eSJohn Baldwin 344054cfb29eSJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 344154cfb29eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 344254cfb29eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 344354cfb29eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 344454cfb29eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 344554cfb29eSJohn Baldwin 344654cfb29eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 344754cfb29eSJohn Baldwin 344854cfb29eSJohn Baldwin /* The next stop should report the SIGABRT in the child body. */ 344954cfb29eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 345054cfb29eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 345154cfb29eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 345254cfb29eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGABRT); 345354cfb29eSJohn Baldwin 345454cfb29eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 345554cfb29eSJohn Baldwin ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); 345654cfb29eSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT); 345754cfb29eSJohn Baldwin 345854cfb29eSJohn Baldwin /* Step the child process inserting SIGUSR1. */ 345954cfb29eSJohn Baldwin ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1) == 0); 346054cfb29eSJohn Baldwin 346154cfb29eSJohn Baldwin /* The next stop should report the SIGABRT in the signal handler. */ 346254cfb29eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 346354cfb29eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 346454cfb29eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 346554cfb29eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGABRT); 346654cfb29eSJohn Baldwin 346754cfb29eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 346854cfb29eSJohn Baldwin ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); 346954cfb29eSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT); 347054cfb29eSJohn Baldwin 347154cfb29eSJohn Baldwin /* Continue the child process discarding the signal. */ 347254cfb29eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 347354cfb29eSJohn Baldwin 347454cfb29eSJohn Baldwin /* The next stop should report a trace trap from PT_STEP. */ 347554cfb29eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 347654cfb29eSJohn Baldwin ATF_REQUIRE(wpid == fpid); 347754cfb29eSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 347854cfb29eSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 347954cfb29eSJohn Baldwin 348054cfb29eSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 348154cfb29eSJohn Baldwin ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); 348254cfb29eSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP); 348354cfb29eSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE); 348454cfb29eSJohn Baldwin 348554cfb29eSJohn Baldwin /* Continue the child to let it exit. */ 348654cfb29eSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 348754cfb29eSJohn Baldwin 348854cfb29eSJohn Baldwin /* The last event should be for the child process's exit. */ 348954cfb29eSJohn Baldwin wpid = waitpid(fpid, &status, 0); 349054cfb29eSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 349154cfb29eSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 349254cfb29eSJohn Baldwin 349354cfb29eSJohn Baldwin wpid = wait(&status); 349454cfb29eSJohn Baldwin ATF_REQUIRE(wpid == -1); 349554cfb29eSJohn Baldwin ATF_REQUIRE(errno == ECHILD); 349654cfb29eSJohn Baldwin } 349754cfb29eSJohn Baldwin 3498643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT 3499643ce7deSJohn Baldwin /* 3500643ce7deSJohn Baldwin * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported 3501643ce7deSJohn Baldwin * for a breakpoint trap. 3502643ce7deSJohn Baldwin */ 3503643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo); 3504643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__breakpoint_siginfo, tc) 3505643ce7deSJohn Baldwin { 3506643ce7deSJohn Baldwin struct ptrace_lwpinfo pl; 3507643ce7deSJohn Baldwin pid_t fpid, wpid; 3508643ce7deSJohn Baldwin int status; 3509643ce7deSJohn Baldwin 3510643ce7deSJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 3511643ce7deSJohn Baldwin if (fpid == 0) { 3512643ce7deSJohn Baldwin trace_me(); 3513643ce7deSJohn Baldwin breakpoint(); 3514643ce7deSJohn Baldwin exit(1); 3515643ce7deSJohn Baldwin } 3516643ce7deSJohn Baldwin 3517643ce7deSJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 3518643ce7deSJohn Baldwin wpid = waitpid(fpid, &status, 0); 3519643ce7deSJohn Baldwin ATF_REQUIRE(wpid == fpid); 3520643ce7deSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3521643ce7deSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 3522643ce7deSJohn Baldwin 3523643ce7deSJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 3524643ce7deSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3525643ce7deSJohn Baldwin 3526643ce7deSJohn Baldwin /* The second wait() should report hitting the breakpoint. */ 3527643ce7deSJohn Baldwin wpid = waitpid(fpid, &status, 0); 3528643ce7deSJohn Baldwin ATF_REQUIRE(wpid == fpid); 3529643ce7deSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3530643ce7deSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 3531643ce7deSJohn Baldwin 3532643ce7deSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 3533643ce7deSJohn Baldwin ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0); 3534643ce7deSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP); 3535643ce7deSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_BRKPT); 3536643ce7deSJohn Baldwin 3537643ce7deSJohn Baldwin /* Kill the child process. */ 3538643ce7deSJohn Baldwin ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0); 3539643ce7deSJohn Baldwin 3540643ce7deSJohn Baldwin /* The last wait() should report the SIGKILL. */ 3541643ce7deSJohn Baldwin wpid = waitpid(fpid, &status, 0); 3542643ce7deSJohn Baldwin ATF_REQUIRE(wpid == fpid); 3543643ce7deSJohn Baldwin ATF_REQUIRE(WIFSIGNALED(status)); 3544643ce7deSJohn Baldwin ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 3545643ce7deSJohn Baldwin 3546643ce7deSJohn Baldwin wpid = wait(&status); 3547643ce7deSJohn Baldwin ATF_REQUIRE(wpid == -1); 3548643ce7deSJohn Baldwin ATF_REQUIRE(errno == ECHILD); 3549643ce7deSJohn Baldwin } 3550643ce7deSJohn Baldwin #endif /* HAVE_BREAKPOINT */ 3551643ce7deSJohn Baldwin 3552643ce7deSJohn Baldwin /* 3553643ce7deSJohn Baldwin * Verify that a SIGTRAP event with the TRAP_TRACE code is reported 3554643ce7deSJohn Baldwin * for a single-step trap from PT_STEP. 3555643ce7deSJohn Baldwin */ 3556643ce7deSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo); 3557643ce7deSJohn Baldwin ATF_TC_BODY(ptrace__step_siginfo, tc) 3558643ce7deSJohn Baldwin { 3559643ce7deSJohn Baldwin struct ptrace_lwpinfo pl; 3560643ce7deSJohn Baldwin pid_t fpid, wpid; 3561643ce7deSJohn Baldwin int status; 3562643ce7deSJohn Baldwin 3563643ce7deSJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 3564643ce7deSJohn Baldwin if (fpid == 0) { 3565643ce7deSJohn Baldwin trace_me(); 3566643ce7deSJohn Baldwin exit(1); 3567643ce7deSJohn Baldwin } 3568643ce7deSJohn Baldwin 3569643ce7deSJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 3570643ce7deSJohn Baldwin wpid = waitpid(fpid, &status, 0); 3571643ce7deSJohn Baldwin ATF_REQUIRE(wpid == fpid); 3572643ce7deSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3573643ce7deSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 3574643ce7deSJohn Baldwin 3575643ce7deSJohn Baldwin /* Step the child ignoring the SIGSTOP. */ 3576643ce7deSJohn Baldwin ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, 0) == 0); 3577643ce7deSJohn Baldwin 3578643ce7deSJohn Baldwin /* The second wait() should report a single-step trap. */ 3579643ce7deSJohn Baldwin wpid = waitpid(fpid, &status, 0); 3580643ce7deSJohn Baldwin ATF_REQUIRE(wpid == fpid); 3581643ce7deSJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3582643ce7deSJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 3583643ce7deSJohn Baldwin 3584643ce7deSJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 3585643ce7deSJohn Baldwin ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0); 3586643ce7deSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP); 3587643ce7deSJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE); 3588643ce7deSJohn Baldwin 3589643ce7deSJohn Baldwin /* Continue the child process. */ 3590643ce7deSJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3591643ce7deSJohn Baldwin 3592643ce7deSJohn Baldwin /* The last event should be for the child process's exit. */ 3593643ce7deSJohn Baldwin wpid = waitpid(fpid, &status, 0); 3594643ce7deSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 3595643ce7deSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 3596643ce7deSJohn Baldwin 3597643ce7deSJohn Baldwin wpid = wait(&status); 3598643ce7deSJohn Baldwin ATF_REQUIRE(wpid == -1); 3599643ce7deSJohn Baldwin ATF_REQUIRE(errno == ECHILD); 3600643ce7deSJohn Baldwin } 3601643ce7deSJohn Baldwin 3602403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK) 3603e012fe34SJohn Baldwin static void * 3604e0a40f30SJohn Baldwin continue_thread(void *arg __unused) 3605e012fe34SJohn Baldwin { 3606e012fe34SJohn Baldwin breakpoint(); 3607e012fe34SJohn Baldwin return (NULL); 3608e012fe34SJohn Baldwin } 3609e012fe34SJohn Baldwin 3610e012fe34SJohn Baldwin static __dead2 void 3611e012fe34SJohn Baldwin continue_thread_main(void) 3612e012fe34SJohn Baldwin { 3613e012fe34SJohn Baldwin pthread_t threads[2]; 3614e012fe34SJohn Baldwin 3615e012fe34SJohn Baldwin CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread, 3616e012fe34SJohn Baldwin NULL) == 0); 3617e012fe34SJohn Baldwin CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread, 3618e012fe34SJohn Baldwin NULL) == 0); 3619e012fe34SJohn Baldwin CHILD_REQUIRE(pthread_join(threads[0], NULL) == 0); 3620e012fe34SJohn Baldwin CHILD_REQUIRE(pthread_join(threads[1], NULL) == 0); 3621e012fe34SJohn Baldwin exit(1); 3622e012fe34SJohn Baldwin } 3623e012fe34SJohn Baldwin 3624e012fe34SJohn Baldwin /* 3625e012fe34SJohn Baldwin * Ensure that PT_CONTINUE clears the status of the thread that 3626e012fe34SJohn Baldwin * triggered the stop even if a different thread's LWP was passed to 3627e012fe34SJohn Baldwin * PT_CONTINUE. 3628e012fe34SJohn Baldwin */ 3629e012fe34SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread); 3630e012fe34SJohn Baldwin ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc) 3631e012fe34SJohn Baldwin { 3632e012fe34SJohn Baldwin struct ptrace_lwpinfo pl; 3633e012fe34SJohn Baldwin pid_t fpid, wpid; 3634e012fe34SJohn Baldwin lwpid_t lwps[2]; 3635e012fe34SJohn Baldwin bool hit_break[2]; 3636403e331dSJohn Baldwin struct reg reg; 3637e012fe34SJohn Baldwin int i, j, status; 3638e012fe34SJohn Baldwin 3639e012fe34SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 3640e012fe34SJohn Baldwin if (fpid == 0) { 3641e012fe34SJohn Baldwin trace_me(); 3642e012fe34SJohn Baldwin continue_thread_main(); 3643e012fe34SJohn Baldwin } 3644e012fe34SJohn Baldwin 3645e012fe34SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 3646e012fe34SJohn Baldwin wpid = waitpid(fpid, &status, 0); 3647e012fe34SJohn Baldwin ATF_REQUIRE(wpid == fpid); 3648e012fe34SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3649e012fe34SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 3650e012fe34SJohn Baldwin 3651e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 3652e012fe34SJohn Baldwin sizeof(pl)) != -1); 3653e012fe34SJohn Baldwin 3654e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0); 3655e012fe34SJohn Baldwin 3656e012fe34SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 3657e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3658e012fe34SJohn Baldwin 3659e012fe34SJohn Baldwin /* One of the new threads should report it's birth. */ 3660e012fe34SJohn Baldwin wpid = waitpid(fpid, &status, 0); 3661e012fe34SJohn Baldwin ATF_REQUIRE(wpid == fpid); 3662e012fe34SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3663e012fe34SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 3664e012fe34SJohn Baldwin 3665e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 3666e012fe34SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) == 3667e012fe34SJohn Baldwin (PL_FLAG_BORN | PL_FLAG_SCX)); 3668e012fe34SJohn Baldwin lwps[0] = pl.pl_lwpid; 3669e012fe34SJohn Baldwin 3670e012fe34SJohn Baldwin /* 3671e012fe34SJohn Baldwin * Suspend this thread to ensure both threads are alive before 3672e012fe34SJohn Baldwin * hitting the breakpoint. 3673e012fe34SJohn Baldwin */ 3674e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1); 3675e012fe34SJohn Baldwin 3676e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3677e012fe34SJohn Baldwin 3678e012fe34SJohn Baldwin /* Second thread should report it's birth. */ 3679e012fe34SJohn Baldwin wpid = waitpid(fpid, &status, 0); 3680e012fe34SJohn Baldwin ATF_REQUIRE(wpid == fpid); 3681e012fe34SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3682e012fe34SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 3683e012fe34SJohn Baldwin 3684e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 3685e012fe34SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) == 3686e012fe34SJohn Baldwin (PL_FLAG_BORN | PL_FLAG_SCX)); 3687e012fe34SJohn Baldwin ATF_REQUIRE(pl.pl_lwpid != lwps[0]); 3688e012fe34SJohn Baldwin lwps[1] = pl.pl_lwpid; 3689e012fe34SJohn Baldwin 3690e012fe34SJohn Baldwin /* Resume both threads waiting for breakpoint events. */ 3691e012fe34SJohn Baldwin hit_break[0] = hit_break[1] = false; 3692e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1); 3693e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3694e012fe34SJohn Baldwin 3695e012fe34SJohn Baldwin /* One thread should report a breakpoint. */ 3696e012fe34SJohn Baldwin wpid = waitpid(fpid, &status, 0); 3697e012fe34SJohn Baldwin ATF_REQUIRE(wpid == fpid); 3698e012fe34SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3699e012fe34SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 3700e012fe34SJohn Baldwin 3701e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); 3702e012fe34SJohn Baldwin ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0); 3703e012fe34SJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP && 3704e012fe34SJohn Baldwin pl.pl_siginfo.si_code == TRAP_BRKPT); 3705e012fe34SJohn Baldwin if (pl.pl_lwpid == lwps[0]) 3706e012fe34SJohn Baldwin i = 0; 3707e012fe34SJohn Baldwin else 3708e012fe34SJohn Baldwin i = 1; 3709e012fe34SJohn Baldwin hit_break[i] = true; 3710403e331dSJohn Baldwin ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)®, 0) != -1); 3711403e331dSJohn Baldwin SKIP_BREAK(®); 3712403e331dSJohn Baldwin ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)®, 0) != -1); 3713e012fe34SJohn Baldwin 3714e012fe34SJohn Baldwin /* 3715e012fe34SJohn Baldwin * Resume both threads but pass the other thread's LWPID to 3716e012fe34SJohn Baldwin * PT_CONTINUE. 3717e012fe34SJohn Baldwin */ 3718e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0) == 0); 3719e012fe34SJohn Baldwin 3720e012fe34SJohn Baldwin /* 3721e012fe34SJohn Baldwin * Will now get two thread exit events and one more breakpoint 3722e012fe34SJohn Baldwin * event. 3723e012fe34SJohn Baldwin */ 3724e012fe34SJohn Baldwin for (j = 0; j < 3; j++) { 3725e012fe34SJohn Baldwin wpid = waitpid(fpid, &status, 0); 3726e012fe34SJohn Baldwin ATF_REQUIRE(wpid == fpid); 3727e012fe34SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 3728e012fe34SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 3729e012fe34SJohn Baldwin 3730e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 3731e012fe34SJohn Baldwin sizeof(pl)) != -1); 3732e012fe34SJohn Baldwin 3733e012fe34SJohn Baldwin if (pl.pl_lwpid == lwps[0]) 3734e012fe34SJohn Baldwin i = 0; 3735e012fe34SJohn Baldwin else 3736e012fe34SJohn Baldwin i = 1; 3737e012fe34SJohn Baldwin 3738e012fe34SJohn Baldwin ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread"); 3739e012fe34SJohn Baldwin if (pl.pl_flags & PL_FLAG_EXITED) { 3740e012fe34SJohn Baldwin ATF_REQUIRE_MSG(hit_break[i], 3741e012fe34SJohn Baldwin "exited thread did not report breakpoint"); 3742e012fe34SJohn Baldwin lwps[i] = 0; 3743e012fe34SJohn Baldwin } else { 3744e012fe34SJohn Baldwin ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0); 3745e012fe34SJohn Baldwin ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP && 3746e012fe34SJohn Baldwin pl.pl_siginfo.si_code == TRAP_BRKPT); 3747e012fe34SJohn Baldwin ATF_REQUIRE_MSG(!hit_break[i], 3748e012fe34SJohn Baldwin "double breakpoint event"); 3749e012fe34SJohn Baldwin hit_break[i] = true; 3750403e331dSJohn Baldwin ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)®, 3751403e331dSJohn Baldwin 0) != -1); 3752403e331dSJohn Baldwin SKIP_BREAK(®); 3753403e331dSJohn Baldwin ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)®, 3754403e331dSJohn Baldwin 0) != -1); 3755e012fe34SJohn Baldwin } 3756e012fe34SJohn Baldwin 3757e012fe34SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 3758e012fe34SJohn Baldwin } 3759e012fe34SJohn Baldwin 3760e012fe34SJohn Baldwin /* Both threads should have exited. */ 3761e012fe34SJohn Baldwin ATF_REQUIRE(lwps[0] == 0); 3762e012fe34SJohn Baldwin ATF_REQUIRE(lwps[1] == 0); 3763e012fe34SJohn Baldwin 3764e012fe34SJohn Baldwin /* The last event should be for the child process's exit. */ 3765e012fe34SJohn Baldwin wpid = waitpid(fpid, &status, 0); 3766e012fe34SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 3767e012fe34SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 3768e012fe34SJohn Baldwin 3769e012fe34SJohn Baldwin wpid = wait(&status); 3770e012fe34SJohn Baldwin ATF_REQUIRE(wpid == -1); 3771e012fe34SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 3772e012fe34SJohn Baldwin } 3773e012fe34SJohn Baldwin #endif 3774e012fe34SJohn Baldwin 3775c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp) 3776c209e3e2SJohn Baldwin { 3777c209e3e2SJohn Baldwin 3778c209e3e2SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me); 3779c209e3e2SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach); 378057c74f5bSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger); 378157c74f5bSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger); 378298685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached); 378398685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached); 378498685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached); 378598685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger); 378698685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, 378798685dc8SJohn Baldwin ptrace__follow_fork_child_detached_unrelated_debugger); 378898685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, 378998685dc8SJohn Baldwin ptrace__follow_fork_parent_detached_unrelated_debugger); 3790368b2b1cSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__getppid); 3791189ac973SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork); 3792189ac973SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork); 3793189ac973SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread); 37945fcfab6eSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__lwp_events); 37955fcfab6eSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec); 37963340c45bSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__siginfo); 37978d570f64SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable); 37988d570f64SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable); 37998d570f64SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__event_mask); 3800fc4f075aSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork); 3801fc4f075aSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow); 3802403e331dSJohn Baldwin #ifdef HAVE_BREAKPOINT 380382a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint); 3804e2ebfbbfSEric Badger #endif 380582a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call); 380682a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads); 380782a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal); 380882a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop); 380982a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue); 381082a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry); 381182a4538fSEric Badger ATF_TP_ADD_TC(tp, 381282a4538fSEric Badger ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit); 381382a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue); 3814753e2922SBryan Drewery ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue); 381582a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig); 381682a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry); 381782a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix); 381882a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue); 3819753e2922SBryan Drewery ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask); 3820753e2922SBryan Drewery ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask); 382182a4538fSEric Badger ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask); 3822b38bd91fSEric Badger ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1); 3823b38bd91fSEric Badger ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2); 3824b4d33259SEric Badger ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard); 3825d74da94cSMark Johnston ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread); 382654cfb29eSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal); 3827643ce7deSJohn Baldwin #ifdef HAVE_BREAKPOINT 3828643ce7deSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo); 3829643ce7deSJohn Baldwin #endif 3830643ce7deSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__step_siginfo); 3831403e331dSJohn Baldwin #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK) 3832e012fe34SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread); 3833e012fe34SJohn Baldwin #endif 3834c209e3e2SJohn Baldwin 3835c209e3e2SJohn Baldwin return (atf_no_error()); 3836c209e3e2SJohn Baldwin } 3837