84b277
From f0fdbdb003cb3e8d8188c1c01701b510505b5b8b Mon Sep 17 00:00:00 2001
61b3c9
From: Lennart Poettering <lennart@poettering.net>
61b3c9
Date: Wed, 27 Aug 2014 21:42:20 +0200
61b3c9
Subject: [PATCH] util: fix minimal race where we might miss SIGTERMs when
61b3c9
 forking off an agent
61b3c9
61b3c9
Before forking, block all signals, and unblock them afterwards. This way
61b3c9
the child will have them blocked, and we won't lose them.
61b3c9
61b3c9
(cherry picked from commit 8a7c93d858c342744adf481565d8bb03b9713dcf)
61b3c9
61b3c9
Related: #1134818
61b3c9
---
84b277
 src/shared/util.c | 35 +++++++++++++++++++++++------------
84b277
 1 file changed, 23 insertions(+), 12 deletions(-)
61b3c9
61b3c9
diff --git a/src/shared/util.c b/src/shared/util.c
84b277
index e4448ff..9f25b15 100644
61b3c9
--- a/src/shared/util.c
61b3c9
+++ b/src/shared/util.c
84b277
@@ -5002,9 +5002,9 @@ int fd_inc_rcvbuf(int fd, size_t n) {
61b3c9
 }
61b3c9
 
61b3c9
 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
61b3c9
-        pid_t parent_pid, agent_pid;
61b3c9
-        int fd;
61b3c9
         bool stdout_is_tty, stderr_is_tty;
61b3c9
+        pid_t parent_pid, agent_pid;
61b3c9
+        sigset_t ss, saved_ss;
61b3c9
         unsigned n, i;
61b3c9
         va_list ap;
61b3c9
         char **l;
84b277
@@ -5012,16 +5012,25 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
61b3c9
         assert(pid);
61b3c9
         assert(path);
61b3c9
 
61b3c9
-        parent_pid = getpid();
61b3c9
-
61b3c9
         /* Spawns a temporary TTY agent, making sure it goes away when
61b3c9
          * we go away */
61b3c9
 
61b3c9
+        parent_pid = getpid();
61b3c9
+
61b3c9
+        /* First we temporarily block all signals, so that the new
61b3c9
+         * child has them blocked initially. This way, we can be sure
61b3c9
+         * that SIGTERMs are not lost we might send to the agent. */
61b3c9
+        assert_se(sigfillset(&ss) >= 0);
61b3c9
+        assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
61b3c9
+
61b3c9
         agent_pid = fork();
61b3c9
-        if (agent_pid < 0)
61b3c9
+        if (agent_pid < 0) {
61b3c9
+                assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
61b3c9
                 return -errno;
61b3c9
+        }
61b3c9
 
61b3c9
         if (agent_pid != 0) {
61b3c9
+                assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
61b3c9
                 *pid = agent_pid;
61b3c9
                 return 0;
61b3c9
         }
84b277
@@ -5032,24 +5041,26 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
61b3c9
         if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
61b3c9
                 _exit(EXIT_FAILURE);
61b3c9
 
61b3c9
+        /* Make sure we actually can kill the agent, if we need to, in
61b3c9
+         * case somebody invoked us from a shell script that trapped
61b3c9
+         * SIGTERM or so... */
61b3c9
+        reset_all_signal_handlers();
61b3c9
+        reset_signal_mask();
61b3c9
+
61b3c9
         /* Check whether our parent died before we were able
61b3c9
-         * to set the death signal */
61b3c9
+         * to set the death signal and unblock the signals */
61b3c9
         if (getppid() != parent_pid)
61b3c9
                 _exit(EXIT_SUCCESS);
61b3c9
 
84b277
         /* Don't leak fds to the agent */
84b277
         close_all_fds(except, n_except);
84b277
 
84b277
-        /* Make sure we actually can kill the agent, if we need to, in
84b277
-         * case somebody invoked us from a shell script that trapped
84b277
-         * SIGTERM or so... */
84b277
-        reset_all_signal_handlers();
84b277
-        reset_signal_mask();
84b277
-
84b277
         stdout_is_tty = isatty(STDOUT_FILENO);
61b3c9
         stderr_is_tty = isatty(STDERR_FILENO);
61b3c9
 
61b3c9
         if (!stdout_is_tty || !stderr_is_tty) {
61b3c9
+                int fd;
61b3c9
+
61b3c9
                 /* Detach from stdout/stderr. and reopen
61b3c9
                  * /dev/tty for them. This is important to
61b3c9
                  * ensure that when systemctl is started via