]> granicus.if.org Git - sudo/commitdiff
Save signal state before changing handlers and restore before
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 2 Feb 2011 17:44:35 +0000 (12:44 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 2 Feb 2011 17:44:35 +0000 (12:44 -0500)
we execute the command.

src/exec.c
src/exec_pty.c
src/sudo.h

index 5969ed7d3fefadd2864d7547b6c19c6686562d2a..f3038a331309518d73fecd426e3e6c1e3bfd724d 100644 (file)
@@ -128,6 +128,7 @@ static int fork_cmnd(struct command_details *details, char *argv[],
        close(signal_pipe[0]);
        close(signal_pipe[1]);
        fcntl(sv[1], F_SETFD, FD_CLOEXEC);
+       restore_signals();
        if (exec_setup(details, NULL, -1) == TRUE) {
            /* headed for execve() */
            if (details->closefrom >= 0)
@@ -147,6 +148,52 @@ static int fork_cmnd(struct command_details *details, char *argv[],
     return pid;
 }
 
+static struct signal_state {
+    int signo;
+    sigaction_t sa;
+} saved_signals[] = {
+    { SIGALRM },
+    { SIGCHLD },
+    { SIGCONT },
+    { SIGHUP },
+    { SIGINT },
+    { SIGPIPE },
+    { SIGQUIT },
+    { SIGTERM },
+    { SIGQUIT },
+    { SIGTERM },
+    { SIGTSTP },
+    { SIGTTIN },
+    { SIGTTOU },
+    { SIGUSR1 },
+    { SIGUSR2 },
+    { -1 }
+};
+
+/*
+ * Save signal handler state so it can be restored before exec.
+ */
+void
+save_signals(void)
+{
+    struct signal_state *ss;
+
+    for (ss = saved_signals; ss->signo != -1; ss++)
+       sigaction(ss->signo, NULL, &ss->sa);
+}
+
+/*
+ * Restore signal handlers to initial state.
+ */
+void
+restore_signals(void)
+{
+    struct signal_state *ss;
+
+    for (ss = saved_signals; ss->signo != -1; ss++)
+       sigaction(ss->signo, &ss->sa, NULL);
+}
+
 /*
  * Execute a command, potentially in a pty with I/O loggging.
  * This is a little bit tricky due to how POSIX job control works and
index d9bd721b8131029f364337678865c1c09ca9ceaf..6a21f9e18162d09eaa0a4ced2e9537113d5968c2 100644 (file)
@@ -824,6 +824,7 @@ exec_monitor(struct command_details *details, char *argv[], char *envp[],
        error(1, "cannot create pipe");
 
     /* Reset SIGWINCH and SIGALRM. */
+    /* XXX - restore all signals except SIGPIPE? */
     zero_bytes(&sa, sizeof(sa));
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = SA_RESTART;
@@ -885,6 +886,7 @@ exec_monitor(struct command_details *details, char *argv[], char *envp[],
        close(signal_pipe[1]);
        close(errpipe[0]);
        fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);
+       restore_signals();
 
        /* setup tty and exec command */
        exec_pty(details, argv, envp);
@@ -1082,25 +1084,8 @@ flush_output(void)
 static void
 exec_pty(struct command_details *details, char *argv[], char *envp[])
 {
-    sigaction_t sa;
     pid_t self = getpid();
 
-    /* Reset signal handlers. */
-    zero_bytes(&sa, sizeof(sa));
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_RESTART;
-    sa.sa_handler = SIG_DFL;
-    sigaction(SIGHUP, &sa, NULL);
-    sigaction(SIGTERM, &sa, NULL);
-    sigaction(SIGINT, &sa, NULL);
-    sigaction(SIGQUIT, &sa, NULL);
-    sigaction(SIGTSTP, &sa, NULL);
-    sigaction(SIGTTIN, &sa, NULL);
-    sigaction(SIGTTOU, &sa, NULL);
-    sigaction(SIGUSR1, &sa, NULL);
-    sigaction(SIGUSR2, &sa, NULL);
-    sigaction(SIGCHLD, &sa, NULL);
-
     /* Set child process group here too to avoid a race. */
     setpgid(0, self);
 
index aff081bbedcbf2db42dcdb489efaf5b3b340e38a..6402d82b2c59b9cb070faac1ee2be48a3c3303df 100644 (file)
@@ -167,6 +167,8 @@ void zero_bytes(volatile void *, size_t);
 /* exec.c */
 int sudo_execve(struct command_details *details, char *argv[], char *envp[],
     struct command_status *cstat);
+void save_signals(void);
+void restore_signals(void);
 
 /* term.c */
 int term_cbreak(int);