From c18468d1a55ba5f981c8061e0d32007afe304d08 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 2 Feb 2011 12:44:35 -0500 Subject: [PATCH] Save signal state before changing handlers and restore before we execute the command. --- src/exec.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/exec_pty.c | 19 ++----------------- src/sudo.h | 2 ++ 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/exec.c b/src/exec.c index 5969ed7d3..f3038a331 100644 --- a/src/exec.c +++ b/src/exec.c @@ -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 diff --git a/src/exec_pty.c b/src/exec_pty.c index d9bd721b8..6a21f9e18 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -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); diff --git a/src/sudo.h b/src/sudo.h index aff081bbe..6402d82b2 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -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);