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 */
54static volatile pid_t grandchild_pid = -1;
55static volatile int grandchild_status;
56
57static struct pipe_barrier wait_grandchild_barrier;
58static struct pipe_barrier wait_all_descendants_barrier;
59
60static void
61kill_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
70static void
71sigalrm_handler(int sig __unused)
72{
73	int saved_errno;
74
75	saved_errno = errno;
76	kill_descendants(SIGKILL);
77	errno = saved_errno;
78}
79
80static void
81wait_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
102static void
103sigchld_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
131static void
132exit_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
151static void
152kill_wait_all_descendants(int sig)
153{
154	kill_descendants(sig);
155	wait_all_descendants();
156}
157
158static void
159kill_wait_all_descendants_err_exit(int eval __unused)
160{
161	kill_wait_all_descendants(SIGTERM);
162}
163
164static void __dead2
165grandchild_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
203static int
204wait_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
220void
221child_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