Remove extra flag to sudo_sigaction(). We want to trap the signal
regardless of whether or not it is ignored by the underlying command since there's no way to know what signal handlers the command will install. Now we just use sudo_sigaction() to set a flag in saved_signals[] to indicate whether a signal needs to be restored before exec.
This commit is contained in:
28
src/exec.c
28
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. */
|
||||
|
@@ -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
|
||||
|
37
src/signal.c
37
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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user