1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2022 Jessica Clarke <jrtc27@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/errno.h> 30 #include <sys/procctl.h> 31 #include <sys/queue.h> 32 #include <sys/resource.h> 33 #include <sys/sysctl.h> 34 #include <sys/wait.h> 35 36 #include <err.h> 37 #include <errno.h> 38 #include <fcntl.h> 39 #include <signal.h> 40 #include <stdarg.h> 41 #include <stdbool.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <sysexits.h> 46 #include <termios.h> 47 #include <ttyent.h> 48 #include <unistd.h> 49 50 #include "common.h" 51 #include "child.h" 52 53 /* -1: not started, 0: reaped */ 54 static volatile pid_t grandchild_pid = -1; 55 static volatile int grandchild_status; 56 57 static struct pipe_barrier wait_grandchild_barrier; 58 static struct pipe_barrier wait_all_descendants_barrier; 59 60 static void 61 kill_descendants(int sig) 62 { 63 struct procctl_reaper_kill rk; 64 65 rk.rk_sig = sig; 66 rk.rk_flags = 0; 67 procctl(P_PID, getpid(), PROC_REAP_KILL, &rk); 68 } 69 70 static void 71 sigalrm_handler(int sig __unused) 72 { 73 int saved_errno; 74 75 saved_errno = errno; 76 kill_descendants(SIGKILL); 77 errno = saved_errno; 78 } 79 80 static void 81 wait_all_descendants(void) 82 { 83 sigset_t set, oset; 84 85 err_set_exit(NULL); 86 87 /* 88 * We may be run in a context where SIGALRM is blocked; temporarily 89 * unblock so we can SIGKILL. Similarly, SIGCHLD may be blocked, but if 90 * we're waiting on the pipe we need to make sure it's not. 91 */ 92 sigemptyset(&set); 93 sigaddset(&set, SIGALRM); 94 sigaddset(&set, SIGCHLD); 95 sigprocmask(SIG_UNBLOCK, &set, &oset); 96 alarm(KILL_TIMEOUT); 97 pipe_barrier_wait(&wait_all_descendants_barrier); 98 alarm(0); 99 sigprocmask(SIG_SETMASK, &oset, NULL); 100 } 101 102 static void 103 sigchld_handler(int sig __unused) 104 { 105 int status, saved_errno; 106 pid_t pid; 107 108 saved_errno = errno; 109 110 while ((void)(pid = waitpid(-1, &status, WNOHANG)), 111 pid != -1 && pid != 0) { 112 /* NB: No need to check grandchild_pid due to the pid checks */ 113 if (pid == grandchild_pid) { 114 grandchild_status = status; 115 grandchild_pid = 0; 116 pipe_barrier_ready(&wait_grandchild_barrier); 117 } 118 } 119 120 /* 121 * Another process calling kill(..., SIGCHLD) could cause us to get 122 * here before we've spawned the grandchild; only ready when we have no 123 * children if the grandchild has been reaped. 124 */ 125 if (pid == -1 && errno == ECHILD && grandchild_pid == 0) 126 pipe_barrier_ready(&wait_all_descendants_barrier); 127 128 errno = saved_errno; 129 } 130 131 static void 132 exit_signal_handler(int sig) 133 { 134 int saved_errno; 135 136 /* 137 * If we get killed before we've started the grandchild then just exit 138 * with that signal, otherwise kill all our descendants with that 139 * signal and let the main program pick up the grandchild's death. 140 */ 141 if (grandchild_pid == -1) { 142 reproduce_signal_death(sig); 143 exit(EXIT_FAILURE); 144 } 145 146 saved_errno = errno; 147 kill_descendants(sig); 148 errno = saved_errno; 149 } 150 151 static void 152 kill_wait_all_descendants(int sig) 153 { 154 kill_descendants(sig); 155 wait_all_descendants(); 156 } 157 158 static void 159 kill_wait_all_descendants_err_exit(int eval __unused) 160 { 161 kill_wait_all_descendants(SIGTERM); 162 } 163 164 static void __dead2 165 grandchild_run(const char **argv, const sigset_t *oset) 166 { 167 sig_t orig; 168 169 /* Restore signals */ 170 orig = signal(SIGALRM, SIG_DFL); 171 if (orig == SIG_ERR) 172 err(EX_OSERR, "could not restore SIGALRM"); 173 orig = signal(SIGCHLD, SIG_DFL); 174 if (orig == SIG_ERR) 175 err(EX_OSERR, "could not restore SIGCHLD"); 176 orig = signal(SIGTERM, SIG_DFL); 177 if (orig == SIG_ERR) 178 err(EX_OSERR, "could not restore SIGTERM"); 179 orig = signal(SIGINT, SIG_DFL); 180 if (orig == SIG_ERR) 181 err(EX_OSERR, "could not restore SIGINT"); 182 orig = signal(SIGQUIT, SIG_DFL); 183 if (orig == SIG_ERR) 184 err(EX_OSERR, "could not restore SIGQUIT"); 185 orig = signal(SIGPIPE, SIG_DFL); 186 if (orig == SIG_ERR) 187 err(EX_OSERR, "could not restore SIGPIPE"); 188 orig = signal(SIGTTOU, SIG_DFL); 189 if (orig == SIG_ERR) 190 err(EX_OSERR, "could not restore SIGTTOU"); 191 192 /* Now safe to unmask signals */ 193 sigprocmask(SIG_SETMASK, oset, NULL); 194 195 /* Only run with stdin/stdout/stderr */ 196 closefrom(3); 197 198 /* Ready to execute the requested program */ 199 execvp(argv[0], __DECONST(char * const *, argv)); 200 err(EX_OSERR, "cannot execvp %s", argv[0]); 201 } 202 203 static int 204 wait_grandchild_descendants(void) 205 { 206 pipe_barrier_wait(&wait_grandchild_barrier); 207 208 /* 209 * Once the grandchild itself has exited, kill any lingering 210 * descendants and wait until we've reaped them all. 211 */ 212 kill_wait_all_descendants(SIGTERM); 213 214 if (grandchild_pid != 0) 215 errx(EX_SOFTWARE, "failed to reap grandchild"); 216 217 return (grandchild_status); 218 } 219 220 void 221 child_leader_run(const char *name, int fd, bool new_session, const char **argv, 222 const sigset_t *oset, struct pipe_barrier *start_children_barrier) 223 { 224 struct pipe_barrier start_grandchild_barrier; 225 pid_t pid, sid, pgid; 226 struct sigaction sa; 227 int error, status; 228 sigset_t set; 229 230 setproctitle("%s [%s]", getprogname(), name); 231 232 error = procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL); 233 if (error != 0) 234 err(EX_OSERR, "could not acquire reaper status"); 235 236 /* 237 * Set up our own signal handlers for everything the parent overrides 238 * other than SIGPIPE and SIGTTOU which we leave as ignored, since we 239 * also use pipe-based synchronisation and want to be able to print 240 * errors. 241 */ 242 sa.sa_flags = SA_RESTART; 243 sa.sa_handler = sigchld_handler; 244 sigfillset(&sa.sa_mask); 245 error = sigaction(SIGCHLD, &sa, NULL); 246 if (error != 0) 247 err(EX_OSERR, "could not enable SIGCHLD handler"); 248 sa.sa_handler = sigalrm_handler; 249 error = sigaction(SIGALRM, &sa, NULL); 250 if (error != 0) 251 err(EX_OSERR, "could not enable SIGALRM handler"); 252 sa.sa_handler = exit_signal_handler; 253 error = sigaction(SIGTERM, &sa, NULL); 254 if (error != 0) 255 err(EX_OSERR, "could not enable SIGTERM handler"); 256 error = sigaction(SIGINT, &sa, NULL); 257 if (error != 0) 258 err(EX_OSERR, "could not enable SIGINT handler"); 259 error = sigaction(SIGQUIT, &sa, NULL); 260 if (error != 0) 261 err(EX_OSERR, "could not enable SIGQUIT handler"); 262 263 /* 264 * Now safe to unmask signals. Note that creating the barriers used by 265 * the SIGCHLD handler with signals unmasked is safe since they won't 266 * be used if the grandchild hasn't been forked (and reaped), which 267 * comes later. 268 */ 269 sigprocmask(SIG_SETMASK, oset, NULL); 270 271 error = pipe_barrier_init(&start_grandchild_barrier); 272 if (error != 0) 273 err(EX_OSERR, "could not create start grandchild barrier"); 274 275 error = pipe_barrier_init(&wait_grandchild_barrier); 276 if (error != 0) 277 err(EX_OSERR, "could not create wait grandchild barrier"); 278 279 error = pipe_barrier_init(&wait_all_descendants_barrier); 280 if (error != 0) 281 err(EX_OSERR, "could not create wait all descendants barrier"); 282 283 /* 284 * Create a new session if this is on a different terminal to 285 * the current one, otherwise just create a new process group to keep 286 * things as similar as possible between the two cases. 287 */ 288 if (new_session) { 289 sid = setsid(); 290 pgid = sid; 291 if (sid == -1) 292 err(EX_OSERR, "could not create session"); 293 } else { 294 sid = -1; 295 pgid = getpid(); 296 error = setpgid(0, pgid); 297 if (error == -1) 298 err(EX_OSERR, "could not create process group"); 299 } 300 301 /* Wait until parent is ready for us to start */ 302 pipe_barrier_destroy_ready(start_children_barrier); 303 pipe_barrier_wait(start_children_barrier); 304 305 /* 306 * Use the console for stdin/stdout/stderr. 307 * 308 * NB: dup2(2) is a no-op if the two fds are equal, and the call to 309 * closefrom(2) later in the grandchild will close the fd if it isn't 310 * one of stdin/stdout/stderr already. This means we do not need to 311 * handle that special case differently. 312 */ 313 error = dup2(fd, STDIN_FILENO); 314 if (error == -1) 315 err(EX_IOERR, "could not dup %s to stdin", name); 316 error = dup2(fd, STDOUT_FILENO); 317 if (error == -1) 318 err(EX_IOERR, "could not dup %s to stdout", name); 319 error = dup2(fd, STDERR_FILENO); 320 if (error == -1) 321 err(EX_IOERR, "could not dup %s to stderr", name); 322 323 /* 324 * If we created a new session, make the console our controlling 325 * terminal. Either way, also make this the foreground process group. 326 */ 327 if (new_session) { 328 error = tcsetsid(STDIN_FILENO, sid); 329 if (error != 0) 330 err(EX_IOERR, "could not set session for %s", name); 331 } else { 332 error = tcsetpgrp(STDIN_FILENO, pgid); 333 if (error != 0) 334 err(EX_IOERR, "could not set process group for %s", 335 name); 336 } 337 338 /* 339 * Temporarily block signals again; forking, setting grandchild_pid and 340 * calling err_set_exit need to all be atomic for similar reasons as 341 * the parent when forking us. 342 */ 343 sigfillset(&set); 344 sigprocmask(SIG_BLOCK, &set, NULL); 345 pid = fork(); 346 if (pid == -1) 347 err(EX_OSERR, "could not fork"); 348 349 if (pid == 0) { 350 /* 351 * We need to destroy the ready ends so we don't block these 352 * child leader-only self-pipes, and might as well destroy the 353 * wait ends too given we're not going to use them. 354 */ 355 pipe_barrier_destroy(&wait_grandchild_barrier); 356 pipe_barrier_destroy(&wait_all_descendants_barrier); 357 358 /* Wait until the parent has put us in a new process group */ 359 pipe_barrier_destroy_ready(&start_grandchild_barrier); 360 pipe_barrier_wait(&start_grandchild_barrier); 361 grandchild_run(argv, oset); 362 } 363 364 grandchild_pid = pid; 365 366 /* 367 * Now the grandchild exists make sure to clean it up, and any of its 368 * descendants, on exit. 369 */ 370 err_set_exit(kill_wait_all_descendants_err_exit); 371 372 sigprocmask(SIG_SETMASK, oset, NULL); 373 374 /* Start the grandchild and wait for it and its descendants to exit */ 375 pipe_barrier_ready(&start_grandchild_barrier); 376 377 status = wait_grandchild_descendants(); 378 379 if (WIFSIGNALED(status)) 380 reproduce_signal_death(WTERMSIG(status)); 381 382 if (WIFEXITED(status)) 383 exit(WEXITSTATUS(status)); 384 385 exit(EXIT_FAILURE); 386 } 387