From: Todd C. Miller Date: Wed, 2 Feb 2011 19:22:41 +0000 (-0500) Subject: Save signal state before changing handlers and restore before X-Git-Tag: SUDO_1_7_5~40 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ad879205650ce04f0f663c57ce77e9aae81b8054;p=sudo Save signal state before changing handlers and restore before we execute the command. --HG-- branch : 1.7 --- diff --git a/exec.c b/exec.c index 5b3b3d707..d9c3608b0 100644 --- a/exec.c +++ b/exec.c @@ -136,6 +136,7 @@ static int fork_cmnd(path, argv, envp, sv, rbac_enabled) close(signal_pipe[0]); close(signal_pipe[1]); fcntl(sv[1], F_SETFD, FD_CLOEXEC); + restore_signals(); if (exec_setup(rbac_enabled, user_ttypath, -1) == TRUE) { /* headed for execve() */ closefrom(def_closefrom); @@ -154,6 +155,52 @@ static int fork_cmnd(path, argv, envp, sv, rbac_enabled) 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/exec_pty.c b/exec_pty.c index 4985ff0b2..deb685a57 100644 --- a/exec_pty.c +++ b/exec_pty.c @@ -716,6 +716,7 @@ exec_monitor(path, argv, envp, backchannel, rbac) 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; @@ -777,6 +778,7 @@ exec_monitor(path, argv, envp, backchannel, rbac) close(signal_pipe[1]); close(errpipe[0]); fcntl(errpipe[1], F_SETFD, FD_CLOEXEC); + restore_signals(); /* setup tty and exec command */ exec_pty(path, argv, envp, rbac); @@ -978,25 +980,8 @@ exec_pty(path, argv, envp, rbac_enabled) char *envp[]; int rbac_enabled; { - 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/sudo.h b/sudo.h index fa7e56d97..98e3b3f16 100644 --- a/sudo.h +++ b/sudo.h @@ -235,6 +235,8 @@ void validate_env_vars __P((struct list_member *)); /* exec.c */ int sudo_execve __P((const char *path, char *argv[], char *envp[], uid_t uid, struct command_status *cstat, int dowait, int bgmode)); +void save_signals __P((void)); +void restore_signals __P((void)); /* fileops.c */ char *sudo_parseln __P((FILE *));