diff --git a/src/exec.c b/src/exec.c index dd6000b8e..41f7e2f98 100644 --- a/src/exec.c +++ b/src/exec.c @@ -113,11 +113,11 @@ static int fork_cmnd(struct command_details *details, int sv[2]) #else sa.sa_handler = handler; #endif - sudo_sigaction(SIGCONT, &sa, NULL, false); + sudo_sigaction(SIGCONT, &sa, NULL); #ifdef SA_SIGINFO sa.sa_sigaction = handler_user_only; #endif - sudo_sigaction(SIGTSTP, &sa, NULL, true); + sudo_sigaction(SIGTSTP, &sa, NULL); /* * The policy plugin's session init must be run before we fork @@ -247,12 +247,12 @@ sudo_execute(struct command_details *details, struct command_status *cstat) #else sa.sa_handler = handler; #endif - sudo_sigaction(SIGTERM, &sa, NULL, true); - sudo_sigaction(SIGALRM, &sa, NULL, false); /* XXX - only if there is a timeout */ - sudo_sigaction(SIGCHLD, &sa, NULL, false); - sudo_sigaction(SIGPIPE, &sa, NULL, false); - sudo_sigaction(SIGUSR1, &sa, NULL, true); - sudo_sigaction(SIGUSR2, &sa, NULL, true); + sudo_sigaction(SIGTERM, &sa, NULL); + sudo_sigaction(SIGALRM, &sa, NULL); /* XXX - only if there is a timeout */ + sudo_sigaction(SIGCHLD, &sa, NULL); + sudo_sigaction(SIGPIPE, &sa, NULL); + sudo_sigaction(SIGUSR1, &sa, NULL); + sudo_sigaction(SIGUSR2, &sa, NULL); /* * When not running the command in a pty, we do not want to @@ -267,9 +267,9 @@ sudo_execute(struct command_details *details, struct command_status *cstat) sa.sa_sigaction = handler_user_only; } #endif - sudo_sigaction(SIGHUP, &sa, NULL, true); - sudo_sigaction(SIGINT, &sa, NULL, true); - sudo_sigaction(SIGQUIT, &sa, NULL, true); + sudo_sigaction(SIGHUP, &sa, NULL); + sudo_sigaction(SIGINT, &sa, NULL); + sudo_sigaction(SIGQUIT, &sa, NULL); /* Max fd we will be selecting on. */ maxfd = MAX(sv[0], signal_pipe[0]); @@ -514,12 +514,12 @@ dispatch_signals(int sv[2], pid_t child, int log_io, struct command_status *csta sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = SIG_DFL; - sudo_sigaction(SIGTSTP, &sa, &osa, false); + sudo_sigaction(SIGTSTP, &sa, &osa); } if (kill(getpid(), signo) != 0) warning("kill(%d, SIG%s)", (int)getpid(), signame); if (signo == SIGTSTP) - sudo_sigaction(SIGTSTP, &osa, NULL, false); + sudo_sigaction(SIGTSTP, &osa, NULL); if (fd != -1) { /* * Restore command's process group if different. @@ -602,7 +602,7 @@ dispatch_pending_signals(struct command_status *cstat) sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = SIG_DFL; - sudo_sigaction(SIGTSTP, &sa, NULL, false); + sudo_sigaction(SIGTSTP, &sa, NULL); if (kill(getpid(), SIGTSTP) != 0) warning("kill(%d, SIGTSTP)", (int)getpid()); /* No need to reinstall SIGTSTP handler. */ diff --git a/src/exec_pty.c b/src/exec_pty.c index 42221a5f3..243012a33 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -380,7 +380,7 @@ suspend_parent(int signo) sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = SIG_DFL; - sudo_sigaction(signo, &sa, &osa, false); + sudo_sigaction(signo, &sa, &osa); } sudo_debug_printf(SUDO_DEBUG_INFO, "kill parent SIG%s", signame); if (killpg(ppgrp, signo) != 0) @@ -413,7 +413,7 @@ suspend_parent(int signo) } if (signo != SIGSTOP) - sudo_sigaction(signo, &osa, NULL, false); + sudo_sigaction(signo, &osa, NULL); rval = ttymode == TERM_RAW ? SIGCONT_FG : SIGCONT_BG; break; } @@ -575,7 +575,7 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask) if (io_fds[SFD_USERTTY] != -1) { sa.sa_flags = SA_RESTART; sa.sa_handler = sigwinch; - sudo_sigaction(SIGWINCH, &sa, NULL, false); + sudo_sigaction(SIGWINCH, &sa, NULL); } /* So we can block tty-generated signals */ @@ -644,8 +644,8 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask) /* We don't want to receive SIGTTIN/SIGTTOU, getting EIO is preferable. */ sa.sa_handler = SIG_IGN; - sudo_sigaction(SIGTTIN, &sa, NULL, true); - sudo_sigaction(SIGTTOU, &sa, NULL, true); + sudo_sigaction(SIGTTIN, &sa, NULL); + sudo_sigaction(SIGTTOU, &sa, NULL); /* Job control signals to relay from parent to child. */ sigfillset(&sa.sa_mask); @@ -656,7 +656,7 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask) #else sa.sa_handler = handler; #endif - sudo_sigaction(SIGTSTP, &sa, NULL, true); + sudo_sigaction(SIGTSTP, &sa, NULL); if (foreground) { /* Copy terminal attrs from user tty -> pty slave. */ @@ -991,13 +991,13 @@ exec_monitor(struct command_details *details, int backchannel) sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = SIG_DFL; - sudo_sigaction(SIGWINCH, &sa, NULL, false); - sudo_sigaction(SIGALRM, &sa, NULL, false); /* XXX - saved value */ + sudo_sigaction(SIGWINCH, &sa, NULL); + sudo_sigaction(SIGALRM, &sa, NULL); /* Ignore any SIGTTIN or SIGTTOU we get. */ sa.sa_handler = SIG_IGN; - sudo_sigaction(SIGTTIN, &sa, NULL, true); - sudo_sigaction(SIGTTOU, &sa, NULL, true); + sudo_sigaction(SIGTTIN, &sa, NULL); + sudo_sigaction(SIGTTOU, &sa, NULL); /* Block all signals in mon_handler(). */ sigfillset(&sa.sa_mask); @@ -1010,7 +1010,7 @@ exec_monitor(struct command_details *details, int backchannel) #else sa.sa_handler = mon_handler; #endif - sudo_sigaction(SIGCHLD, &sa, NULL, false); + sudo_sigaction(SIGCHLD, &sa, NULL); /* Catch common signals so we can cleanup properly. */ sa.sa_flags = SA_RESTART; @@ -1020,13 +1020,13 @@ exec_monitor(struct command_details *details, int backchannel) #else sa.sa_handler = mon_handler; #endif - sudo_sigaction(SIGHUP, &sa, NULL, true); - sudo_sigaction(SIGINT, &sa, NULL, true); - sudo_sigaction(SIGQUIT, &sa, NULL, true); - sudo_sigaction(SIGTERM, &sa, NULL, true); - sudo_sigaction(SIGTSTP, &sa, NULL, true); - sudo_sigaction(SIGUSR1, &sa, NULL, true); - sudo_sigaction(SIGUSR2, &sa, NULL, true); + sudo_sigaction(SIGHUP, &sa, NULL); + sudo_sigaction(SIGINT, &sa, NULL); + sudo_sigaction(SIGQUIT, &sa, NULL); + sudo_sigaction(SIGTERM, &sa, NULL); + sudo_sigaction(SIGTSTP, &sa, NULL); + sudo_sigaction(SIGUSR1, &sa, NULL); + sudo_sigaction(SIGUSR2, &sa, NULL); /* * Start a new session with the parent as the session leader diff --git a/src/signal.c b/src/signal.c index 549279637..522e76d2a 100644 --- a/src/signal.c +++ b/src/signal.c @@ -44,6 +44,7 @@ int signal_pipe[2]; static struct signal_state { int signo; + int restore; sigaction_t sa; } saved_signals[] = { { SIGALRM }, /* SAVED_SIGALRM */ @@ -86,8 +87,10 @@ restore_signals(void) struct signal_state *ss; debug_decl(restore_signals, SUDO_DEBUG_MAIN) - for (ss = saved_signals; ss->signo != -1; ss++) - sigaction(ss->signo, &ss->sa, NULL); + for (ss = saved_signals; ss->signo != -1; ss++) { + if (ss->restore) + sigaction(ss->signo, &ss->sa, NULL); + } debug_return; } @@ -146,22 +149,28 @@ init_signals(void) } /* - * Like sigaction() but includes an udpate_only flag. - * In update-only mode, don't override SIG_IGN. + * Like sigaction() but sets restore flag in saved_signals[] + * if needed. */ int -sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa, bool update_only) +sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa) { - /* Don't override SIG_IGN if the update_only flag is set. */ - if (update_only) { - struct signal_state *ss; - for (ss = saved_signals; ss->signo > 0; ss++) { - if (ss->signo == signo) { - if (ss->sa.sa_handler == SIG_IGN) - return 0; - break; + struct signal_state *ss; + int rval; + debug_decl(sudo_sigaction, SUDO_DEBUG_MAIN) + + for (ss = saved_signals; ss->signo > 0; ss++) { + if (ss->signo == signo) { + /* If signal was or now is ignored, restore old handler on exec. */ + if (ss->sa.sa_handler == SIG_IGN || sa->sa_handler == SIG_IGN) { + sudo_debug_printf(SUDO_DEBUG_INFO, + "will restore signal %d on exec", signo); + ss->restore = true; } + break; } } - return sigaction(signo, sa, osa); + rval = sigaction(signo, sa, osa); + + debug_return_int(rval); } diff --git a/src/sudo.h b/src/sudo.h index 1517b560f..492f19518 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -267,7 +267,7 @@ char *get_process_ttyname(void); /* signal.c */ struct sigaction; extern int signal_pipe[2]; -int sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa, bool update_only); +int sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa); void init_signals(void); void restore_signals(void); void save_signals(void);