2 * Copyright (c) 2018 Thomas Munro
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
38 #include <sys/procctl.h>
39 #include <sys/ptrace.h>
40 #include <sys/signal.h>
41 #include <sys/types.h>
44 dummy_signal_handler(int signum)
48 ATF_TC_WITHOUT_HEAD(arg_validation);
49 ATF_TC_BODY(arg_validation, tc)
56 rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
58 ATF_CHECK_EQ(EINVAL, errno);
62 rc = procctl(8888, 0, PROC_PDEATHSIG_CTL, &signum);
64 ATF_CHECK_EQ(EINVAL, errno);
66 /* bad id (pid that doesn't match mine or zero) */
68 rc = procctl(P_PID, (((getpid() + 1) % 10) + 100),
69 PROC_PDEATHSIG_CTL, &signum);
71 ATF_CHECK_EQ(EINVAL, errno);
75 rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, NULL);
77 ATF_CHECK_EQ(EFAULT, errno);
81 rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
84 /* good (pid == my pid) */
86 rc = procctl(P_PID, getpid(), PROC_PDEATHSIG_CTL, &signum);
89 /* check that we can read the signal number back */
91 rc = procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &signum);
93 ATF_CHECK_EQ(SIGINFO, signum);
96 ATF_TC_WITHOUT_HEAD(fork_no_inherit);
97 ATF_TC_BODY(fork_no_inherit, tc)
103 /* request a signal on parent death in the parent */
105 rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
108 ATF_REQUIRE(rc != -1);
110 /* check that we didn't inherit the setting */
112 rc = procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &signum);
118 /* wait for the child to exit successfully */
119 waitpid(rc, &status, 0);
120 ATF_CHECK_EQ(0, status);
123 ATF_TC_WITHOUT_HEAD(exec_inherit);
124 ATF_TC_BODY(exec_inherit, tc)
130 ATF_REQUIRE(rc != -1);
132 char exec_path[1024];
135 /* compute the path of the helper executable */
136 snprintf(exec_path, sizeof(exec_path), "%s/pdeathsig_helper",
137 atf_tc_get_config_var(tc, "srcdir"));
139 /* request a signal on parent death and register a handler */
141 rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
144 /* execute helper program: it asserts that it has the setting */
145 rc = execl(exec_path, exec_path, NULL);
150 /* wait for the child to exit successfully */
151 waitpid(rc, &status, 0);
152 ATF_CHECK_EQ(0, status);
155 ATF_TC_WITHOUT_HEAD(signal_delivered);
156 ATF_TC_BODY(signal_delivered, tc)
166 ATF_REQUIRE(rc == 0);
168 ATF_REQUIRE(rc == 0);
171 ATF_REQUIRE(rc != -1);
179 /* block signals so we can handle them synchronously */
180 rc = sigfillset(&sigset);
182 rc = sigprocmask(SIG_SETMASK, &sigset, NULL);
185 /* register a dummy handler or the kernel will not queue it */
186 signal(signum, dummy_signal_handler);
188 /* request a signal on death of our parent B */
189 rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
192 /* tell B that we're ready for it to exit now */
193 rc = write(pipe_cb[1], ".", 1);
196 /* wait for B to die and signal us... */
198 rc = sigwait(&sigset, &signum);
200 assert(signum == SIGINFO);
202 /* tell A the test passed */
203 rc = write(pipe_ca[1], ".", 1);
210 /* wait for C to tell us it is ready for us to exit */
211 rc = read(pipe_cb[0], &buffer, 1);
214 /* now we exit so that C gets a signal */
219 /* wait for C to tell us the test passed */
220 rc = read(pipe_ca[0], &buffer, 1);
224 ATF_TC_WITHOUT_HEAD(signal_delivered_ptrace);
225 ATF_TC_BODY(signal_delivered_ptrace, tc)
236 ATF_REQUIRE(rc == 0);
238 ATF_REQUIRE(rc == 0);
241 ATF_REQUIRE(rc != -1);
253 /* block signals so we can handle them synchronously */
254 rc = sigfillset(&sigset);
256 rc = sigprocmask(SIG_SETMASK, &sigset, NULL);
259 /* register a dummy handler or the kernel will not queue it */
260 signal(signum, dummy_signal_handler);
262 /* request a signal on parent death and register a handler */
263 rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
266 /* wait for B to die and signal us... */
268 rc = sigwait(&sigset, &signum);
270 assert(signum == SIGINFO);
272 /* tell A the test passed */
273 rc = write(pipe_ca[1], ".", 1);
280 /* fork another process to ptrace C */
286 rc = ptrace(PT_ATTACH, c_pid, 0, 0);
289 waitpid(c_pid, &status, 0);
290 assert(WIFSTOPPED(status));
291 assert(WSTOPSIG(status) == SIGSTOP);
293 rc = ptrace(PT_CONTINUE, c_pid, (caddr_t) 1, 0);
296 /* tell B that we're ready for it to exit now */
297 rc = write(pipe_db[1], ".", 1);
300 waitpid(c_pid, &status, 0);
301 assert(WIFSTOPPED(status));
302 assert(WSTOPSIG(status) == SIGINFO);
304 rc = ptrace(PT_CONTINUE, c_pid, (caddr_t) 1,
308 ptrace(PT_DETACH, c_pid, 0, 0);
313 /* wait for D to tell us it is ready for us to exit */
314 rc = read(pipe_db[0], &buffer, 1);
317 /* now we exit so that C gets a signal */
323 /* wait for C to tell us the test passed */
324 rc = read(pipe_ca[0], &buffer, 1);
330 ATF_TP_ADD_TC(tp, arg_validation);
331 ATF_TP_ADD_TC(tp, fork_no_inherit);
332 ATF_TP_ADD_TC(tp, exec_inherit);
333 ATF_TP_ADD_TC(tp, signal_delivered);
334 ATF_TP_ADD_TC(tp, signal_delivered_ptrace);
335 return (atf_no_error());