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> 32189ac973SJohn Baldwin #include <sys/syscall.h> 3357c74f5bSJohn Baldwin #include <sys/sysctl.h> 3457c74f5bSJohn Baldwin #include <sys/user.h> 35c209e3e2SJohn Baldwin #include <sys/wait.h> 36c209e3e2SJohn Baldwin #include <errno.h> 37189ac973SJohn Baldwin #include <pthread.h> 38c209e3e2SJohn Baldwin #include <signal.h> 39dfa8ba12SJohn Baldwin #include <stdio.h> 40c209e3e2SJohn Baldwin #include <stdlib.h> 41c209e3e2SJohn Baldwin #include <unistd.h> 42c209e3e2SJohn Baldwin #include <atf-c.h> 43c209e3e2SJohn Baldwin 44c209e3e2SJohn Baldwin /* 45dfa8ba12SJohn Baldwin * A variant of ATF_REQUIRE that is suitable for use in child 46dfa8ba12SJohn Baldwin * processes. This only works if the parent process is tripped up by 47dfa8ba12SJohn Baldwin * the early exit and fails some requirement itself. 48dfa8ba12SJohn Baldwin */ 49dfa8ba12SJohn Baldwin #define CHILD_REQUIRE(exp) do { \ 50dfa8ba12SJohn Baldwin if (!(exp)) \ 51dfa8ba12SJohn Baldwin child_fail_require(__FILE__, __LINE__, \ 52dfa8ba12SJohn Baldwin #exp " not met"); \ 53dfa8ba12SJohn Baldwin } while (0) 54dfa8ba12SJohn Baldwin 5598685dc8SJohn Baldwin static __dead2 void 56dfa8ba12SJohn Baldwin child_fail_require(const char *file, int line, const char *str) 57dfa8ba12SJohn Baldwin { 58dfa8ba12SJohn Baldwin char buf[128]; 59dfa8ba12SJohn Baldwin 60dfa8ba12SJohn Baldwin snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str); 61dfa8ba12SJohn Baldwin write(2, buf, strlen(buf)); 62dfa8ba12SJohn Baldwin _exit(32); 63dfa8ba12SJohn Baldwin } 64dfa8ba12SJohn Baldwin 6598685dc8SJohn Baldwin static void 6698685dc8SJohn Baldwin trace_me(void) 6798685dc8SJohn Baldwin { 6898685dc8SJohn Baldwin 6998685dc8SJohn Baldwin /* Attach the parent process as a tracer of this process. */ 7098685dc8SJohn Baldwin CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7198685dc8SJohn Baldwin 7298685dc8SJohn Baldwin /* Trigger a stop. */ 7398685dc8SJohn Baldwin raise(SIGSTOP); 7498685dc8SJohn Baldwin } 7598685dc8SJohn Baldwin 7698685dc8SJohn Baldwin static void 7798685dc8SJohn Baldwin attach_child(pid_t pid) 7898685dc8SJohn Baldwin { 7998685dc8SJohn Baldwin pid_t wpid; 8098685dc8SJohn Baldwin int status; 8198685dc8SJohn Baldwin 8298685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0); 8398685dc8SJohn Baldwin 8498685dc8SJohn Baldwin wpid = waitpid(pid, &status, 0); 8598685dc8SJohn Baldwin ATF_REQUIRE(wpid == pid); 8698685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 8798685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 8898685dc8SJohn Baldwin } 8998685dc8SJohn Baldwin 9098685dc8SJohn Baldwin static void 9198685dc8SJohn Baldwin wait_for_zombie(pid_t pid) 9298685dc8SJohn Baldwin { 9398685dc8SJohn Baldwin 9498685dc8SJohn Baldwin /* 9598685dc8SJohn Baldwin * Wait for a process to exit. This is kind of gross, but 9698685dc8SJohn Baldwin * there is not a better way. 9798685dc8SJohn Baldwin */ 9898685dc8SJohn Baldwin for (;;) { 9998685dc8SJohn Baldwin struct kinfo_proc kp; 10098685dc8SJohn Baldwin size_t len; 10198685dc8SJohn Baldwin int mib[4]; 10298685dc8SJohn Baldwin 10398685dc8SJohn Baldwin mib[0] = CTL_KERN; 10498685dc8SJohn Baldwin mib[1] = KERN_PROC; 10598685dc8SJohn Baldwin mib[2] = KERN_PROC_PID; 10698685dc8SJohn Baldwin mib[3] = pid; 10798685dc8SJohn Baldwin len = sizeof(kp); 10898685dc8SJohn Baldwin if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) { 10998685dc8SJohn Baldwin /* The KERN_PROC_PID sysctl fails for zombies. */ 11098685dc8SJohn Baldwin ATF_REQUIRE(errno == ESRCH); 11198685dc8SJohn Baldwin break; 11298685dc8SJohn Baldwin } 11398685dc8SJohn Baldwin usleep(5000); 11498685dc8SJohn Baldwin } 11598685dc8SJohn Baldwin } 11698685dc8SJohn Baldwin 117dfa8ba12SJohn Baldwin /* 118c209e3e2SJohn Baldwin * Verify that a parent debugger process "sees" the exit of a debugged 119c209e3e2SJohn Baldwin * process exactly once when attached via PT_TRACE_ME. 120c209e3e2SJohn Baldwin */ 121c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me); 122c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc) 123c209e3e2SJohn Baldwin { 124c209e3e2SJohn Baldwin pid_t child, wpid; 125c209e3e2SJohn Baldwin int status; 126c209e3e2SJohn Baldwin 127c209e3e2SJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 128c209e3e2SJohn Baldwin if (child == 0) { 129c209e3e2SJohn Baldwin /* Child process. */ 13098685dc8SJohn Baldwin trace_me(); 131c209e3e2SJohn Baldwin 132b98cb919SJohn Baldwin _exit(1); 133c209e3e2SJohn Baldwin } 134c209e3e2SJohn Baldwin 135c209e3e2SJohn Baldwin /* Parent process. */ 136c209e3e2SJohn Baldwin 137c209e3e2SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 138c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 139c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 140c209e3e2SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 141c209e3e2SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 142c209e3e2SJohn Baldwin 143c209e3e2SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 144c209e3e2SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 145c209e3e2SJohn Baldwin 146c209e3e2SJohn Baldwin /* The second wait() should report the exit status. */ 147c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 148c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 149c209e3e2SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 150c209e3e2SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 151c209e3e2SJohn Baldwin 152c209e3e2SJohn Baldwin /* The child should no longer exist. */ 153c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 154c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == -1); 155c209e3e2SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 156c209e3e2SJohn Baldwin } 157c209e3e2SJohn Baldwin 158c209e3e2SJohn Baldwin /* 159c209e3e2SJohn Baldwin * Verify that a parent debugger process "sees" the exit of a debugged 160c209e3e2SJohn Baldwin * process exactly once when attached via PT_ATTACH. 161c209e3e2SJohn Baldwin */ 162c209e3e2SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach); 163c209e3e2SJohn Baldwin ATF_TC_BODY(ptrace__parent_wait_after_attach, tc) 164c209e3e2SJohn Baldwin { 165c209e3e2SJohn Baldwin pid_t child, wpid; 166c209e3e2SJohn Baldwin int cpipe[2], status; 167c209e3e2SJohn Baldwin char c; 168c209e3e2SJohn Baldwin 169c209e3e2SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 170c209e3e2SJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 171c209e3e2SJohn Baldwin if (child == 0) { 172c209e3e2SJohn Baldwin /* Child process. */ 173c209e3e2SJohn Baldwin close(cpipe[0]); 174c209e3e2SJohn Baldwin 175c209e3e2SJohn Baldwin /* Wait for the parent to attach. */ 176dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0); 177c209e3e2SJohn Baldwin 178b98cb919SJohn Baldwin _exit(1); 179c209e3e2SJohn Baldwin } 180c209e3e2SJohn Baldwin close(cpipe[1]); 181c209e3e2SJohn Baldwin 182c209e3e2SJohn Baldwin /* Parent process. */ 183c209e3e2SJohn Baldwin 184c209e3e2SJohn Baldwin /* Attach to the child process. */ 18598685dc8SJohn Baldwin attach_child(child); 186c209e3e2SJohn Baldwin 187c209e3e2SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 188c209e3e2SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 189c209e3e2SJohn Baldwin 190c209e3e2SJohn Baldwin /* Signal the child to exit. */ 191c209e3e2SJohn Baldwin close(cpipe[0]); 192c209e3e2SJohn Baldwin 193c209e3e2SJohn Baldwin /* The second wait() should report the exit status. */ 194c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 195c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == child); 196c209e3e2SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 197c209e3e2SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 198c209e3e2SJohn Baldwin 199c209e3e2SJohn Baldwin /* The child should no longer exist. */ 200c209e3e2SJohn Baldwin wpid = waitpid(child, &status, 0); 201c209e3e2SJohn Baldwin ATF_REQUIRE(wpid == -1); 202c209e3e2SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 203c209e3e2SJohn Baldwin } 204c209e3e2SJohn Baldwin 20557c74f5bSJohn Baldwin /* 20657c74f5bSJohn Baldwin * Verify that a parent process "sees" the exit of a debugged process only 20757c74f5bSJohn Baldwin * after the debugger has seen it. 20857c74f5bSJohn Baldwin */ 20957c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger); 21057c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc) 21157c74f5bSJohn Baldwin { 21257c74f5bSJohn Baldwin pid_t child, debugger, wpid; 21357c74f5bSJohn Baldwin int cpipe[2], dpipe[2], status; 21457c74f5bSJohn Baldwin char c; 21557c74f5bSJohn Baldwin 21657c74f5bSJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 21757c74f5bSJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 21857c74f5bSJohn Baldwin 21957c74f5bSJohn Baldwin if (child == 0) { 22057c74f5bSJohn Baldwin /* Child process. */ 22157c74f5bSJohn Baldwin close(cpipe[0]); 22257c74f5bSJohn Baldwin 22357c74f5bSJohn Baldwin /* Wait for parent to be ready. */ 224dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 22557c74f5bSJohn Baldwin 226b98cb919SJohn Baldwin _exit(1); 22757c74f5bSJohn Baldwin } 22857c74f5bSJohn Baldwin close(cpipe[1]); 22957c74f5bSJohn Baldwin 23057c74f5bSJohn Baldwin ATF_REQUIRE(pipe(dpipe) == 0); 23157c74f5bSJohn Baldwin ATF_REQUIRE((debugger = fork()) != -1); 23257c74f5bSJohn Baldwin 23357c74f5bSJohn Baldwin if (debugger == 0) { 23457c74f5bSJohn Baldwin /* Debugger process. */ 23557c74f5bSJohn Baldwin close(dpipe[0]); 23657c74f5bSJohn Baldwin 237dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 23857c74f5bSJohn Baldwin 23957c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 240dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 241dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFSTOPPED(status)); 242dfa8ba12SJohn Baldwin CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 24357c74f5bSJohn Baldwin 244dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 24557c74f5bSJohn Baldwin 24657c74f5bSJohn Baldwin /* Signal parent that debugger is attached. */ 247dfa8ba12SJohn Baldwin CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 24857c74f5bSJohn Baldwin 24957c74f5bSJohn Baldwin /* Wait for parent's failed wait. */ 250dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0); 25157c74f5bSJohn Baldwin 25257c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 253dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 254dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 255dfa8ba12SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 1); 25657c74f5bSJohn Baldwin 257b98cb919SJohn Baldwin _exit(0); 25857c74f5bSJohn Baldwin } 25957c74f5bSJohn Baldwin close(dpipe[1]); 26057c74f5bSJohn Baldwin 26157c74f5bSJohn Baldwin /* Parent process. */ 26257c74f5bSJohn Baldwin 26357c74f5bSJohn Baldwin /* Wait for the debugger to attach to the child. */ 26457c74f5bSJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 26557c74f5bSJohn Baldwin 26657c74f5bSJohn Baldwin /* Release the child. */ 26757c74f5bSJohn Baldwin ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 26857c74f5bSJohn Baldwin ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0); 26957c74f5bSJohn Baldwin close(cpipe[0]); 27057c74f5bSJohn Baldwin 27198685dc8SJohn Baldwin wait_for_zombie(child); 27257c74f5bSJohn Baldwin 27357c74f5bSJohn Baldwin /* 2742f021998SJohn Baldwin * This wait should return a pid of 0 to indicate no status to 2752f021998SJohn Baldwin * report. The parent should see the child as non-exited 2762f021998SJohn Baldwin * until the debugger sees the exit. 27757c74f5bSJohn Baldwin */ 27857c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 27957c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 28057c74f5bSJohn Baldwin 28157c74f5bSJohn Baldwin /* Signal the debugger to wait for the child. */ 28257c74f5bSJohn Baldwin close(dpipe[0]); 28357c74f5bSJohn Baldwin 28457c74f5bSJohn Baldwin /* Wait for the debugger. */ 28557c74f5bSJohn Baldwin wpid = waitpid(debugger, &status, 0); 28657c74f5bSJohn Baldwin ATF_REQUIRE(wpid == debugger); 28757c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 28857c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 28957c74f5bSJohn Baldwin 29057c74f5bSJohn Baldwin /* The child process should now be ready. */ 29157c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 29257c74f5bSJohn Baldwin ATF_REQUIRE(wpid == child); 29357c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 29457c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 29557c74f5bSJohn Baldwin } 29657c74f5bSJohn Baldwin 29757c74f5bSJohn Baldwin /* 29857c74f5bSJohn Baldwin * Verify that a parent process "sees" the exit of a debugged process 29957c74f5bSJohn Baldwin * only after a non-direct-child debugger has seen it. In particular, 30057c74f5bSJohn Baldwin * various wait() calls in the parent must avoid failing with ESRCH by 30157c74f5bSJohn Baldwin * checking the parent's orphan list for the debugee. 30257c74f5bSJohn Baldwin */ 30357c74f5bSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger); 30457c74f5bSJohn Baldwin ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc) 30557c74f5bSJohn Baldwin { 30657c74f5bSJohn Baldwin pid_t child, debugger, fpid, wpid; 30757c74f5bSJohn Baldwin int cpipe[2], dpipe[2], status; 30857c74f5bSJohn Baldwin char c; 30957c74f5bSJohn Baldwin 31057c74f5bSJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 31157c74f5bSJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 31257c74f5bSJohn Baldwin 31357c74f5bSJohn Baldwin if (child == 0) { 31457c74f5bSJohn Baldwin /* Child process. */ 31557c74f5bSJohn Baldwin close(cpipe[0]); 31657c74f5bSJohn Baldwin 31757c74f5bSJohn Baldwin /* Wait for parent to be ready. */ 318dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 31957c74f5bSJohn Baldwin 320b98cb919SJohn Baldwin _exit(1); 32157c74f5bSJohn Baldwin } 32257c74f5bSJohn Baldwin close(cpipe[1]); 32357c74f5bSJohn Baldwin 32457c74f5bSJohn Baldwin ATF_REQUIRE(pipe(dpipe) == 0); 32557c74f5bSJohn Baldwin ATF_REQUIRE((debugger = fork()) != -1); 32657c74f5bSJohn Baldwin 32757c74f5bSJohn Baldwin if (debugger == 0) { 32857c74f5bSJohn Baldwin /* Debugger parent. */ 32957c74f5bSJohn Baldwin 33057c74f5bSJohn Baldwin /* 33157c74f5bSJohn Baldwin * Fork again and drop the debugger parent so that the 33257c74f5bSJohn Baldwin * debugger is not a child of the main parent. 33357c74f5bSJohn Baldwin */ 334dfa8ba12SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 33557c74f5bSJohn Baldwin if (fpid != 0) 336b98cb919SJohn Baldwin _exit(2); 33757c74f5bSJohn Baldwin 33857c74f5bSJohn Baldwin /* Debugger process. */ 33957c74f5bSJohn Baldwin close(dpipe[0]); 34057c74f5bSJohn Baldwin 341dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 34257c74f5bSJohn Baldwin 34357c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 344dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 345dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFSTOPPED(status)); 346dfa8ba12SJohn Baldwin CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 34757c74f5bSJohn Baldwin 348dfa8ba12SJohn Baldwin CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 34957c74f5bSJohn Baldwin 35057c74f5bSJohn Baldwin /* Signal parent that debugger is attached. */ 351dfa8ba12SJohn Baldwin CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 35257c74f5bSJohn Baldwin 35357c74f5bSJohn Baldwin /* Wait for parent's failed wait. */ 354dfa8ba12SJohn Baldwin CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c)); 35557c74f5bSJohn Baldwin 35657c74f5bSJohn Baldwin wpid = waitpid(child, &status, 0); 357dfa8ba12SJohn Baldwin CHILD_REQUIRE(wpid == child); 358dfa8ba12SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 359dfa8ba12SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 1); 36057c74f5bSJohn Baldwin 361b98cb919SJohn Baldwin _exit(0); 36257c74f5bSJohn Baldwin } 363eddb85c6SJohn Baldwin close(dpipe[1]); 36457c74f5bSJohn Baldwin 36557c74f5bSJohn Baldwin /* Parent process. */ 36657c74f5bSJohn Baldwin 36757c74f5bSJohn Baldwin /* Wait for the debugger parent process to exit. */ 36857c74f5bSJohn Baldwin wpid = waitpid(debugger, &status, 0); 36957c74f5bSJohn Baldwin ATF_REQUIRE(wpid == debugger); 37057c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 37157c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 37257c74f5bSJohn Baldwin 37357c74f5bSJohn Baldwin /* A WNOHANG wait here should see the non-exited child. */ 37457c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 37557c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 37657c74f5bSJohn Baldwin 37757c74f5bSJohn Baldwin /* Wait for the debugger to attach to the child. */ 37857c74f5bSJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 37957c74f5bSJohn Baldwin 38057c74f5bSJohn Baldwin /* Release the child. */ 38157c74f5bSJohn Baldwin ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 38257c74f5bSJohn Baldwin ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0); 38357c74f5bSJohn Baldwin close(cpipe[0]); 38457c74f5bSJohn Baldwin 38598685dc8SJohn Baldwin wait_for_zombie(child); 38657c74f5bSJohn Baldwin 38757c74f5bSJohn Baldwin /* 3882f021998SJohn Baldwin * This wait should return a pid of 0 to indicate no status to 3892f021998SJohn Baldwin * report. The parent should see the child as non-exited 3902f021998SJohn Baldwin * until the debugger sees the exit. 39157c74f5bSJohn Baldwin */ 39257c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 39357c74f5bSJohn Baldwin ATF_REQUIRE(wpid == 0); 39457c74f5bSJohn Baldwin 39557c74f5bSJohn Baldwin /* Signal the debugger to wait for the child. */ 396eddb85c6SJohn Baldwin ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c)); 39757c74f5bSJohn Baldwin 39857c74f5bSJohn Baldwin /* Wait for the debugger. */ 399eddb85c6SJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0); 400eddb85c6SJohn Baldwin close(dpipe[0]); 40157c74f5bSJohn Baldwin 40257c74f5bSJohn Baldwin /* The child process should now be ready. */ 40357c74f5bSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 40457c74f5bSJohn Baldwin ATF_REQUIRE(wpid == child); 40557c74f5bSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 40657c74f5bSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 40757c74f5bSJohn Baldwin } 40857c74f5bSJohn Baldwin 40998685dc8SJohn Baldwin /* 41098685dc8SJohn Baldwin * The parent process should always act the same regardless of how the 41198685dc8SJohn Baldwin * debugger is attached to it. 41298685dc8SJohn Baldwin */ 41398685dc8SJohn Baldwin static __dead2 void 414189ac973SJohn Baldwin follow_fork_parent(bool use_vfork) 41598685dc8SJohn Baldwin { 41698685dc8SJohn Baldwin pid_t fpid, wpid; 41798685dc8SJohn Baldwin int status; 41898685dc8SJohn Baldwin 419189ac973SJohn Baldwin if (use_vfork) 420189ac973SJohn Baldwin CHILD_REQUIRE((fpid = vfork()) != -1); 421189ac973SJohn Baldwin else 42298685dc8SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 42398685dc8SJohn Baldwin 42498685dc8SJohn Baldwin if (fpid == 0) 42598685dc8SJohn Baldwin /* Child */ 426b98cb919SJohn Baldwin _exit(2); 42798685dc8SJohn Baldwin 42898685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 42998685dc8SJohn Baldwin CHILD_REQUIRE(wpid == fpid); 43098685dc8SJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 43198685dc8SJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 2); 43298685dc8SJohn Baldwin 433b98cb919SJohn Baldwin _exit(1); 43498685dc8SJohn Baldwin } 43598685dc8SJohn Baldwin 43698685dc8SJohn Baldwin /* 43798685dc8SJohn Baldwin * Helper routine for follow fork tests. This waits for two stops 43898685dc8SJohn Baldwin * that report both "sides" of a fork. It returns the pid of the new 43998685dc8SJohn Baldwin * child process. 44098685dc8SJohn Baldwin */ 44198685dc8SJohn Baldwin static pid_t 442189ac973SJohn Baldwin handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl) 44398685dc8SJohn Baldwin { 44498685dc8SJohn Baldwin struct ptrace_lwpinfo pl; 44598685dc8SJohn Baldwin bool fork_reported[2]; 44698685dc8SJohn Baldwin pid_t child, wpid; 44798685dc8SJohn Baldwin int i, status; 44898685dc8SJohn Baldwin 44998685dc8SJohn Baldwin fork_reported[0] = false; 45098685dc8SJohn Baldwin fork_reported[1] = false; 45198685dc8SJohn Baldwin child = -1; 45298685dc8SJohn Baldwin 45398685dc8SJohn Baldwin /* 45498685dc8SJohn Baldwin * Each process should report a fork event. The parent should 45598685dc8SJohn Baldwin * report a PL_FLAG_FORKED event, and the child should report 45698685dc8SJohn Baldwin * a PL_FLAG_CHILD event. 45798685dc8SJohn Baldwin */ 45898685dc8SJohn Baldwin for (i = 0; i < 2; i++) { 45998685dc8SJohn Baldwin wpid = wait(&status); 46098685dc8SJohn Baldwin ATF_REQUIRE(wpid > 0); 46198685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 46298685dc8SJohn Baldwin 46398685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 46498685dc8SJohn Baldwin sizeof(pl)) != -1); 46598685dc8SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) != 46698685dc8SJohn Baldwin 0); 46798685dc8SJohn Baldwin ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) != 46898685dc8SJohn Baldwin (PL_FLAG_FORKED | PL_FLAG_CHILD)); 46998685dc8SJohn Baldwin if (pl.pl_flags & PL_FLAG_CHILD) { 47098685dc8SJohn Baldwin ATF_REQUIRE(wpid != parent); 47198685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 47298685dc8SJohn Baldwin ATF_REQUIRE(!fork_reported[1]); 47398685dc8SJohn Baldwin if (child == -1) 47498685dc8SJohn Baldwin child = wpid; 47598685dc8SJohn Baldwin else 47698685dc8SJohn Baldwin ATF_REQUIRE(child == wpid); 477189ac973SJohn Baldwin if (ppl != NULL) 478189ac973SJohn Baldwin ppl[1] = pl; 47998685dc8SJohn Baldwin fork_reported[1] = true; 48098685dc8SJohn Baldwin } else { 48198685dc8SJohn Baldwin ATF_REQUIRE(wpid == parent); 48298685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 48398685dc8SJohn Baldwin ATF_REQUIRE(!fork_reported[0]); 48498685dc8SJohn Baldwin if (child == -1) 48598685dc8SJohn Baldwin child = pl.pl_child_pid; 48698685dc8SJohn Baldwin else 48798685dc8SJohn Baldwin ATF_REQUIRE(child == pl.pl_child_pid); 488189ac973SJohn Baldwin if (ppl != NULL) 489189ac973SJohn Baldwin ppl[0] = pl; 49098685dc8SJohn Baldwin fork_reported[0] = true; 49198685dc8SJohn Baldwin } 49298685dc8SJohn Baldwin } 49398685dc8SJohn Baldwin 49498685dc8SJohn Baldwin return (child); 49598685dc8SJohn Baldwin } 49698685dc8SJohn Baldwin 49798685dc8SJohn Baldwin /* 49898685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork and 49998685dc8SJohn Baldwin * that the traced parent sees the exit of the child after the debugger 50098685dc8SJohn Baldwin * when both processes remain attached to the debugger. 50198685dc8SJohn Baldwin */ 50298685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached); 50398685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached, tc) 50498685dc8SJohn Baldwin { 505479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 50698685dc8SJohn Baldwin int status; 50798685dc8SJohn Baldwin 50898685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 50998685dc8SJohn Baldwin if (fpid == 0) { 51098685dc8SJohn Baldwin trace_me(); 511189ac973SJohn Baldwin follow_fork_parent(false); 51298685dc8SJohn Baldwin } 51398685dc8SJohn Baldwin 51498685dc8SJohn Baldwin /* Parent process. */ 51598685dc8SJohn Baldwin children[0] = fpid; 51698685dc8SJohn Baldwin 51798685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 51898685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 51998685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 52098685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 52198685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 52298685dc8SJohn Baldwin 52398685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 52498685dc8SJohn Baldwin 52598685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 52698685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 52798685dc8SJohn Baldwin 528189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 52998685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 53098685dc8SJohn Baldwin 53198685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 53298685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 53398685dc8SJohn Baldwin 53498685dc8SJohn Baldwin /* 53598685dc8SJohn Baldwin * The child can't exit until the grandchild reports status, so the 53698685dc8SJohn Baldwin * grandchild should report its exit first to the debugger. 53798685dc8SJohn Baldwin */ 53898685dc8SJohn Baldwin wpid = wait(&status); 53998685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 54098685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 54198685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 54298685dc8SJohn Baldwin 54398685dc8SJohn Baldwin wpid = wait(&status); 54498685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 54598685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 54698685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 54798685dc8SJohn Baldwin 54898685dc8SJohn Baldwin wpid = wait(&status); 54998685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 55098685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 55198685dc8SJohn Baldwin } 55298685dc8SJohn Baldwin 55398685dc8SJohn Baldwin /* 55498685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 55598685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the new 55698685dc8SJohn Baldwin * child process is detached after it reports its fork. 55798685dc8SJohn Baldwin */ 55898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached); 55998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached, tc) 56098685dc8SJohn Baldwin { 561479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 56298685dc8SJohn Baldwin int status; 56398685dc8SJohn Baldwin 56498685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 56598685dc8SJohn Baldwin if (fpid == 0) { 56698685dc8SJohn Baldwin trace_me(); 567189ac973SJohn Baldwin follow_fork_parent(false); 56898685dc8SJohn Baldwin } 56998685dc8SJohn Baldwin 57098685dc8SJohn Baldwin /* Parent process. */ 57198685dc8SJohn Baldwin children[0] = fpid; 57298685dc8SJohn Baldwin 57398685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 57498685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 57598685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 57698685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 57798685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 57898685dc8SJohn Baldwin 57998685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 58098685dc8SJohn Baldwin 58198685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 58298685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 58398685dc8SJohn Baldwin 584189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 58598685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 58698685dc8SJohn Baldwin 58798685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 58898685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1); 58998685dc8SJohn Baldwin 59098685dc8SJohn Baldwin /* 59198685dc8SJohn Baldwin * Should not see any status from the grandchild now, only the 59298685dc8SJohn Baldwin * child. 59398685dc8SJohn Baldwin */ 59498685dc8SJohn Baldwin wpid = wait(&status); 59598685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 59698685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 59798685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 59898685dc8SJohn Baldwin 59998685dc8SJohn Baldwin wpid = wait(&status); 60098685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 60198685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 60298685dc8SJohn Baldwin } 60398685dc8SJohn Baldwin 60498685dc8SJohn Baldwin /* 60598685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 60698685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the 60798685dc8SJohn Baldwin * traced parent is detached after the fork. 60898685dc8SJohn Baldwin */ 60998685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached); 61098685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc) 61198685dc8SJohn Baldwin { 612479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 61398685dc8SJohn Baldwin int status; 61498685dc8SJohn Baldwin 61598685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 61698685dc8SJohn Baldwin if (fpid == 0) { 61798685dc8SJohn Baldwin trace_me(); 618189ac973SJohn Baldwin follow_fork_parent(false); 61998685dc8SJohn Baldwin } 62098685dc8SJohn Baldwin 62198685dc8SJohn Baldwin /* Parent process. */ 62298685dc8SJohn Baldwin children[0] = fpid; 62398685dc8SJohn Baldwin 62498685dc8SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 62598685dc8SJohn Baldwin wpid = waitpid(children[0], &status, 0); 62698685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 62798685dc8SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 62898685dc8SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 62998685dc8SJohn Baldwin 63098685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 63198685dc8SJohn Baldwin 63298685dc8SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 63398685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 63498685dc8SJohn Baldwin 635189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 63698685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 63798685dc8SJohn Baldwin 63898685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1); 63998685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 64098685dc8SJohn Baldwin 64198685dc8SJohn Baldwin /* 64298685dc8SJohn Baldwin * The child can't exit until the grandchild reports status, so the 64398685dc8SJohn Baldwin * grandchild should report its exit first to the debugger. 64498685dc8SJohn Baldwin * 64598685dc8SJohn Baldwin * Even though the child process is detached, it is still a 64698685dc8SJohn Baldwin * child of the debugger, so it will still report it's exit 64798685dc8SJohn Baldwin * after the grandchild. 64898685dc8SJohn Baldwin */ 64998685dc8SJohn Baldwin wpid = wait(&status); 65098685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 65198685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 65298685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 65398685dc8SJohn Baldwin 65498685dc8SJohn Baldwin wpid = wait(&status); 65598685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 65698685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 65798685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 65898685dc8SJohn Baldwin 65998685dc8SJohn Baldwin wpid = wait(&status); 66098685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 66198685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 66298685dc8SJohn Baldwin } 66398685dc8SJohn Baldwin 66498685dc8SJohn Baldwin static void 66598685dc8SJohn Baldwin attach_fork_parent(int cpipe[2]) 66698685dc8SJohn Baldwin { 66798685dc8SJohn Baldwin pid_t fpid; 66898685dc8SJohn Baldwin 66998685dc8SJohn Baldwin close(cpipe[0]); 67098685dc8SJohn Baldwin 67198685dc8SJohn Baldwin /* Double-fork to disassociate from the debugger. */ 67298685dc8SJohn Baldwin CHILD_REQUIRE((fpid = fork()) != -1); 67398685dc8SJohn Baldwin if (fpid != 0) 674b98cb919SJohn Baldwin _exit(3); 67598685dc8SJohn Baldwin 67698685dc8SJohn Baldwin /* Send the pid of the disassociated child to the debugger. */ 67798685dc8SJohn Baldwin fpid = getpid(); 67898685dc8SJohn Baldwin CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid)); 67998685dc8SJohn Baldwin 68098685dc8SJohn Baldwin /* Wait for the debugger to attach. */ 68198685dc8SJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0); 68298685dc8SJohn Baldwin } 68398685dc8SJohn Baldwin 68498685dc8SJohn Baldwin /* 68598685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork and 68698685dc8SJohn Baldwin * that the traced parent sees the exit of the child after the debugger 68798685dc8SJohn Baldwin * when both processes remain attached to the debugger. In this test 68898685dc8SJohn Baldwin * the parent that forks is not a direct child of the debugger. 68998685dc8SJohn Baldwin */ 69098685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger); 69198685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc) 69298685dc8SJohn Baldwin { 693479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 69498685dc8SJohn Baldwin int cpipe[2], status; 69598685dc8SJohn Baldwin 69698685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 69798685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 69898685dc8SJohn Baldwin if (fpid == 0) { 69998685dc8SJohn Baldwin attach_fork_parent(cpipe); 700189ac973SJohn Baldwin follow_fork_parent(false); 70198685dc8SJohn Baldwin } 70298685dc8SJohn Baldwin 70398685dc8SJohn Baldwin /* Parent process. */ 70498685dc8SJohn Baldwin close(cpipe[1]); 70598685dc8SJohn Baldwin 70698685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 70798685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 70898685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 70998685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 71098685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 71198685dc8SJohn Baldwin 71298685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 71398685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 71498685dc8SJohn Baldwin sizeof(children[0])); 71598685dc8SJohn Baldwin 71698685dc8SJohn Baldwin /* Attach to the fork parent. */ 71798685dc8SJohn Baldwin attach_child(children[0]); 71898685dc8SJohn Baldwin 71998685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 72098685dc8SJohn Baldwin 72198685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 72298685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 72398685dc8SJohn Baldwin 72498685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 72598685dc8SJohn Baldwin close(cpipe[0]); 72698685dc8SJohn Baldwin 727189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 72898685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 72998685dc8SJohn Baldwin 73098685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 73198685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 73298685dc8SJohn Baldwin 73398685dc8SJohn Baldwin /* 73498685dc8SJohn Baldwin * The fork parent can't exit until the child reports status, 73598685dc8SJohn Baldwin * so the child should report its exit first to the debugger. 73698685dc8SJohn Baldwin */ 73798685dc8SJohn Baldwin wpid = wait(&status); 73898685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 73998685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 74098685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 74198685dc8SJohn Baldwin 74298685dc8SJohn Baldwin wpid = wait(&status); 74398685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 74498685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 74598685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 74698685dc8SJohn Baldwin 74798685dc8SJohn Baldwin wpid = wait(&status); 74898685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 74998685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 75098685dc8SJohn Baldwin } 75198685dc8SJohn Baldwin 75298685dc8SJohn Baldwin /* 75398685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 75498685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the new 75598685dc8SJohn Baldwin * child process is detached after it reports its fork. In this test 75698685dc8SJohn Baldwin * the parent that forks is not a direct child of the debugger. 75798685dc8SJohn Baldwin */ 75898685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger); 75998685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc) 76098685dc8SJohn Baldwin { 761479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 76298685dc8SJohn Baldwin int cpipe[2], status; 76398685dc8SJohn Baldwin 76498685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 76598685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 76698685dc8SJohn Baldwin if (fpid == 0) { 76798685dc8SJohn Baldwin attach_fork_parent(cpipe); 768189ac973SJohn Baldwin follow_fork_parent(false); 76998685dc8SJohn Baldwin } 77098685dc8SJohn Baldwin 77198685dc8SJohn Baldwin /* Parent process. */ 77298685dc8SJohn Baldwin close(cpipe[1]); 77398685dc8SJohn Baldwin 77498685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 77598685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 77698685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 77798685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 77898685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 77998685dc8SJohn Baldwin 78098685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 78198685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 78298685dc8SJohn Baldwin sizeof(children[0])); 78398685dc8SJohn Baldwin 78498685dc8SJohn Baldwin /* Attach to the fork parent. */ 78598685dc8SJohn Baldwin attach_child(children[0]); 78698685dc8SJohn Baldwin 78798685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 78898685dc8SJohn Baldwin 78998685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 79098685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 79198685dc8SJohn Baldwin 79298685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 79398685dc8SJohn Baldwin close(cpipe[0]); 79498685dc8SJohn Baldwin 795189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 79698685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 79798685dc8SJohn Baldwin 79898685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 79998685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1); 80098685dc8SJohn Baldwin 80198685dc8SJohn Baldwin /* 80298685dc8SJohn Baldwin * Should not see any status from the child now, only the fork 80398685dc8SJohn Baldwin * parent. 80498685dc8SJohn Baldwin */ 80598685dc8SJohn Baldwin wpid = wait(&status); 80698685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 80798685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 80898685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 80998685dc8SJohn Baldwin 81098685dc8SJohn Baldwin wpid = wait(&status); 81198685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 81298685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 81398685dc8SJohn Baldwin } 81498685dc8SJohn Baldwin 81598685dc8SJohn Baldwin /* 81698685dc8SJohn Baldwin * Verify that a new child process is stopped after a followed fork 81798685dc8SJohn Baldwin * and that the traced parent sees the exit of the child when the 81898685dc8SJohn Baldwin * traced parent is detached after the fork. In this test the parent 81998685dc8SJohn Baldwin * that forks is not a direct child of the debugger. 82098685dc8SJohn Baldwin */ 82198685dc8SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger); 82298685dc8SJohn Baldwin ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc) 82398685dc8SJohn Baldwin { 824479b610dSJohn Baldwin pid_t children[2], fpid, wpid; 82598685dc8SJohn Baldwin int cpipe[2], status; 82698685dc8SJohn Baldwin 82798685dc8SJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 82898685dc8SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 82998685dc8SJohn Baldwin if (fpid == 0) { 83098685dc8SJohn Baldwin attach_fork_parent(cpipe); 831189ac973SJohn Baldwin follow_fork_parent(false); 83298685dc8SJohn Baldwin } 83398685dc8SJohn Baldwin 83498685dc8SJohn Baldwin /* Parent process. */ 83598685dc8SJohn Baldwin close(cpipe[1]); 83698685dc8SJohn Baldwin 83798685dc8SJohn Baldwin /* Wait for the direct child to exit. */ 83898685dc8SJohn Baldwin wpid = waitpid(fpid, &status, 0); 83998685dc8SJohn Baldwin ATF_REQUIRE(wpid == fpid); 84098685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 84198685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 3); 84298685dc8SJohn Baldwin 84398685dc8SJohn Baldwin /* Read the pid of the fork parent. */ 84498685dc8SJohn Baldwin ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) == 84598685dc8SJohn Baldwin sizeof(children[0])); 84698685dc8SJohn Baldwin 84798685dc8SJohn Baldwin /* Attach to the fork parent. */ 84898685dc8SJohn Baldwin attach_child(children[0]); 84998685dc8SJohn Baldwin 85098685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 85198685dc8SJohn Baldwin 85298685dc8SJohn Baldwin /* Continue the fork parent ignoring the SIGSTOP. */ 85398685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 85498685dc8SJohn Baldwin 85598685dc8SJohn Baldwin /* Signal the fork parent to continue. */ 85698685dc8SJohn Baldwin close(cpipe[0]); 85798685dc8SJohn Baldwin 858189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], NULL); 85998685dc8SJohn Baldwin ATF_REQUIRE(children[1] > 0); 86098685dc8SJohn Baldwin 86198685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1); 86298685dc8SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 86398685dc8SJohn Baldwin 86498685dc8SJohn Baldwin /* 86598685dc8SJohn Baldwin * Should not see any status from the fork parent now, only 86698685dc8SJohn Baldwin * the child. 86798685dc8SJohn Baldwin */ 86898685dc8SJohn Baldwin wpid = wait(&status); 86998685dc8SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 87098685dc8SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 87198685dc8SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 87298685dc8SJohn Baldwin 87398685dc8SJohn Baldwin wpid = wait(&status); 87498685dc8SJohn Baldwin ATF_REQUIRE(wpid == -1); 87598685dc8SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 87698685dc8SJohn Baldwin } 87798685dc8SJohn Baldwin 878368b2b1cSJohn Baldwin /* 879368b2b1cSJohn Baldwin * Verify that a child process does not see an unrelated debugger as its 880368b2b1cSJohn Baldwin * parent but sees its original parent process. 881368b2b1cSJohn Baldwin */ 882368b2b1cSJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__getppid); 883368b2b1cSJohn Baldwin ATF_TC_BODY(ptrace__getppid, tc) 884368b2b1cSJohn Baldwin { 885368b2b1cSJohn Baldwin pid_t child, debugger, ppid, wpid; 886368b2b1cSJohn Baldwin int cpipe[2], dpipe[2], status; 887368b2b1cSJohn Baldwin char c; 888368b2b1cSJohn Baldwin 889368b2b1cSJohn Baldwin ATF_REQUIRE(pipe(cpipe) == 0); 890368b2b1cSJohn Baldwin ATF_REQUIRE((child = fork()) != -1); 891368b2b1cSJohn Baldwin 892368b2b1cSJohn Baldwin if (child == 0) { 893368b2b1cSJohn Baldwin /* Child process. */ 894368b2b1cSJohn Baldwin close(cpipe[0]); 895368b2b1cSJohn Baldwin 896368b2b1cSJohn Baldwin /* Wait for parent to be ready. */ 897368b2b1cSJohn Baldwin CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 898368b2b1cSJohn Baldwin 899368b2b1cSJohn Baldwin /* Report the parent PID to the parent. */ 900368b2b1cSJohn Baldwin ppid = getppid(); 901368b2b1cSJohn Baldwin CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) == 902368b2b1cSJohn Baldwin sizeof(ppid)); 903368b2b1cSJohn Baldwin 904368b2b1cSJohn Baldwin _exit(1); 905368b2b1cSJohn Baldwin } 906368b2b1cSJohn Baldwin close(cpipe[1]); 907368b2b1cSJohn Baldwin 908368b2b1cSJohn Baldwin ATF_REQUIRE(pipe(dpipe) == 0); 909368b2b1cSJohn Baldwin ATF_REQUIRE((debugger = fork()) != -1); 910368b2b1cSJohn Baldwin 911368b2b1cSJohn Baldwin if (debugger == 0) { 912368b2b1cSJohn Baldwin /* Debugger process. */ 913368b2b1cSJohn Baldwin close(dpipe[0]); 914368b2b1cSJohn Baldwin 915368b2b1cSJohn Baldwin CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 916368b2b1cSJohn Baldwin 917368b2b1cSJohn Baldwin wpid = waitpid(child, &status, 0); 918368b2b1cSJohn Baldwin CHILD_REQUIRE(wpid == child); 919368b2b1cSJohn Baldwin CHILD_REQUIRE(WIFSTOPPED(status)); 920368b2b1cSJohn Baldwin CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP); 921368b2b1cSJohn Baldwin 922368b2b1cSJohn Baldwin CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 923368b2b1cSJohn Baldwin 924368b2b1cSJohn Baldwin /* Signal parent that debugger is attached. */ 925368b2b1cSJohn Baldwin CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 926368b2b1cSJohn Baldwin 927368b2b1cSJohn Baldwin /* Wait for traced child to exit. */ 928368b2b1cSJohn Baldwin wpid = waitpid(child, &status, 0); 929368b2b1cSJohn Baldwin CHILD_REQUIRE(wpid == child); 930368b2b1cSJohn Baldwin CHILD_REQUIRE(WIFEXITED(status)); 931368b2b1cSJohn Baldwin CHILD_REQUIRE(WEXITSTATUS(status) == 1); 932368b2b1cSJohn Baldwin 933368b2b1cSJohn Baldwin _exit(0); 934368b2b1cSJohn Baldwin } 935368b2b1cSJohn Baldwin close(dpipe[1]); 936368b2b1cSJohn Baldwin 937368b2b1cSJohn Baldwin /* Parent process. */ 938368b2b1cSJohn Baldwin 939368b2b1cSJohn Baldwin /* Wait for the debugger to attach to the child. */ 940368b2b1cSJohn Baldwin ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 941368b2b1cSJohn Baldwin 942368b2b1cSJohn Baldwin /* Release the child. */ 943368b2b1cSJohn Baldwin ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 944368b2b1cSJohn Baldwin 945368b2b1cSJohn Baldwin /* Read the parent PID from the child. */ 946368b2b1cSJohn Baldwin ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid)); 947368b2b1cSJohn Baldwin close(cpipe[0]); 948368b2b1cSJohn Baldwin 949368b2b1cSJohn Baldwin ATF_REQUIRE(ppid == getpid()); 950368b2b1cSJohn Baldwin 951368b2b1cSJohn Baldwin /* Wait for the debugger. */ 952368b2b1cSJohn Baldwin wpid = waitpid(debugger, &status, 0); 953368b2b1cSJohn Baldwin ATF_REQUIRE(wpid == debugger); 954368b2b1cSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 955368b2b1cSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0); 956368b2b1cSJohn Baldwin 957368b2b1cSJohn Baldwin /* The child process should now be ready. */ 958368b2b1cSJohn Baldwin wpid = waitpid(child, &status, WNOHANG); 959368b2b1cSJohn Baldwin ATF_REQUIRE(wpid == child); 960368b2b1cSJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 961368b2b1cSJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 962368b2b1cSJohn Baldwin } 963368b2b1cSJohn Baldwin 964189ac973SJohn Baldwin /* 965189ac973SJohn Baldwin * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new 966189ac973SJohn Baldwin * child process created via fork() reports the correct value. 967189ac973SJohn Baldwin */ 968189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork); 969189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc) 970189ac973SJohn Baldwin { 971189ac973SJohn Baldwin struct ptrace_lwpinfo pl[2]; 972189ac973SJohn Baldwin pid_t children[2], fpid, wpid; 973189ac973SJohn Baldwin int status; 974189ac973SJohn Baldwin 975189ac973SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 976189ac973SJohn Baldwin if (fpid == 0) { 977189ac973SJohn Baldwin trace_me(); 978189ac973SJohn Baldwin follow_fork_parent(false); 979189ac973SJohn Baldwin } 980189ac973SJohn Baldwin 981189ac973SJohn Baldwin /* Parent process. */ 982189ac973SJohn Baldwin children[0] = fpid; 983189ac973SJohn Baldwin 984189ac973SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 985189ac973SJohn Baldwin wpid = waitpid(children[0], &status, 0); 986189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 987189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 988189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 989189ac973SJohn Baldwin 990189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 991189ac973SJohn Baldwin 992189ac973SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 993189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 994189ac973SJohn Baldwin 995189ac973SJohn Baldwin /* Wait for both halves of the fork event to get reported. */ 996189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], pl); 997189ac973SJohn Baldwin ATF_REQUIRE(children[1] > 0); 998189ac973SJohn Baldwin 999189ac973SJohn Baldwin ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0); 1000189ac973SJohn Baldwin ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0); 1001189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork); 1002189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code); 1003189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg); 1004189ac973SJohn Baldwin 1005189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1006189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 1007189ac973SJohn Baldwin 1008189ac973SJohn Baldwin /* 1009189ac973SJohn Baldwin * The child can't exit until the grandchild reports status, so the 1010189ac973SJohn Baldwin * grandchild should report its exit first to the debugger. 1011189ac973SJohn Baldwin */ 1012189ac973SJohn Baldwin wpid = wait(&status); 1013189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 1014189ac973SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1015189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 1016189ac973SJohn Baldwin 1017189ac973SJohn Baldwin wpid = wait(&status); 1018189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1019189ac973SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1020189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1021189ac973SJohn Baldwin 1022189ac973SJohn Baldwin wpid = wait(&status); 1023189ac973SJohn Baldwin ATF_REQUIRE(wpid == -1); 1024189ac973SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 1025189ac973SJohn Baldwin } 1026189ac973SJohn Baldwin 1027189ac973SJohn Baldwin /* 1028189ac973SJohn Baldwin * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new 1029189ac973SJohn Baldwin * child process created via vfork() reports the correct value. 1030189ac973SJohn Baldwin */ 1031189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork); 1032189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc) 1033189ac973SJohn Baldwin { 1034189ac973SJohn Baldwin struct ptrace_lwpinfo pl[2]; 1035189ac973SJohn Baldwin pid_t children[2], fpid, wpid; 1036189ac973SJohn Baldwin int status; 1037189ac973SJohn Baldwin 1038189ac973SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 1039189ac973SJohn Baldwin if (fpid == 0) { 1040189ac973SJohn Baldwin trace_me(); 1041189ac973SJohn Baldwin follow_fork_parent(true); 1042189ac973SJohn Baldwin } 1043189ac973SJohn Baldwin 1044189ac973SJohn Baldwin /* Parent process. */ 1045189ac973SJohn Baldwin children[0] = fpid; 1046189ac973SJohn Baldwin 1047189ac973SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 1048189ac973SJohn Baldwin wpid = waitpid(children[0], &status, 0); 1049189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1050189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1051189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 1052189ac973SJohn Baldwin 1053189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1); 1054189ac973SJohn Baldwin 1055189ac973SJohn Baldwin /* Continue the child ignoring the SIGSTOP. */ 1056189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1057189ac973SJohn Baldwin 1058189ac973SJohn Baldwin /* Wait for both halves of the fork event to get reported. */ 1059189ac973SJohn Baldwin children[1] = handle_fork_events(children[0], pl); 1060189ac973SJohn Baldwin ATF_REQUIRE(children[1] > 0); 1061189ac973SJohn Baldwin 1062189ac973SJohn Baldwin ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0); 1063189ac973SJohn Baldwin ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0); 1064189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork); 1065189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code); 1066189ac973SJohn Baldwin ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg); 1067189ac973SJohn Baldwin 1068189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1); 1069189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1); 1070189ac973SJohn Baldwin 1071189ac973SJohn Baldwin /* 1072189ac973SJohn Baldwin * The child can't exit until the grandchild reports status, so the 1073189ac973SJohn Baldwin * grandchild should report its exit first to the debugger. 1074189ac973SJohn Baldwin */ 1075189ac973SJohn Baldwin wpid = wait(&status); 1076189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[1]); 1077189ac973SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1078189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 2); 1079189ac973SJohn Baldwin 1080189ac973SJohn Baldwin wpid = wait(&status); 1081189ac973SJohn Baldwin ATF_REQUIRE(wpid == children[0]); 1082189ac973SJohn Baldwin ATF_REQUIRE(WIFEXITED(status)); 1083189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1084189ac973SJohn Baldwin 1085189ac973SJohn Baldwin wpid = wait(&status); 1086189ac973SJohn Baldwin ATF_REQUIRE(wpid == -1); 1087189ac973SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 1088189ac973SJohn Baldwin } 1089189ac973SJohn Baldwin 1090189ac973SJohn Baldwin static void * 1091189ac973SJohn Baldwin simple_thread(void *arg __unused) 1092189ac973SJohn Baldwin { 1093189ac973SJohn Baldwin 1094189ac973SJohn Baldwin pthread_exit(NULL); 1095189ac973SJohn Baldwin } 1096189ac973SJohn Baldwin 1097189ac973SJohn Baldwin /* 1098189ac973SJohn Baldwin * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new 1099189ac973SJohn Baldwin * thread reports the correct value. 1100189ac973SJohn Baldwin */ 1101189ac973SJohn Baldwin ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread); 1102189ac973SJohn Baldwin ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc) 1103189ac973SJohn Baldwin { 1104189ac973SJohn Baldwin struct ptrace_lwpinfo pl; 1105189ac973SJohn Baldwin pid_t fpid, wpid; 1106*e72879e5SJohn Baldwin lwpid_t mainlwp; 1107189ac973SJohn Baldwin int status; 1108189ac973SJohn Baldwin 1109189ac973SJohn Baldwin ATF_REQUIRE((fpid = fork()) != -1); 1110189ac973SJohn Baldwin if (fpid == 0) { 1111189ac973SJohn Baldwin pthread_t thread; 1112189ac973SJohn Baldwin 1113189ac973SJohn Baldwin trace_me(); 1114189ac973SJohn Baldwin 1115189ac973SJohn Baldwin CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, 1116189ac973SJohn Baldwin NULL) == 0); 1117189ac973SJohn Baldwin CHILD_REQUIRE(pthread_join(thread, NULL) == 0); 1118189ac973SJohn Baldwin exit(1); 1119189ac973SJohn Baldwin } 1120189ac973SJohn Baldwin 1121189ac973SJohn Baldwin /* The first wait() should report the stop from SIGSTOP. */ 1122189ac973SJohn Baldwin wpid = waitpid(fpid, &status, 0); 1123189ac973SJohn Baldwin ATF_REQUIRE(wpid == fpid); 1124189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1125189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 1126189ac973SJohn Baldwin 1127189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 1128189ac973SJohn Baldwin sizeof(pl)) != -1); 1129*e72879e5SJohn Baldwin mainlwp = pl.pl_lwpid; 1130189ac973SJohn Baldwin 1131189ac973SJohn Baldwin /* 1132189ac973SJohn Baldwin * Continue the child ignoring the SIGSTOP and tracing all 1133189ac973SJohn Baldwin * system call exits. 1134189ac973SJohn Baldwin */ 1135189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1); 1136189ac973SJohn Baldwin 1137189ac973SJohn Baldwin /* 1138189ac973SJohn Baldwin * Wait for the new thread to arrive. pthread_create() might 1139189ac973SJohn Baldwin * invoke any number of system calls. For now we just wait 1140189ac973SJohn Baldwin * for the new thread to arrive and make sure it reports a 1141189ac973SJohn Baldwin * valid system call code. If ptrace grows thread event 1142189ac973SJohn Baldwin * reporting then this test can be made more precise. 1143189ac973SJohn Baldwin */ 1144189ac973SJohn Baldwin for (;;) { 1145189ac973SJohn Baldwin wpid = waitpid(fpid, &status, 0); 1146189ac973SJohn Baldwin ATF_REQUIRE(wpid == fpid); 1147189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1148189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 1149189ac973SJohn Baldwin 1150189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, 1151189ac973SJohn Baldwin sizeof(pl)) != -1); 1152189ac973SJohn Baldwin ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0); 1153189ac973SJohn Baldwin ATF_REQUIRE(pl.pl_syscall_code != 0); 1154*e72879e5SJohn Baldwin if (pl.pl_lwpid != mainlwp) 1155189ac973SJohn Baldwin /* New thread seen. */ 1156189ac973SJohn Baldwin break; 1157189ac973SJohn Baldwin 1158189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 1159189ac973SJohn Baldwin } 1160189ac973SJohn Baldwin 1161189ac973SJohn Baldwin /* Wait for the child to exit. */ 1162189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 1163189ac973SJohn Baldwin for (;;) { 1164189ac973SJohn Baldwin wpid = waitpid(fpid, &status, 0); 1165189ac973SJohn Baldwin ATF_REQUIRE(wpid == fpid); 1166189ac973SJohn Baldwin if (WIFEXITED(status)) 1167189ac973SJohn Baldwin break; 1168189ac973SJohn Baldwin 1169189ac973SJohn Baldwin ATF_REQUIRE(WIFSTOPPED(status)); 1170189ac973SJohn Baldwin ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); 1171189ac973SJohn Baldwin ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); 1172189ac973SJohn Baldwin } 1173189ac973SJohn Baldwin 1174189ac973SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 1); 1175189ac973SJohn Baldwin 1176189ac973SJohn Baldwin wpid = wait(&status); 1177189ac973SJohn Baldwin ATF_REQUIRE(wpid == -1); 1178189ac973SJohn Baldwin ATF_REQUIRE(errno == ECHILD); 1179189ac973SJohn Baldwin } 1180189ac973SJohn Baldwin 1181c209e3e2SJohn Baldwin ATF_TP_ADD_TCS(tp) 1182c209e3e2SJohn Baldwin { 1183c209e3e2SJohn Baldwin 1184c209e3e2SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me); 1185c209e3e2SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach); 118657c74f5bSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger); 118757c74f5bSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger); 118898685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached); 118998685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached); 119098685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached); 119198685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger); 119298685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, 119398685dc8SJohn Baldwin ptrace__follow_fork_child_detached_unrelated_debugger); 119498685dc8SJohn Baldwin ATF_TP_ADD_TC(tp, 119598685dc8SJohn Baldwin ptrace__follow_fork_parent_detached_unrelated_debugger); 1196368b2b1cSJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__getppid); 1197189ac973SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork); 1198189ac973SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork); 1199189ac973SJohn Baldwin ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread); 1200c209e3e2SJohn Baldwin 1201c209e3e2SJohn Baldwin return (atf_no_error()); 1202c209e3e2SJohn Baldwin } 1203