From 77bc87e6f9042000a56091539ce2ca66660cd068 Mon Sep 17 00:00:00 2001 From: Earl Chew Date: Wed, 3 Feb 2021 18:51:14 -0800 Subject: [PATCH] [bubblewrap] Propagate SIGTERM and SIGINT to child --- bubblewrap.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/bubblewrap.c b/bubblewrap.c index b3d52bc7..c0855471 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -286,6 +286,25 @@ handle_die_with_parent (void) die_with_error ("prctl"); } +static void +gate_signals (int action, sigset_t *prevmask) +{ + sigset_t mask; + + /* When unblocking, only restore if not previously blocked. */ + + sigemptyset (&mask); + + if (action == SIG_BLOCK || !sigismember (prevmask, SIGINT)) + sigaddset (&mask, SIGINT); + + if (action == SIG_BLOCK || !sigismember (prevmask, SIGTERM)) + sigaddset (&mask, SIGTERM); + + if (sigprocmask (action, &mask, prevmask) == -1) + die_with_error ("sigprocmask"); +} + static void block_sigchild (void) { @@ -421,6 +440,8 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd) sigemptyset (&mask); sigaddset (&mask, SIGCHLD); + sigaddset (&mask, SIGINT); + sigaddset (&mask, SIGTERM); signal_fd = signalfd (-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK); if (signal_fd == -1) @@ -460,12 +481,17 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd) } /* We need to read the signal_fd, or it will keep polling as read, - * however we ignore the details as we get them from waitpid + * however we ignore the details for SIGCHLD as we get them from waitpid * below anyway */ s = read (signal_fd, &fdsi, sizeof (struct signalfd_siginfo)); if (s == -1 && errno != EINTR && errno != EAGAIN) die_with_error ("read signalfd"); + /* Propagate signal to child so that it will take the correct + * action. This avoids the parent terminating, leaving an orphan. */ + if (fdsi.ssi_signo != SIGCHLD && kill (child_pid, fdsi.ssi_signo)) + die_with_error ("kill child"); + /* We may actually get several sigchld compressed into one SIGCHLD, so we have to handle all of them. */ while ((died_pid = waitpid (-1, &died_status, WNOHANG)) > 0) @@ -2230,6 +2256,7 @@ main (int argc, struct sock_fprog seccomp_prog; cleanup_free char *args_data = NULL; int intermediate_pids_sockets[2] = {-1, -1}; + sigset_t sigmask; /* Handle --version early on before we try to acquire/drop * any capabilities so it works in a build environment; @@ -2397,6 +2424,9 @@ main (int argc, /* We block sigchild here so that we can use signalfd in the monitor. */ block_sigchild (); + /* We block other signals here to avoid leaving an orphan. */ + gate_signals (SIG_BLOCK, &sigmask); + clone_flags = SIGCHLD | CLONE_NEWNS; if (opt_unshare_user) clone_flags |= CLONE_NEWUSER; @@ -2544,6 +2574,9 @@ main (int argc, return monitor_child (event_fd, pid, setup_finished_pipe[0]); } + /* Unblock other signals here to receive signals from the parent. */ + gate_signals (SIG_UNBLOCK, &sigmask); + if (opt_pidns_fd > 0) { if (setns (opt_pidns_fd, CLONE_NEWPID) != 0)