1332740Skib/*- 2332740Skib * Copyright (c) 2018 Thomas Munro 3332740Skib * All rights reserved. 4332740Skib * 5332740Skib * Redistribution and use in source and binary forms, with or without 6332740Skib * modification, are permitted provided that the following conditions 7332740Skib * are met: 8332740Skib * 1. Redistributions of source code must retain the above copyright 9332740Skib * notice, this list of conditions and the following disclaimer. 10332740Skib * 2. Redistributions in binary form must reproduce the above copyright 11332740Skib * notice, this list of conditions and the following disclaimer in the 12332740Skib * documentation and/or other materials provided with the distribution. 13332740Skib * 14332740Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15332740Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16332740Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17332740Skib * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18332740Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19332740Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20332740Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21332740Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22332740Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23332740Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24332740Skib * SUCH DAMAGE. 25332740Skib */ 26332740Skib 27332740Skib#include <sys/cdefs.h> 28332740Skib__FBSDID("$FreeBSD: stable/11/tests/sys/kern/pdeathsig.c 351506 2019-08-26 08:08:15Z kib $"); 29332740Skib 30332740Skib#include <assert.h> 31332740Skib#include <atf-c.h> 32332740Skib#include <errno.h> 33332740Skib#include <signal.h> 34332740Skib#include <stdio.h> 35332740Skib#include <stdlib.h> 36332740Skib#include <time.h> 37332740Skib#include <unistd.h> 38332740Skib#include <sys/procctl.h> 39332740Skib#include <sys/ptrace.h> 40332740Skib#include <sys/signal.h> 41332740Skib#include <sys/types.h> 42332740Skib 43332740Skibstatic void 44332740Skibdummy_signal_handler(int signum) 45332740Skib{ 46332740Skib} 47332740Skib 48332740SkibATF_TC_WITHOUT_HEAD(arg_validation); 49332740SkibATF_TC_BODY(arg_validation, tc) 50332740Skib{ 51332740Skib int signum; 52332740Skib int rc; 53332740Skib 54332740Skib /* bad signal */ 55332740Skib signum = 8888; 56333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); 57332740Skib ATF_CHECK_EQ(-1, rc); 58332740Skib ATF_CHECK_EQ(EINVAL, errno); 59332740Skib 60332740Skib /* bad id type */ 61332740Skib signum = SIGINFO; 62333162Skib rc = procctl(8888, 0, PROC_PDEATHSIG_CTL, &signum); 63332740Skib ATF_CHECK_EQ(-1, rc); 64332740Skib ATF_CHECK_EQ(EINVAL, errno); 65332740Skib 66332740Skib /* bad id (pid that doesn't match mine or zero) */ 67332740Skib signum = SIGINFO; 68332740Skib rc = procctl(P_PID, (((getpid() + 1) % 10) + 100), 69333162Skib PROC_PDEATHSIG_CTL, &signum); 70332740Skib ATF_CHECK_EQ(-1, rc); 71332740Skib ATF_CHECK_EQ(EINVAL, errno); 72332740Skib 73332740Skib /* null pointer */ 74332740Skib signum = SIGINFO; 75333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, NULL); 76332740Skib ATF_CHECK_EQ(-1, rc); 77332740Skib ATF_CHECK_EQ(EFAULT, errno); 78332740Skib 79332740Skib /* good (pid == 0) */ 80332740Skib signum = SIGINFO; 81333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); 82332740Skib ATF_CHECK_EQ(0, rc); 83332740Skib 84332740Skib /* good (pid == my pid) */ 85332740Skib signum = SIGINFO; 86333162Skib rc = procctl(P_PID, getpid(), PROC_PDEATHSIG_CTL, &signum); 87332740Skib ATF_CHECK_EQ(0, rc); 88332740Skib 89332740Skib /* check that we can read the signal number back */ 90332740Skib signum = 0xdeadbeef; 91333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &signum); 92332740Skib ATF_CHECK_EQ(0, rc); 93332740Skib ATF_CHECK_EQ(SIGINFO, signum); 94332740Skib} 95332740Skib 96332740SkibATF_TC_WITHOUT_HEAD(fork_no_inherit); 97332740SkibATF_TC_BODY(fork_no_inherit, tc) 98332740Skib{ 99332740Skib int status; 100332740Skib int signum; 101332740Skib int rc; 102332740Skib 103332740Skib /* request a signal on parent death in the parent */ 104332740Skib signum = SIGINFO; 105333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); 106332740Skib 107332740Skib rc = fork(); 108332740Skib ATF_REQUIRE(rc != -1); 109332740Skib if (rc == 0) { 110332740Skib /* check that we didn't inherit the setting */ 111332740Skib signum = 0xdeadbeef; 112333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &signum); 113332740Skib assert(rc == 0); 114332740Skib assert(signum == 0); 115332740Skib _exit(0); 116332740Skib } 117332740Skib 118332740Skib /* wait for the child to exit successfully */ 119332740Skib waitpid(rc, &status, 0); 120332740Skib ATF_CHECK_EQ(0, status); 121332740Skib} 122332740Skib 123332740SkibATF_TC_WITHOUT_HEAD(exec_inherit); 124332740SkibATF_TC_BODY(exec_inherit, tc) 125332740Skib{ 126332740Skib int status; 127332740Skib int rc; 128332740Skib 129332740Skib rc = fork(); 130332740Skib ATF_REQUIRE(rc != -1); 131332740Skib if (rc == 0) { 132332740Skib char exec_path[1024]; 133332740Skib int signum; 134332740Skib 135332740Skib /* compute the path of the helper executable */ 136332740Skib snprintf(exec_path, sizeof(exec_path), "%s/pdeathsig_helper", 137332740Skib atf_tc_get_config_var(tc, "srcdir")); 138332740Skib 139332740Skib /* request a signal on parent death and register a handler */ 140332740Skib signum = SIGINFO; 141333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); 142332740Skib assert(rc == 0); 143332740Skib 144332740Skib /* execute helper program: it asserts that it has the setting */ 145332740Skib rc = execl(exec_path, exec_path, NULL); 146332740Skib assert(rc == 0); 147332740Skib _exit(0); 148332740Skib } 149332740Skib 150332740Skib /* wait for the child to exit successfully */ 151332740Skib waitpid(rc, &status, 0); 152332740Skib ATF_CHECK_EQ(0, status); 153332740Skib} 154332740Skib 155332740SkibATF_TC_WITHOUT_HEAD(signal_delivered); 156332740SkibATF_TC_BODY(signal_delivered, tc) 157332740Skib{ 158332740Skib sigset_t sigset; 159332740Skib int signum; 160332740Skib int rc; 161332740Skib int pipe_ca[2]; 162332740Skib int pipe_cb[2]; 163332740Skib char buffer; 164332740Skib 165332740Skib rc = pipe(pipe_ca); 166332740Skib ATF_REQUIRE(rc == 0); 167332740Skib rc = pipe(pipe_cb); 168332740Skib ATF_REQUIRE(rc == 0); 169332740Skib 170332740Skib rc = fork(); 171332740Skib ATF_REQUIRE(rc != -1); 172332740Skib if (rc == 0) { 173332740Skib rc = fork(); 174332740Skib assert(rc >= 0); 175332740Skib if (rc == 0) { 176332740Skib /* process C */ 177332740Skib signum = SIGINFO; 178332740Skib 179332740Skib /* block signals so we can handle them synchronously */ 180332740Skib rc = sigfillset(&sigset); 181332740Skib assert(rc == 0); 182332740Skib rc = sigprocmask(SIG_SETMASK, &sigset, NULL); 183332740Skib assert(rc == 0); 184332740Skib 185332740Skib /* register a dummy handler or the kernel will not queue it */ 186332740Skib signal(signum, dummy_signal_handler); 187332740Skib 188332740Skib /* request a signal on death of our parent B */ 189333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); 190332740Skib assert(rc == 0); 191332740Skib 192332740Skib /* tell B that we're ready for it to exit now */ 193332740Skib rc = write(pipe_cb[1], ".", 1); 194332740Skib assert(rc == 1); 195332740Skib 196332740Skib /* wait for B to die and signal us... */ 197332740Skib signum = 0xdeadbeef; 198332740Skib rc = sigwait(&sigset, &signum); 199332740Skib assert(rc == 0); 200332740Skib assert(signum == SIGINFO); 201332740Skib 202332740Skib /* tell A the test passed */ 203332740Skib rc = write(pipe_ca[1], ".", 1); 204332740Skib assert(rc == 1); 205332740Skib _exit(0); 206332740Skib } 207332740Skib 208332740Skib /* process B */ 209332740Skib 210332740Skib /* wait for C to tell us it is ready for us to exit */ 211332740Skib rc = read(pipe_cb[0], &buffer, 1); 212332740Skib assert(rc == 1); 213332740Skib 214332740Skib /* now we exit so that C gets a signal */ 215332740Skib _exit(0); 216332740Skib } 217332740Skib /* process A */ 218332740Skib 219332740Skib /* wait for C to tell us the test passed */ 220332740Skib rc = read(pipe_ca[0], &buffer, 1); 221332740Skib ATF_CHECK_EQ(1, rc); 222332740Skib} 223332740Skib 224332740SkibATF_TC_WITHOUT_HEAD(signal_delivered_ptrace); 225332740SkibATF_TC_BODY(signal_delivered_ptrace, tc) 226332740Skib{ 227332740Skib sigset_t sigset; 228332740Skib int signum; 229332740Skib int rc; 230332740Skib int pipe_ca[2]; 231332740Skib int pipe_db[2]; 232351506Skib int pipe_cd[2]; 233332740Skib char buffer; 234332740Skib int status; 235332740Skib 236332740Skib rc = pipe(pipe_ca); 237332740Skib ATF_REQUIRE(rc == 0); 238332740Skib rc = pipe(pipe_db); 239332740Skib ATF_REQUIRE(rc == 0); 240351506Skib rc = pipe(pipe_cd); 241351506Skib assert(rc == 0); 242332740Skib 243332740Skib rc = fork(); 244332740Skib ATF_REQUIRE(rc != -1); 245332740Skib if (rc == 0) { 246332740Skib pid_t c_pid; 247332740Skib 248332740Skib /* process B */ 249332740Skib 250332740Skib rc = fork(); 251332740Skib assert(rc >= 0); 252332740Skib if (rc == 0) { 253332740Skib /* process C */ 254332740Skib signum = SIGINFO; 255332740Skib 256332740Skib /* block signals so we can handle them synchronously */ 257332740Skib rc = sigfillset(&sigset); 258332740Skib assert(rc == 0); 259332740Skib rc = sigprocmask(SIG_SETMASK, &sigset, NULL); 260332740Skib assert(rc == 0); 261332740Skib 262332740Skib /* register a dummy handler or the kernel will not queue it */ 263332740Skib signal(signum, dummy_signal_handler); 264332740Skib 265332740Skib /* request a signal on parent death and register a handler */ 266333162Skib rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); 267332740Skib assert(rc == 0); 268332740Skib 269351506Skib rc = write(pipe_cd[1], "x", 1); 270351506Skib assert(rc == 1); 271351506Skib 272332740Skib /* wait for B to die and signal us... */ 273332740Skib signum = 0xdeadbeef; 274332740Skib rc = sigwait(&sigset, &signum); 275332740Skib assert(rc == 0); 276332740Skib assert(signum == SIGINFO); 277332740Skib 278332740Skib /* tell A the test passed */ 279332740Skib rc = write(pipe_ca[1], ".", 1); 280332740Skib assert(rc == 1); 281332740Skib _exit(0); 282332740Skib } 283332740Skib c_pid = rc; 284332740Skib 285332740Skib 286332740Skib /* fork another process to ptrace C */ 287332740Skib rc = fork(); 288332740Skib assert(rc >= 0); 289332740Skib if (rc == 0) { 290332740Skib 291332740Skib /* process D */ 292332740Skib rc = ptrace(PT_ATTACH, c_pid, 0, 0); 293332740Skib assert(rc == 0); 294332740Skib 295332740Skib waitpid(c_pid, &status, 0); 296332740Skib assert(WIFSTOPPED(status)); 297332740Skib assert(WSTOPSIG(status) == SIGSTOP); 298332740Skib 299332740Skib rc = ptrace(PT_CONTINUE, c_pid, (caddr_t) 1, 0); 300332740Skib assert(rc == 0); 301332740Skib 302351506Skib rc = read(pipe_cd[0], &buffer, 1); 303351506Skib assert(rc == 1); 304351506Skib 305332740Skib /* tell B that we're ready for it to exit now */ 306332740Skib rc = write(pipe_db[1], ".", 1); 307332740Skib assert(rc == 1); 308332740Skib 309332740Skib waitpid(c_pid, &status, 0); 310332740Skib assert(WIFSTOPPED(status)); 311332740Skib assert(WSTOPSIG(status) == SIGINFO); 312332740Skib 313332740Skib rc = ptrace(PT_CONTINUE, c_pid, (caddr_t) 1, 314332740Skib WSTOPSIG(status)); 315332740Skib assert(rc == 0); 316332740Skib 317351505Skib waitpid(c_pid, &status, 0); 318351505Skib if (!WIFEXITED(status)) 319351505Skib ptrace(PT_DETACH, c_pid, 0, 0); 320332740Skib 321332740Skib _exit(0); 322332740Skib } 323332740Skib 324332740Skib /* wait for D to tell us it is ready for us to exit */ 325332740Skib rc = read(pipe_db[0], &buffer, 1); 326332740Skib assert(rc == 1); 327332740Skib 328332740Skib /* now we exit so that C gets a signal */ 329332740Skib _exit(0); 330332740Skib } 331332740Skib 332332740Skib /* process A */ 333332740Skib 334332740Skib /* wait for C to tell us the test passed */ 335332740Skib rc = read(pipe_ca[0], &buffer, 1); 336332740Skib ATF_CHECK_EQ(1, rc); 337332740Skib} 338332740Skib 339332740SkibATF_TP_ADD_TCS(tp) 340332740Skib{ 341332740Skib ATF_TP_ADD_TC(tp, arg_validation); 342332740Skib ATF_TP_ADD_TC(tp, fork_no_inherit); 343332740Skib ATF_TP_ADD_TC(tp, exec_inherit); 344332740Skib ATF_TP_ADD_TC(tp, signal_delivered); 345332740Skib ATF_TP_ADD_TC(tp, signal_delivered_ptrace); 346332740Skib return (atf_no_error()); 347332740Skib} 348