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> 31c209e3e2SJohn Baldwin #include <sys/ptrace.h> 3257c74f5bSJohn Baldwin #include <sys/sysctl.h> 3357c74f5bSJohn Baldwin #include <sys/user.h> 34c209e3e2SJohn Baldwin #include <sys/wait.h> 35c209e3e2SJohn Baldwin #include <errno.h> 36c209e3e2SJohn Baldwin #include <signal.h> 37dfa8ba12SJohn Baldwin #include <stdio.h> 38c209e3e2SJohn Baldwin #include <stdlib.h> 39c209e3e2SJohn Baldwin #include <unistd.h> 40c209e3e2SJohn Baldwin #include <atf-c.h> 41c209e3e2SJohn Baldwin 42c209e3e2SJohn Baldwin /* 43dfa8ba12SJohn Baldwin * A variant of ATF_REQUIRE that is suitable for use in child 44dfa8ba12SJohn Baldwin * processes. This only works if the parent process is tripped up by 45dfa8ba12SJohn Baldwin * the early exit and fails some requirement itself. 46dfa8ba12SJohn Baldwin */ 47dfa8ba12SJohn Baldwin #define CHILD_REQUIRE(exp) do { \ 48dfa8ba12SJohn Baldwin if (!(exp)) \ 49dfa8ba12SJohn Baldwin child_fail_require(__FILE__, __LINE__, \ 50dfa8ba12SJohn Baldwin #exp " not met"); \ 51dfa8ba12SJohn Baldwin } while (0) 52dfa8ba12SJohn Baldwin 53*98685dc8SJohn Baldwin static __dead2 void 54dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str) 55dfa8ba12SJohn Baldwin { 56dfa8ba12SJohn Baldwin char buf[128]; 57dfa8ba12SJohn Baldwin 58dfa8ba12SJohn Baldwin snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str); 59dfa8ba12SJohn Baldwin write(2, buf, strlen(buf)); 60dfa8ba12SJohn Baldwin _exit(32); 61dfa8ba12SJohn Baldwin } 62dfa8ba12SJohn Baldwin 63*98685dc8SJohn Baldwin static void 64*98685dc8SJohn Baldwin trace_me(void) 65*98685dc8SJohn Baldwin { 66*98685dc8SJohn Baldwin 67*98685dc8SJohn Baldwin /* Attach the parent process as a tracer of this process. */ 68*98685dc8SJohn Baldwin CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 69*98685dc8SJohn Baldwin 70*98685dc8SJohn Baldwin /* Trigger a stop. */ 71*98685dc8SJohn Baldwin raise(SIGSTOP); 72*98685dc8SJohn Baldwin } 73*98685dc8SJohn Baldwin 74*98685dc8SJohn Baldwin static void 75*98685dc8SJohn Baldwin attach_child(pid_t pid) 76*98685dc8SJohn Baldwin { 77*98685dc8SJohn Baldwin pid_t wpid; 78*98685dc8SJohn Baldwin int status; 79*98685dc8SJohn Baldwin 80*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0); 81*98685dc8SJohn Baldwin 82*98685dc8SJohn Baldwin wpid = waitpid(pid, &status, 0); 83*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == pid); 84*98685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 85*98685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 86*98685dc8SJohn Baldwin } 87*98685dc8SJohn Baldwin 88*98685dc8SJohn Baldwin static void 89*98685dc8SJohn Baldwin wait_for_zombie(pid_t pid) 90*98685dc8SJohn Baldwin { 91*98685dc8SJohn Baldwin 92*98685dc8SJohn Baldwin /* 93*98685dc8SJohn Baldwin * Wait for a process to exit. This is kind of gross, but 94*98685dc8SJohn Baldwin * there is not a better way. 95*98685dc8SJohn Baldwin */ 96*98685dc8SJohn Baldwin for (;;) { 97*98685dc8SJohn Baldwin struct kinfo_proc kp; 98*98685dc8SJohn Baldwin size_t len; 99*98685dc8SJohn Baldwin int mib[4]; 100*98685dc8SJohn Baldwin 101*98685dc8SJohn Baldwin mib[0] = CTL_KERN; 102*98685dc8SJohn Baldwin mib[1] = KERN_PROC; 103*98685dc8SJohn Baldwin mib[2] = KERN_PROC_PID; 104*98685dc8SJohn Baldwin mib[3] = pid; 105*98685dc8SJohn Baldwin len = sizeof(kp); 106*98685dc8SJohn Baldwin if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) { 107*98685dc8SJohn Baldwin /* The KERN_PROC_PID sysctl fails for zombies. */ 108*98685dc8SJohn Baldwin ATF_REQUIRE(errno == ESRCH); 109*98685dc8SJohn Baldwin break; 110*98685dc8SJohn Baldwin } 111*98685dc8SJohn Baldwin usleep(5000); 112*98685dc8SJohn Baldwin } 113*98685dc8SJohn Baldwin } 114*98685dc8SJohn Baldwin 115dfa8ba12SJohn Baldwin /* 116c209e3e2SJohn Baldwin * Verify that a parent debugger process "sees" the exit of a debugged 117c209e3e2SJohn Baldwin * process exactly once when attached via PT_TRACE_ME. 118c209e3e2SJohn Baldwin */ 119c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me); 120c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc) 121c209e3e2SJohn Baldwin { 122c209e3e2SJohn Baldwin pid_t child, wpid; 123c209e3e2SJohn Baldwin int status; 124c209e3e2SJohn Baldwin 125c209e3e2SJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 126c209e3e2SJohn Baldwin if (child == 0) { 127c209e3e2SJohn Baldwin /* Child process. */ 128*98685dc8SJohn Baldwin trace_me(); 129c209e3e2SJohn Baldwin 130c209e3e2SJohn Baldwin exit(1); 131c209e3e2SJohn Baldwin } 132c209e3e2SJohn Baldwin 133c209e3e2SJohn Baldwin /* Parent process. */ 134c209e3e2SJohn Baldwin 135c209e3e2SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 136c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 137c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 138c209e3e2SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 139c209e3e2SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 140c209e3e2SJohn Baldwin 141c209e3e2SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 142c209e3e2SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 143c209e3e2SJohn Baldwin 144c209e3e2SJohn Baldwin /* The second wait() should report the exit status. */ 145c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 146c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 147c209e3e2SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 148c209e3e2SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 149c209e3e2SJohn Baldwin 150c209e3e2SJohn Baldwin /* The child should no longer exist. */ 151c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 152c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == -1); 153c209e3e2SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 154c209e3e2SJohn Baldwin } 155c209e3e2SJohn Baldwin 156c209e3e2SJohn Baldwin /* 157c209e3e2SJohn Baldwin * Verify that a parent debugger process "sees" the exit of a debugged 158c209e3e2SJohn Baldwin * process exactly once when attached via PT_ATTACH. 159c209e3e2SJohn Baldwin */ 160c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach); 161c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc) 162c209e3e2SJohn Baldwin { 163c209e3e2SJohn Baldwin pid_t child, wpid; 164c209e3e2SJohn Baldwin int cpipe[2], status; 165c209e3e2SJohn Baldwin char c; 166c209e3e2SJohn Baldwin 167c209e3e2SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 168c209e3e2SJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 169c209e3e2SJohn Baldwin if (child == 0) { 170c209e3e2SJohn Baldwin /* Child process. */ 171c209e3e2SJohn Baldwin close(cpipe[0]); 172c209e3e2SJohn Baldwin 173c209e3e2SJohn Baldwin /* Wait for the parent to attach. */ 174dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0); 175c209e3e2SJohn Baldwin 176c209e3e2SJohn Baldwin exit(1); 177c209e3e2SJohn Baldwin } 178c209e3e2SJohn Baldwin close(cpipe[1]); 179c209e3e2SJohn Baldwin 180c209e3e2SJohn Baldwin /* Parent process. */ 181c209e3e2SJohn Baldwin 182c209e3e2SJohn Baldwin /* Attach to the child process. */ 183*98685dc8SJohn Baldwin attach_child(child); 184c209e3e2SJohn Baldwin 185c209e3e2SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 186c209e3e2SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 187c209e3e2SJohn Baldwin 188c209e3e2SJohn Baldwin /* Signal the child to exit. */ 189c209e3e2SJohn Baldwin close(cpipe[0]); 190c209e3e2SJohn Baldwin 191c209e3e2SJohn Baldwin /* The second wait() should report the exit status. */ 192c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 193c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 194c209e3e2SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 195c209e3e2SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 196c209e3e2SJohn Baldwin 197c209e3e2SJohn Baldwin /* The child should no longer exist. */ 198c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 199c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == -1); 200c209e3e2SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 201c209e3e2SJohn Baldwin } 202c209e3e2SJohn Baldwin 20357c74f5bSJohn Baldwin /* 20457c74f5bSJohn Baldwin * Verify that a parent process "sees" the exit of a debugged process only 20557c74f5bSJohn Baldwin * after the debugger has seen it. 20657c74f5bSJohn Baldwin */ 20757c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger); 20857c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc) 20957c74f5bSJohn Baldwin { 21057c74f5bSJohn Baldwin pid_t child, debugger, wpid; 21157c74f5bSJohn Baldwin int cpipe[2], dpipe[2], status; 21257c74f5bSJohn Baldwin char c; 21357c74f5bSJohn Baldwin 21457c74f5bSJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 21557c74f5bSJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 21657c74f5bSJohn Baldwin 21757c74f5bSJohn Baldwin if (child == 0) { 21857c74f5bSJohn Baldwin /* Child process. */ 21957c74f5bSJohn Baldwin close(cpipe[0]); 22057c74f5bSJohn Baldwin 22157c74f5bSJohn Baldwin /* Wait for parent to be ready. */ 222dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 22357c74f5bSJohn Baldwin 22457c74f5bSJohn Baldwin exit(1); 22557c74f5bSJohn Baldwin } 22657c74f5bSJohn Baldwin close(cpipe[1]); 22757c74f5bSJohn Baldwin 22857c74f5bSJohn Baldwin ATF_REQUIRE(pipe(dpipe) == 0); 22957c74f5bSJohn Baldwin ATF_REQUIRE((debugger = fork()) != -1); 23057c74f5bSJohn Baldwin 23157c74f5bSJohn Baldwin if (debugger == 0) { 23257c74f5bSJohn Baldwin /* Debugger process. */ 23357c74f5bSJohn Baldwin close(dpipe[0]); 23457c74f5bSJohn Baldwin 235dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 23657c74f5bSJohn Baldwin 23757c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 238dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 239dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFSTOPPED(status)); 240dfa8ba12SJohn Baldwin CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 24157c74f5bSJohn Baldwin 242dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 24357c74f5bSJohn Baldwin 24457c74f5bSJohn Baldwin /* Signal parent that debugger is attached. */ 245dfa8ba12SJohn Baldwin CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 24657c74f5bSJohn Baldwin 24757c74f5bSJohn Baldwin /* Wait for parent's failed wait. */ 248dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0); 24957c74f5bSJohn Baldwin 25057c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 251dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 252dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 253dfa8ba12SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 1); 25457c74f5bSJohn Baldwin 25557c74f5bSJohn Baldwin exit(0); 25657c74f5bSJohn Baldwin } 25757c74f5bSJohn Baldwin close(dpipe[1]); 25857c74f5bSJohn Baldwin 25957c74f5bSJohn Baldwin /* Parent process. */ 26057c74f5bSJohn Baldwin 26157c74f5bSJohn Baldwin /* Wait for the debugger to attach to the child. */ 26257c74f5bSJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 26357c74f5bSJohn Baldwin 26457c74f5bSJohn Baldwin /* Release the child. */ 26557c74f5bSJohn Baldwin ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 26657c74f5bSJohn Baldwin ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0); 26757c74f5bSJohn Baldwin close(cpipe[0]); 26857c74f5bSJohn Baldwin 269*98685dc8SJohn Baldwin wait_for_zombie(child); 27057c74f5bSJohn Baldwin 27157c74f5bSJohn Baldwin /* 2722f021998SJohn Baldwin * This wait should return a pid of 0 to indicate no status to 2732f021998SJohn Baldwin * report. The parent should see the child as non-exited 2742f021998SJohn Baldwin * until the debugger sees the exit. 27557c74f5bSJohn Baldwin */ 27657c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 27757c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 27857c74f5bSJohn Baldwin 27957c74f5bSJohn Baldwin /* Signal the debugger to wait for the child. */ 28057c74f5bSJohn Baldwin close(dpipe[0]); 28157c74f5bSJohn Baldwin 28257c74f5bSJohn Baldwin /* Wait for the debugger. */ 28357c74f5bSJohn Baldwin wpid = waitpid(debugger, &status, 0); 28457c74f5bSJohn Baldwin ATF_REQUIRE(wpid == debugger); 28557c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 28657c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 28757c74f5bSJohn Baldwin 28857c74f5bSJohn Baldwin /* The child process should now be ready. */ 28957c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 29057c74f5bSJohn Baldwin ATF_REQUIRE(wpid == child); 29157c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 29257c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 29357c74f5bSJohn Baldwin } 29457c74f5bSJohn Baldwin 29557c74f5bSJohn Baldwin /* 29657c74f5bSJohn Baldwin * Verify that a parent process "sees" the exit of a debugged process 29757c74f5bSJohn Baldwin * only after a non-direct-child debugger has seen it. In particular, 29857c74f5bSJohn Baldwin * various wait() calls in the parent must avoid failing with ESRCH by 29957c74f5bSJohn Baldwin * checking the parent's orphan list for the debugee. 30057c74f5bSJohn Baldwin */ 30157c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger); 30257c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc) 30357c74f5bSJohn Baldwin { 30457c74f5bSJohn Baldwin pid_t child, debugger, fpid, wpid; 30557c74f5bSJohn Baldwin int cpipe[2], dpipe[2], status; 30657c74f5bSJohn Baldwin char c; 30757c74f5bSJohn Baldwin 30857c74f5bSJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 30957c74f5bSJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 31057c74f5bSJohn Baldwin 31157c74f5bSJohn Baldwin if (child == 0) { 31257c74f5bSJohn Baldwin /* Child process. */ 31357c74f5bSJohn Baldwin close(cpipe[0]); 31457c74f5bSJohn Baldwin 31557c74f5bSJohn Baldwin /* Wait for parent to be ready. */ 316dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 31757c74f5bSJohn Baldwin 31857c74f5bSJohn Baldwin exit(1); 31957c74f5bSJohn Baldwin } 32057c74f5bSJohn Baldwin close(cpipe[1]); 32157c74f5bSJohn Baldwin 32257c74f5bSJohn Baldwin ATF_REQUIRE(pipe(dpipe) == 0); 32357c74f5bSJohn Baldwin ATF_REQUIRE((debugger = fork()) != -1); 32457c74f5bSJohn Baldwin 32557c74f5bSJohn Baldwin if (debugger == 0) { 32657c74f5bSJohn Baldwin /* Debugger parent. */ 32757c74f5bSJohn Baldwin 32857c74f5bSJohn Baldwin /* 32957c74f5bSJohn Baldwin * Fork again and drop the debugger parent so that the 33057c74f5bSJohn Baldwin * debugger is not a child of the main parent. 33157c74f5bSJohn Baldwin */ 332dfa8ba12SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 33357c74f5bSJohn Baldwin if (fpid != 0) 33457c74f5bSJohn Baldwin exit(2); 33557c74f5bSJohn Baldwin 33657c74f5bSJohn Baldwin /* Debugger process. */ 33757c74f5bSJohn Baldwin close(dpipe[0]); 33857c74f5bSJohn Baldwin 339dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 34057c74f5bSJohn Baldwin 34157c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 342dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 343dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFSTOPPED(status)); 344dfa8ba12SJohn Baldwin CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 34557c74f5bSJohn Baldwin 346dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 34757c74f5bSJohn Baldwin 34857c74f5bSJohn Baldwin /* Signal parent that debugger is attached. */ 349dfa8ba12SJohn Baldwin CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 35057c74f5bSJohn Baldwin 35157c74f5bSJohn Baldwin /* Wait for parent's failed wait. */ 352dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c)); 35357c74f5bSJohn Baldwin 35457c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 355dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 356dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 357dfa8ba12SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 1); 35857c74f5bSJohn Baldwin 35957c74f5bSJohn Baldwin exit(0); 36057c74f5bSJohn Baldwin } 361eddb85c6SJohn Baldwin close(dpipe[1]); 36257c74f5bSJohn Baldwin 36357c74f5bSJohn Baldwin /* Parent process. */ 36457c74f5bSJohn Baldwin 36557c74f5bSJohn Baldwin /* Wait for the debugger parent process to exit. */ 36657c74f5bSJohn Baldwin wpid = waitpid(debugger, &status, 0); 36757c74f5bSJohn Baldwin ATF_REQUIRE(wpid == debugger); 36857c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 36957c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 37057c74f5bSJohn Baldwin 37157c74f5bSJohn Baldwin /* A WNOHANG wait here should see the non-exited child. */ 37257c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 37357c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 37457c74f5bSJohn Baldwin 37557c74f5bSJohn Baldwin /* Wait for the debugger to attach to the child. */ 37657c74f5bSJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 37757c74f5bSJohn Baldwin 37857c74f5bSJohn Baldwin /* Release the child. */ 37957c74f5bSJohn Baldwin ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 38057c74f5bSJohn Baldwin ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0); 38157c74f5bSJohn Baldwin close(cpipe[0]); 38257c74f5bSJohn Baldwin 383*98685dc8SJohn Baldwin wait_for_zombie(child); 38457c74f5bSJohn Baldwin 38557c74f5bSJohn Baldwin /* 3862f021998SJohn Baldwin * This wait should return a pid of 0 to indicate no status to 3872f021998SJohn Baldwin * report. The parent should see the child as non-exited 3882f021998SJohn Baldwin * until the debugger sees the exit. 38957c74f5bSJohn Baldwin */ 39057c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 39157c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 39257c74f5bSJohn Baldwin 39357c74f5bSJohn Baldwin /* Signal the debugger to wait for the child. */ 394eddb85c6SJohn Baldwin ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c)); 39557c74f5bSJohn Baldwin 39657c74f5bSJohn Baldwin /* Wait for the debugger. */ 397eddb85c6SJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0); 398eddb85c6SJohn Baldwin close(dpipe[0]); 39957c74f5bSJohn Baldwin 40057c74f5bSJohn Baldwin /* The child process should now be ready. */ 40157c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 40257c74f5bSJohn Baldwin ATF_REQUIRE(wpid == child); 40357c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 40457c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 40557c74f5bSJohn Baldwin } 40657c74f5bSJohn Baldwin 407*98685dc8SJohn Baldwin /* 408*98685dc8SJohn Baldwin * The parent process should always act the same regardless of how the 409*98685dc8SJohn Baldwin * debugger is attached to it. 410*98685dc8SJohn Baldwin */ 411*98685dc8SJohn Baldwin static __dead2 void 412*98685dc8SJohn Baldwin follow_fork_parent(void) 413*98685dc8SJohn Baldwin { 414*98685dc8SJohn Baldwin pid_t fpid, wpid; 415*98685dc8SJohn Baldwin int status; 416*98685dc8SJohn Baldwin 417*98685dc8SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 418*98685dc8SJohn Baldwin 419*98685dc8SJohn Baldwin if (fpid == 0) 420*98685dc8SJohn Baldwin /* Child */ 421*98685dc8SJohn Baldwin exit(2); 422*98685dc8SJohn Baldwin 423*98685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 424*98685dc8SJohn Baldwin CHILD_REQUIRE(wpid == fpid); 425*98685dc8SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 426*98685dc8SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 2); 427*98685dc8SJohn Baldwin 428*98685dc8SJohn Baldwin exit(1); 429*98685dc8SJohn Baldwin } 430*98685dc8SJohn Baldwin 431*98685dc8SJohn Baldwin /* 432*98685dc8SJohn Baldwin * Helper routine for follow fork tests. This waits for two stops 433*98685dc8SJohn Baldwin * that report both "sides" of a fork. It returns the pid of the new 434*98685dc8SJohn Baldwin * child process. 435*98685dc8SJohn Baldwin */ 436*98685dc8SJohn Baldwin static pid_t 437*98685dc8SJohn Baldwin handle_fork_events(pid_t parent) 438*98685dc8SJohn Baldwin { 439*98685dc8SJohn Baldwin struct ptrace_lwpinfo pl; 440*98685dc8SJohn Baldwin bool fork_reported[2]; 441*98685dc8SJohn Baldwin pid_t child, wpid; 442*98685dc8SJohn Baldwin int i, status; 443*98685dc8SJohn Baldwin 444*98685dc8SJohn Baldwin fork_reported[0] = false; 445*98685dc8SJohn Baldwin fork_reported[1] = false; 446*98685dc8SJohn Baldwin child = -1; 447*98685dc8SJohn Baldwin 448*98685dc8SJohn Baldwin /* 449*98685dc8SJohn Baldwin * Each process should report a fork event. The parent should 450*98685dc8SJohn Baldwin * report a PL_FLAG_FORKED event, and the child should report 451*98685dc8SJohn Baldwin * a PL_FLAG_CHILD event. 452*98685dc8SJohn Baldwin */ 453*98685dc8SJohn Baldwin for (i = 0; i < 2; i++) { 454*98685dc8SJohn Baldwin wpid = wait(&status); 455*98685dc8SJohn Baldwin ATF_REQUIRE(wpid > 0); 456*98685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 457*98685dc8SJohn Baldwin 458*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 459*98685dc8SJohn Baldwin sizeof(pl)) != -1); 460*98685dc8SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) != 461*98685dc8SJohn Baldwin 0); 462*98685dc8SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) != 463*98685dc8SJohn Baldwin (PL_FLAG_FORKED | PL_FLAG_CHILD)); 464*98685dc8SJohn Baldwin if (pl.pl_flags & PL_FLAG_CHILD) { 465*98685dc8SJohn Baldwin ATF_REQUIRE(wpid != parent); 466*98685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 467*98685dc8SJohn Baldwin ATF_REQUIRE(!fork_reported[1]); 468*98685dc8SJohn Baldwin if (child == -1) 469*98685dc8SJohn Baldwin child = wpid; 470*98685dc8SJohn Baldwin else 471*98685dc8SJohn Baldwin ATF_REQUIRE(child == wpid); 472*98685dc8SJohn Baldwin fork_reported[1] = true; 473*98685dc8SJohn Baldwin } else { 474*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == parent); 475*98685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 476*98685dc8SJohn Baldwin ATF_REQUIRE(!fork_reported[0]); 477*98685dc8SJohn Baldwin if (child == -1) 478*98685dc8SJohn Baldwin child = pl.pl_child_pid; 479*98685dc8SJohn Baldwin else 480*98685dc8SJohn Baldwin ATF_REQUIRE(child == pl.pl_child_pid); 481*98685dc8SJohn Baldwin fork_reported[0] = true; 482*98685dc8SJohn Baldwin } 483*98685dc8SJohn Baldwin } 484*98685dc8SJohn Baldwin 485*98685dc8SJohn Baldwin return (child); 486*98685dc8SJohn Baldwin } 487*98685dc8SJohn Baldwin 488*98685dc8SJohn Baldwin /* 489*98685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork and 490*98685dc8SJohn Baldwin * that the traced parent sees the exit of the child after the debugger 491*98685dc8SJohn Baldwin * when both processes remain attached to the debugger. 492*98685dc8SJohn Baldwin */ 493*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached); 494*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc) 495*98685dc8SJohn Baldwin { 496*98685dc8SJohn Baldwin pid_t children[0], fpid, wpid; 497*98685dc8SJohn Baldwin int status; 498*98685dc8SJohn Baldwin 499*98685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 500*98685dc8SJohn Baldwin if (fpid == 0) { 501*98685dc8SJohn Baldwin trace_me(); 502*98685dc8SJohn Baldwin follow_fork_parent(); 503*98685dc8SJohn Baldwin } 504*98685dc8SJohn Baldwin 505*98685dc8SJohn Baldwin /* Parent process. */ 506*98685dc8SJohn Baldwin children[0] = fpid; 507*98685dc8SJohn Baldwin 508*98685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 509*98685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 510*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 511*98685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 512*98685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 513*98685dc8SJohn Baldwin 514*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 515*98685dc8SJohn Baldwin 516*98685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 517*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 518*98685dc8SJohn Baldwin 519*98685dc8SJohn Baldwin children[1] = handle_fork_events(children[0]); 520*98685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 521*98685dc8SJohn Baldwin 522*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 523*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 524*98685dc8SJohn Baldwin 525*98685dc8SJohn Baldwin /* 526*98685dc8SJohn Baldwin * The child can't exit until the grandchild reports status, so the 527*98685dc8SJohn Baldwin * grandchild should report its exit first to the debugger. 528*98685dc8SJohn Baldwin */ 529*98685dc8SJohn Baldwin wpid = wait(&status); 530*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 531*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 532*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 533*98685dc8SJohn Baldwin 534*98685dc8SJohn Baldwin wpid = wait(&status); 535*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 536*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 537*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 538*98685dc8SJohn Baldwin 539*98685dc8SJohn Baldwin wpid = wait(&status); 540*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 541*98685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 542*98685dc8SJohn Baldwin } 543*98685dc8SJohn Baldwin 544*98685dc8SJohn Baldwin /* 545*98685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 546*98685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the new 547*98685dc8SJohn Baldwin * child process is detached after it reports its fork. 548*98685dc8SJohn Baldwin */ 549*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached); 550*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc) 551*98685dc8SJohn Baldwin { 552*98685dc8SJohn Baldwin pid_t children[0], fpid, wpid; 553*98685dc8SJohn Baldwin int status; 554*98685dc8SJohn Baldwin 555*98685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 556*98685dc8SJohn Baldwin if (fpid == 0) { 557*98685dc8SJohn Baldwin trace_me(); 558*98685dc8SJohn Baldwin follow_fork_parent(); 559*98685dc8SJohn Baldwin } 560*98685dc8SJohn Baldwin 561*98685dc8SJohn Baldwin /* Parent process. */ 562*98685dc8SJohn Baldwin children[0] = fpid; 563*98685dc8SJohn Baldwin 564*98685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 565*98685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 566*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 567*98685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 568*98685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 569*98685dc8SJohn Baldwin 570*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 571*98685dc8SJohn Baldwin 572*98685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 573*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 574*98685dc8SJohn Baldwin 575*98685dc8SJohn Baldwin children[1] = handle_fork_events(children[0]); 576*98685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 577*98685dc8SJohn Baldwin 578*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 579*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1); 580*98685dc8SJohn Baldwin 581*98685dc8SJohn Baldwin /* 582*98685dc8SJohn Baldwin * Should not see any status from the grandchild now, only the 583*98685dc8SJohn Baldwin * child. 584*98685dc8SJohn Baldwin */ 585*98685dc8SJohn Baldwin wpid = wait(&status); 586*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 587*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 588*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 589*98685dc8SJohn Baldwin 590*98685dc8SJohn Baldwin wpid = wait(&status); 591*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 592*98685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 593*98685dc8SJohn Baldwin } 594*98685dc8SJohn Baldwin 595*98685dc8SJohn Baldwin /* 596*98685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 597*98685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the 598*98685dc8SJohn Baldwin * traced parent is detached after the fork. 599*98685dc8SJohn Baldwin */ 600*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached); 601*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc) 602*98685dc8SJohn Baldwin { 603*98685dc8SJohn Baldwin pid_t children[0], fpid, wpid; 604*98685dc8SJohn Baldwin int status; 605*98685dc8SJohn Baldwin 606*98685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 607*98685dc8SJohn Baldwin if (fpid == 0) { 608*98685dc8SJohn Baldwin trace_me(); 609*98685dc8SJohn Baldwin follow_fork_parent(); 610*98685dc8SJohn Baldwin } 611*98685dc8SJohn Baldwin 612*98685dc8SJohn Baldwin /* Parent process. */ 613*98685dc8SJohn Baldwin children[0] = fpid; 614*98685dc8SJohn Baldwin 615*98685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 616*98685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 617*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 618*98685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 619*98685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 620*98685dc8SJohn Baldwin 621*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 622*98685dc8SJohn Baldwin 623*98685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 624*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 625*98685dc8SJohn Baldwin 626*98685dc8SJohn Baldwin children[1] = handle_fork_events(children[0]); 627*98685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 628*98685dc8SJohn Baldwin 629*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1); 630*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 631*98685dc8SJohn Baldwin 632*98685dc8SJohn Baldwin /* 633*98685dc8SJohn Baldwin * The child can't exit until the grandchild reports status, so the 634*98685dc8SJohn Baldwin * grandchild should report its exit first to the debugger. 635*98685dc8SJohn Baldwin * 636*98685dc8SJohn Baldwin * Even though the child process is detached, it is still a 637*98685dc8SJohn Baldwin * child of the debugger, so it will still report it's exit 638*98685dc8SJohn Baldwin * after the grandchild. 639*98685dc8SJohn Baldwin */ 640*98685dc8SJohn Baldwin wpid = wait(&status); 641*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 642*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 643*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 644*98685dc8SJohn Baldwin 645*98685dc8SJohn Baldwin wpid = wait(&status); 646*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 647*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 648*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 649*98685dc8SJohn Baldwin 650*98685dc8SJohn Baldwin wpid = wait(&status); 651*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 652*98685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 653*98685dc8SJohn Baldwin } 654*98685dc8SJohn Baldwin 655*98685dc8SJohn Baldwin static void 656*98685dc8SJohn Baldwin attach_fork_parent(int cpipe[2]) 657*98685dc8SJohn Baldwin { 658*98685dc8SJohn Baldwin pid_t fpid; 659*98685dc8SJohn Baldwin 660*98685dc8SJohn Baldwin close(cpipe[0]); 661*98685dc8SJohn Baldwin 662*98685dc8SJohn Baldwin /* Double-fork to disassociate from the debugger. */ 663*98685dc8SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 664*98685dc8SJohn Baldwin if (fpid != 0) 665*98685dc8SJohn Baldwin exit(3); 666*98685dc8SJohn Baldwin 667*98685dc8SJohn Baldwin /* Send the pid of the disassociated child to the debugger. */ 668*98685dc8SJohn Baldwin fpid = getpid(); 669*98685dc8SJohn Baldwin CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid)); 670*98685dc8SJohn Baldwin 671*98685dc8SJohn Baldwin /* Wait for the debugger to attach. */ 672*98685dc8SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0); 673*98685dc8SJohn Baldwin } 674*98685dc8SJohn Baldwin 675*98685dc8SJohn Baldwin /* 676*98685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork and 677*98685dc8SJohn Baldwin * that the traced parent sees the exit of the child after the debugger 678*98685dc8SJohn Baldwin * when both processes remain attached to the debugger. In this test 679*98685dc8SJohn Baldwin * the parent that forks is not a direct child of the debugger. 680*98685dc8SJohn Baldwin */ 681*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger); 682*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc) 683*98685dc8SJohn Baldwin { 684*98685dc8SJohn Baldwin pid_t children[0], fpid, wpid; 685*98685dc8SJohn Baldwin int cpipe[2], status; 686*98685dc8SJohn Baldwin 687*98685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 688*98685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 689*98685dc8SJohn Baldwin if (fpid == 0) { 690*98685dc8SJohn Baldwin attach_fork_parent(cpipe); 691*98685dc8SJohn Baldwin follow_fork_parent(); 692*98685dc8SJohn Baldwin } 693*98685dc8SJohn Baldwin 694*98685dc8SJohn Baldwin /* Parent process. */ 695*98685dc8SJohn Baldwin close(cpipe[1]); 696*98685dc8SJohn Baldwin 697*98685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 698*98685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 699*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 700*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 701*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 702*98685dc8SJohn Baldwin 703*98685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 704*98685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 705*98685dc8SJohn Baldwin sizeof(children[0])); 706*98685dc8SJohn Baldwin 707*98685dc8SJohn Baldwin /* Attach to the fork parent. */ 708*98685dc8SJohn Baldwin attach_child(children[0]); 709*98685dc8SJohn Baldwin 710*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 711*98685dc8SJohn Baldwin 712*98685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 713*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 714*98685dc8SJohn Baldwin 715*98685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 716*98685dc8SJohn Baldwin close(cpipe[0]); 717*98685dc8SJohn Baldwin 718*98685dc8SJohn Baldwin children[1] = handle_fork_events(children[0]); 719*98685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 720*98685dc8SJohn Baldwin 721*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 722*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 723*98685dc8SJohn Baldwin 724*98685dc8SJohn Baldwin /* 725*98685dc8SJohn Baldwin * The fork parent can't exit until the child reports status, 726*98685dc8SJohn Baldwin * so the child should report its exit first to the debugger. 727*98685dc8SJohn Baldwin */ 728*98685dc8SJohn Baldwin wpid = wait(&status); 729*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 730*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 731*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 732*98685dc8SJohn Baldwin 733*98685dc8SJohn Baldwin wpid = wait(&status); 734*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 735*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 736*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 737*98685dc8SJohn Baldwin 738*98685dc8SJohn Baldwin wpid = wait(&status); 739*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 740*98685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 741*98685dc8SJohn Baldwin } 742*98685dc8SJohn Baldwin 743*98685dc8SJohn Baldwin /* 744*98685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 745*98685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the new 746*98685dc8SJohn Baldwin * child process is detached after it reports its fork. In this test 747*98685dc8SJohn Baldwin * the parent that forks is not a direct child of the debugger. 748*98685dc8SJohn Baldwin */ 749*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger); 750*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc) 751*98685dc8SJohn Baldwin { 752*98685dc8SJohn Baldwin pid_t children[0], fpid, wpid; 753*98685dc8SJohn Baldwin int cpipe[2], status; 754*98685dc8SJohn Baldwin 755*98685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 756*98685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 757*98685dc8SJohn Baldwin if (fpid == 0) { 758*98685dc8SJohn Baldwin attach_fork_parent(cpipe); 759*98685dc8SJohn Baldwin follow_fork_parent(); 760*98685dc8SJohn Baldwin } 761*98685dc8SJohn Baldwin 762*98685dc8SJohn Baldwin /* Parent process. */ 763*98685dc8SJohn Baldwin close(cpipe[1]); 764*98685dc8SJohn Baldwin 765*98685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 766*98685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 767*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 768*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 769*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 770*98685dc8SJohn Baldwin 771*98685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 772*98685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 773*98685dc8SJohn Baldwin sizeof(children[0])); 774*98685dc8SJohn Baldwin 775*98685dc8SJohn Baldwin /* Attach to the fork parent. */ 776*98685dc8SJohn Baldwin attach_child(children[0]); 777*98685dc8SJohn Baldwin 778*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 779*98685dc8SJohn Baldwin 780*98685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 781*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 782*98685dc8SJohn Baldwin 783*98685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 784*98685dc8SJohn Baldwin close(cpipe[0]); 785*98685dc8SJohn Baldwin 786*98685dc8SJohn Baldwin children[1] = handle_fork_events(children[0]); 787*98685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 788*98685dc8SJohn Baldwin 789*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 790*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1); 791*98685dc8SJohn Baldwin 792*98685dc8SJohn Baldwin /* 793*98685dc8SJohn Baldwin * Should not see any status from the child now, only the fork 794*98685dc8SJohn Baldwin * parent. 795*98685dc8SJohn Baldwin */ 796*98685dc8SJohn Baldwin wpid = wait(&status); 797*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 798*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 799*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 800*98685dc8SJohn Baldwin 801*98685dc8SJohn Baldwin wpid = wait(&status); 802*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 803*98685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 804*98685dc8SJohn Baldwin } 805*98685dc8SJohn Baldwin 806*98685dc8SJohn Baldwin /* 807*98685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 808*98685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the 809*98685dc8SJohn Baldwin * traced parent is detached after the fork. In this test the parent 810*98685dc8SJohn Baldwin * that forks is not a direct child of the debugger. 811*98685dc8SJohn Baldwin */ 812*98685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger); 813*98685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc) 814*98685dc8SJohn Baldwin { 815*98685dc8SJohn Baldwin pid_t children[0], fpid, wpid; 816*98685dc8SJohn Baldwin int cpipe[2], status; 817*98685dc8SJohn Baldwin 818*98685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 819*98685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 820*98685dc8SJohn Baldwin if (fpid == 0) { 821*98685dc8SJohn Baldwin attach_fork_parent(cpipe); 822*98685dc8SJohn Baldwin follow_fork_parent(); 823*98685dc8SJohn Baldwin } 824*98685dc8SJohn Baldwin 825*98685dc8SJohn Baldwin /* Parent process. */ 826*98685dc8SJohn Baldwin close(cpipe[1]); 827*98685dc8SJohn Baldwin 828*98685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 829*98685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 830*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 831*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 832*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 833*98685dc8SJohn Baldwin 834*98685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 835*98685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 836*98685dc8SJohn Baldwin sizeof(children[0])); 837*98685dc8SJohn Baldwin 838*98685dc8SJohn Baldwin /* Attach to the fork parent. */ 839*98685dc8SJohn Baldwin attach_child(children[0]); 840*98685dc8SJohn Baldwin 841*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 842*98685dc8SJohn Baldwin 843*98685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 844*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 845*98685dc8SJohn Baldwin 846*98685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 847*98685dc8SJohn Baldwin close(cpipe[0]); 848*98685dc8SJohn Baldwin 849*98685dc8SJohn Baldwin children[1] = handle_fork_events(children[0]); 850*98685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 851*98685dc8SJohn Baldwin 852*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1); 853*98685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 854*98685dc8SJohn Baldwin 855*98685dc8SJohn Baldwin /* 856*98685dc8SJohn Baldwin * Should not see any status from the fork parent now, only 857*98685dc8SJohn Baldwin * the child. 858*98685dc8SJohn Baldwin */ 859*98685dc8SJohn Baldwin wpid = wait(&status); 860*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 861*98685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 862*98685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 863*98685dc8SJohn Baldwin 864*98685dc8SJohn Baldwin wpid = wait(&status); 865*98685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 866*98685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 867*98685dc8SJohn Baldwin } 868*98685dc8SJohn Baldwin 869c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp) 870c209e3e2SJohn Baldwin { 871c209e3e2SJohn Baldwin 872c209e3e2SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me); 873c209e3e2SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach); 87457c74f5bSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger); 87557c74f5bSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger); 876*98685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached); 877*98685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached); 878*98685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached); 879*98685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger); 880*98685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, 881*98685dc8SJohn Baldwin ptrace__follow_fork_child_detached_unrelated_debugger); 882*98685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, 883*98685dc8SJohn Baldwin ptrace__follow_fork_parent_detached_unrelated_debugger); 884c209e3e2SJohn Baldwin 885c209e3e2SJohn Baldwin return (atf_no_error()); 886c209e3e2SJohn Baldwin } 887