Move signal code into its own source file and add sudo_sigaction()

wrapper that has an extra flag to check the saved_signals list to
only install the handler if the signal is not already ignored.
Bump plugin API version for the new front-end signal behavior.
This commit is contained in:
Todd C. Miller
2013-01-17 13:29:46 -05:00
parent 99704cc101
commit 855a11af2b
8 changed files with 229 additions and 140 deletions

View File

@@ -347,6 +347,7 @@ src/po/zh_CN.po
src/preload.c src/preload.c
src/selinux.c src/selinux.c
src/sesh.c src/sesh.c
src/signal.c
src/solaris.c src/solaris.c
src/sudo.c src/sudo.c
src/sudo.h src/sudo.h

View File

@@ -19,7 +19,7 @@
/* API version major/minor */ /* API version major/minor */
#define SUDO_API_VERSION_MAJOR 1 #define SUDO_API_VERSION_MAJOR 1
#define SUDO_API_VERSION_MINOR 2 #define SUDO_API_VERSION_MINOR 3
#define SUDO_API_MKVERSION(x, y) ((x << 16) | y) #define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR) #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR)

View File

@@ -85,8 +85,8 @@ SHELL = @SHELL@
PROGS = @PROGS@ PROGS = @PROGS@
OBJS = conversation.o env_hooks.o exec.o exec_common.o exec_pty.o get_pty.o \ OBJS = conversation.o env_hooks.o exec.o exec_common.o exec_pty.o get_pty.o \
hooks.o net_ifs.o load_plugins.o parse_args.o sudo.o sudo_edit.o \ hooks.o net_ifs.o load_plugins.o parse_args.o signal.o sudo.o \
tgetpass.o ttyname.o utmp.o @SUDO_OBJS@ sudo_edit.o tgetpass.o ttyname.o utmp.o @SUDO_OBJS@
SESH_OBJS = sesh.o locale_stub.o exec_common.o SESH_OBJS = sesh.o locale_stub.o exec_common.o
@@ -261,6 +261,12 @@ sesh.o: $(srcdir)/sesh.c $(top_builddir)/config.h \
$(incdir)/list.h $(incdir)/sudo_debug.h $(srcdir)/sudo_exec.h \ $(incdir)/list.h $(incdir)/sudo_debug.h $(srcdir)/sudo_exec.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_plugin.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sesh.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sesh.c
signal.o: $(srcdir)/signal.c $(top_builddir)/config.h $(srcdir)/sudo.h \
$(top_builddir)/pathnames.h $(top_srcdir)/compat/stdbool.h \
$(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h \
$(incdir)/fileops.h $(incdir)/list.h $(incdir)/sudo_conf.h \
$(incdir)/list.h $(incdir)/sudo_debug.h $(incdir)/gettext.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/signal.c
solaris.o: $(srcdir)/solaris.c $(top_builddir)/config.h $(srcdir)/sudo.h \ solaris.o: $(srcdir)/solaris.c $(top_builddir)/config.h $(srcdir)/sudo.h \
$(top_builddir)/pathnames.h $(top_srcdir)/compat/stdbool.h \ $(top_builddir)/pathnames.h $(top_srcdir)/compat/stdbool.h \
$(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h \

View File

@@ -104,7 +104,7 @@ static int fork_cmnd(struct command_details *details, int sv[2])
* XXX - currently we send SIGCONT upon resume in some cases where * XXX - currently we send SIGCONT upon resume in some cases where
* we don't need to (e.g. command pgrp == parent pgrp). * we don't need to (e.g. command pgrp == parent pgrp).
*/ */
zero_bytes(&sa, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask); sigfillset(&sa.sa_mask);
sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */ sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
#ifdef SA_SIGINFO #ifdef SA_SIGINFO
@@ -113,11 +113,11 @@ static int fork_cmnd(struct command_details *details, int sv[2])
#else #else
sa.sa_handler = handler; sa.sa_handler = handler;
#endif #endif
sigaction(SIGCONT, &sa, NULL); sudo_sigaction(SIGCONT, &sa, NULL, false);
#ifdef SA_SIGINFO #ifdef SA_SIGINFO
sa.sa_sigaction = handler_user_only; sa.sa_sigaction = handler_user_only;
#endif #endif
sigaction(SIGTSTP, &sa, NULL); sudo_sigaction(SIGTSTP, &sa, NULL, true);
/* /*
* The policy plugin's session init must be run before we fork * The policy plugin's session init must be run before we fork
@@ -175,56 +175,6 @@ static int fork_cmnd(struct command_details *details, int sv[2])
debug_return_int(cmnd_pid); debug_return_int(cmnd_pid);
} }
static struct signal_state {
int signo;
sigaction_t sa;
} saved_signals[] = {
{ SIGALRM }, /* SAVED_SIGALRM */
{ SIGCHLD }, /* SAVED_SIGCHLD */
{ SIGCONT }, /* SAVED_SIGCONT */
{ SIGHUP }, /* SAVED_SIGHUP */
{ SIGINT }, /* SAVED_SIGINT */
{ SIGPIPE }, /* SAVED_SIGPIPE */
{ SIGQUIT }, /* SAVED_SIGQUIT */
{ SIGTERM }, /* SAVED_SIGTERM */
{ SIGTSTP }, /* SAVED_SIGTSTP */
{ SIGTTIN }, /* SAVED_SIGTTIN */
{ SIGTTOU }, /* SAVED_SIGTTOU */
{ SIGUSR1 }, /* SAVED_SIGUSR1 */
{ SIGUSR2 }, /* SAVED_SIGUSR2 */
{ -1 }
};
/*
* Save signal handler state so it can be restored before exec.
*/
void
save_signals(void)
{
struct signal_state *ss;
debug_decl(save_signals, SUDO_DEBUG_EXEC)
for (ss = saved_signals; ss->signo != -1; ss++)
sigaction(ss->signo, NULL, &ss->sa);
debug_return;
}
/*
* Restore signal handlers to initial state.
*/
void
restore_signals(void)
{
struct signal_state *ss;
debug_decl(restore_signals, SUDO_DEBUG_EXEC)
for (ss = saved_signals; ss->signo != -1; ss++)
sigaction(ss->signo, &ss->sa, NULL);
debug_return;
}
/* /*
* Execute a command, potentially in a pty with I/O loggging. * 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 * This is a little bit tricky due to how POSIX job control works and
@@ -288,7 +238,7 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
* We block all other signals while running the signal handler. * We block all other signals while running the signal handler.
* Note: HP-UX select() will not be interrupted if SA_RESTART set. * Note: HP-UX select() will not be interrupted if SA_RESTART set.
*/ */
zero_bytes(&sa, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask); sigfillset(&sa.sa_mask);
sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */ sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
#ifdef SA_SIGINFO #ifdef SA_SIGINFO
@@ -297,12 +247,12 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
#else #else
sa.sa_handler = handler; sa.sa_handler = handler;
#endif #endif
sigaction(SIGALRM, &sa, NULL); sudo_sigaction(SIGTERM, &sa, NULL, true);
sigaction(SIGCHLD, &sa, NULL); sudo_sigaction(SIGALRM, &sa, NULL, false); /* XXX - only if there is a timeout */
sigaction(SIGPIPE, &sa, NULL); sudo_sigaction(SIGCHLD, &sa, NULL, false);
sigaction(SIGTERM, &sa, NULL); sudo_sigaction(SIGPIPE, &sa, NULL, false);
sigaction(SIGUSR1, &sa, NULL); sudo_sigaction(SIGUSR1, &sa, NULL, true);
sigaction(SIGUSR2, &sa, NULL); sudo_sigaction(SIGUSR2, &sa, NULL, true);
/* /*
* When not running the command in a pty, we do not want to * When not running the command in a pty, we do not want to
@@ -317,9 +267,9 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
sa.sa_sigaction = handler_user_only; sa.sa_sigaction = handler_user_only;
} }
#endif #endif
sigaction(SIGHUP, &sa, NULL); sudo_sigaction(SIGHUP, &sa, NULL, true);
sigaction(SIGINT, &sa, NULL); sudo_sigaction(SIGINT, &sa, NULL, true);
sigaction(SIGQUIT, &sa, NULL); sudo_sigaction(SIGQUIT, &sa, NULL, true);
/* Max fd we will be selecting on. */ /* Max fd we will be selecting on. */
maxfd = MAX(sv[0], signal_pipe[0]); maxfd = MAX(sv[0], signal_pipe[0]);
@@ -560,15 +510,16 @@ dispatch_signals(int sv[2], pid_t child, int log_io, struct command_status *csta
saved_pgrp = -1; saved_pgrp = -1;
} }
if (signo == SIGTSTP) { if (signo == SIGTSTP) {
zero_bytes(&sa, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_DFL; sa.sa_handler = SIG_DFL;
sigaction(SIGTSTP, &sa, &osa); sudo_sigaction(SIGTSTP, &sa, &osa, false);
} }
if (kill(getpid(), signo) != 0) if (kill(getpid(), signo) != 0)
warning("kill(%d, SIG%s)", (int)getpid(), signame); warning("kill(%d, SIG%s)", (int)getpid(), signame);
if (signo == SIGTSTP) if (signo == SIGTSTP)
sigaction(SIGTSTP, &osa, NULL); sudo_sigaction(SIGTSTP, &osa, NULL, false);
if (fd != -1) { if (fd != -1) {
/* /*
* Restore command's process group if different. * Restore command's process group if different.
@@ -603,7 +554,7 @@ dispatch_signals(int sv[2], pid_t child, int log_io, struct command_status *csta
} }
/* /*
* Read pending signals on signale_pipe written by sudo_handler(). * Drain pending signals from signale_pipe written by sudo_handler().
* Handles the case where the signal was sent to us before * Handles the case where the signal was sent to us before
* we have executed the command. * we have executed the command.
* Returns 1 if we should terminate, else 0. * Returns 1 if we should terminate, else 0.
@@ -647,10 +598,11 @@ dispatch_pending_signals(struct command_status *cstat)
/* Only stop if we haven't already been terminated. */ /* Only stop if we haven't already been terminated. */
if (signo == SIGTSTP) if (signo == SIGTSTP)
{ {
zero_bytes(&sa, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_DFL; sa.sa_handler = SIG_DFL;
sigaction(SIGTSTP, &sa, NULL); sudo_sigaction(SIGTSTP, &sa, NULL, false);
if (kill(getpid(), SIGTSTP) != 0) if (kill(getpid(), SIGTSTP) != 0)
warning("kill(%d, SIGTSTP)", (int)getpid()); warning("kill(%d, SIGTSTP)", (int)getpid());
/* No need to reinstall SIGTSTP handler. */ /* No need to reinstall SIGTSTP handler. */

View File

@@ -376,11 +376,11 @@ suspend_parent(int signo)
/* Suspend self and continue command when we resume. */ /* Suspend self and continue command when we resume. */
if (signo != SIGSTOP) { if (signo != SIGSTOP) {
zero_bytes(&sa, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */ sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_DFL; sa.sa_handler = SIG_DFL;
sigaction(signo, &sa, &osa); sudo_sigaction(signo, &sa, &osa, false);
} }
sudo_debug_printf(SUDO_DEBUG_INFO, "kill parent SIG%s", signame); sudo_debug_printf(SUDO_DEBUG_INFO, "kill parent SIG%s", signame);
if (killpg(ppgrp, signo) != 0) if (killpg(ppgrp, signo) != 0)
@@ -413,7 +413,7 @@ suspend_parent(int signo)
} }
if (signo != SIGSTOP) if (signo != SIGSTOP)
sigaction(signo, &osa, NULL); sudo_sigaction(signo, &osa, NULL, false);
rval = ttymode == TERM_RAW ? SIGCONT_FG : SIGCONT_BG; rval = ttymode == TERM_RAW ? SIGCONT_FG : SIGCONT_BG;
break; break;
} }
@@ -569,13 +569,13 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask)
ppgrp = getpgrp(); /* parent's pgrp, so child can signal us */ ppgrp = getpgrp(); /* parent's pgrp, so child can signal us */
zero_bytes(&sa, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
if (io_fds[SFD_USERTTY] != -1) { if (io_fds[SFD_USERTTY] != -1) {
sa.sa_flags = SA_RESTART; sa.sa_flags = SA_RESTART;
sa.sa_handler = sigwinch; sa.sa_handler = sigwinch;
sigaction(SIGWINCH, &sa, NULL); sudo_sigaction(SIGWINCH, &sa, NULL, false);
} }
/* So we can block tty-generated signals */ /* 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. */ /* We don't want to receive SIGTTIN/SIGTTOU, getting EIO is preferable. */
sa.sa_handler = SIG_IGN; sa.sa_handler = SIG_IGN;
sigaction(SIGTTIN, &sa, NULL); sudo_sigaction(SIGTTIN, &sa, NULL, true);
sigaction(SIGTTOU, &sa, NULL); sudo_sigaction(SIGTTOU, &sa, NULL, true);
/* Job control signals to relay from parent to child. */ /* Job control signals to relay from parent to child. */
sigfillset(&sa.sa_mask); sigfillset(&sa.sa_mask);
@@ -656,7 +656,7 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask)
#else #else
sa.sa_handler = handler; sa.sa_handler = handler;
#endif #endif
sigaction(SIGTSTP, &sa, NULL); sudo_sigaction(SIGTSTP, &sa, NULL, true);
if (foreground) { if (foreground) {
/* Copy terminal attrs from user tty -> pty slave. */ /* Copy terminal attrs from user tty -> pty slave. */
@@ -987,17 +987,17 @@ exec_monitor(struct command_details *details, int backchannel)
error(1, _("unable to create pipe")); error(1, _("unable to create pipe"));
/* Reset SIGWINCH and SIGALRM. */ /* Reset SIGWINCH and SIGALRM. */
zero_bytes(&sa, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_DFL; sa.sa_handler = SIG_DFL;
sigaction(SIGWINCH, &sa, NULL); sudo_sigaction(SIGWINCH, &sa, NULL, false);
sigaction(SIGALRM, &sa, NULL); sudo_sigaction(SIGALRM, &sa, NULL, false); /* XXX - saved value */
/* Ignore any SIGTTIN or SIGTTOU we get. */ /* Ignore any SIGTTIN or SIGTTOU we get. */
sa.sa_handler = SIG_IGN; sa.sa_handler = SIG_IGN;
sigaction(SIGTTIN, &sa, NULL); sudo_sigaction(SIGTTIN, &sa, NULL, true);
sigaction(SIGTTOU, &sa, NULL); sudo_sigaction(SIGTTOU, &sa, NULL, true);
/* Block all signals in mon_handler(). */ /* Block all signals in mon_handler(). */
sigfillset(&sa.sa_mask); sigfillset(&sa.sa_mask);
@@ -1010,7 +1010,7 @@ exec_monitor(struct command_details *details, int backchannel)
#else #else
sa.sa_handler = mon_handler; sa.sa_handler = mon_handler;
#endif #endif
sigaction(SIGCHLD, &sa, NULL); sudo_sigaction(SIGCHLD, &sa, NULL, false);
/* Catch common signals so we can cleanup properly. */ /* Catch common signals so we can cleanup properly. */
sa.sa_flags = SA_RESTART; sa.sa_flags = SA_RESTART;
@@ -1020,13 +1020,13 @@ exec_monitor(struct command_details *details, int backchannel)
#else #else
sa.sa_handler = mon_handler; sa.sa_handler = mon_handler;
#endif #endif
sigaction(SIGHUP, &sa, NULL); sudo_sigaction(SIGHUP, &sa, NULL, true);
sigaction(SIGINT, &sa, NULL); sudo_sigaction(SIGINT, &sa, NULL, true);
sigaction(SIGQUIT, &sa, NULL); sudo_sigaction(SIGQUIT, &sa, NULL, true);
sigaction(SIGTERM, &sa, NULL); sudo_sigaction(SIGTERM, &sa, NULL, true);
sigaction(SIGTSTP, &sa, NULL); sudo_sigaction(SIGTSTP, &sa, NULL, true);
sigaction(SIGUSR1, &sa, NULL); sudo_sigaction(SIGUSR1, &sa, NULL, true);
sigaction(SIGUSR2, &sa, NULL); sudo_sigaction(SIGUSR2, &sa, NULL, true);
/* /*
* Start a new session with the parent as the session leader * Start a new session with the parent as the session leader

167
src/signal.c Normal file
View File

@@ -0,0 +1,167 @@
/*
* Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
#include <sys/types.h>
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif /* STDC_HEADERS */
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <errno.h>
#include <signal.h>
#include "sudo.h"
int signal_pipe[2];
static struct signal_state {
int signo;
sigaction_t sa;
} saved_signals[] = {
{ SIGALRM }, /* SAVED_SIGALRM */
{ SIGCHLD }, /* SAVED_SIGCHLD */
{ SIGCONT }, /* SAVED_SIGCONT */
{ SIGHUP }, /* SAVED_SIGHUP */
{ SIGINT }, /* SAVED_SIGINT */
{ SIGPIPE }, /* SAVED_SIGPIPE */
{ SIGQUIT }, /* SAVED_SIGQUIT */
{ SIGTERM }, /* SAVED_SIGTERM */
{ SIGTSTP }, /* SAVED_SIGTSTP */
{ SIGTTIN }, /* SAVED_SIGTTIN */
{ SIGTTOU }, /* SAVED_SIGTTOU */
{ SIGUSR1 }, /* SAVED_SIGUSR1 */
{ SIGUSR2 }, /* SAVED_SIGUSR2 */
{ -1 }
};
/*
* Save signal handler state so it can be restored before exec.
*/
void
save_signals(void)
{
struct signal_state *ss;
debug_decl(save_signals, SUDO_DEBUG_MAIN)
for (ss = saved_signals; ss->signo != -1; ss++)
sigaction(ss->signo, NULL, &ss->sa);
debug_return;
}
/*
* Restore signal handlers to initial state for exec.
*/
void
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);
debug_return;
}
static void
sudo_handler(int signo)
{
/*
* The pipe is non-blocking, if we overflow the kernel's pipe
* buffer we drop the signal. This is not a problem in practice.
*/
ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
}
/*
* Trap tty-generated (and other) signals so we can't be killed before
* calling the policy close function. The signal pipe will be drained
* in sudo_execute() before running the command and new handlers will
* be installed in the parent.
*/
void
init_signals(void)
{
struct sigaction sa;
struct signal_state *ss;
debug_decl(init_signals, SUDO_DEBUG_MAIN)
/*
* We use a pipe to atomically handle signal notification within
* the select() loop without races (we may not have pselect()).
*/
if (pipe_nonblock(signal_pipe) != 0)
error(1, _("unable to create pipe"));
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sudo_handler;
for (ss = saved_signals; ss->signo > 0; ss++) {
switch (ss->signo) {
case SIGCHLD:
case SIGCONT:
case SIGPIPE:
case SIGTTIN:
case SIGTTOU:
/* Don't install these until exec time. */
break;
default:
if (ss->sa.sa_handler != SIG_IGN)
sigaction(ss->signo, &sa, NULL);
break;
}
}
debug_return;
}
/*
* Like sigaction() but includes an udpate_only flag.
* In update-only mode, don't override SIG_IGN.
*/
int
sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa, bool update_only)
{
/* 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;
}
}
}
return sigaction(signo, sa, osa);
}

View File

@@ -95,7 +95,6 @@ struct plugin_container policy_plugin;
struct plugin_container_list io_plugins; struct plugin_container_list io_plugins;
struct user_details user_details; struct user_details user_details;
const char *list_user, *runas_user, *runas_group; /* extern for parse_args.c */ const char *list_user, *runas_user, *runas_group; /* extern for parse_args.c */
int signal_pipe[2];
static int sudo_mode; static int sudo_mode;
/* /*
@@ -107,7 +106,6 @@ static void sudo_check_suid(const char *path);
static char **get_user_info(struct user_details *); static char **get_user_info(struct user_details *);
static void command_info_to_details(char * const info[], static void command_info_to_details(char * const info[],
struct command_details *details); struct command_details *details);
static void setup_signals(void);
/* Policy plugin convenience functions. */ /* Policy plugin convenience functions. */
static int policy_open(struct plugin_container *plugin, char * const settings[], static int policy_open(struct plugin_container *plugin, char * const settings[],
@@ -209,7 +207,7 @@ main(int argc, char *argv[], char *envp[])
errorx(1, _("unable to initialize policy plugin")); errorx(1, _("unable to initialize policy plugin"));
} }
setup_signals(); init_signals();
switch (sudo_mode & MODE_MASK) { switch (sudo_mode & MODE_MASK) {
case MODE_VERSION: case MODE_VERSION:
@@ -1249,43 +1247,3 @@ iolog_unlink(struct plugin_container *plugin)
debug_return; debug_return;
} }
static void
sudo_handler(int signo)
{
/*
* The pipe is non-blocking, if we overflow the kernel's pipe
* buffer we drop the signal. This is not a problem in practice.
*/
ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
}
/*
* Trap tty-generated signals so we can't be killed before calling
* the policy close function. The signal pipe will be checked
* in sudo_execute().
*/
static void
setup_signals(void)
{
struct sigaction sa;
debug_decl(setup_signals, SUDO_DEBUG_MAIN)
/*
* We use a pipe to atomically handle signal notification within
* the select() loop without races (we may not have pselect()).
*/
if (pipe_nonblock(signal_pipe) != 0)
error(1, _("unable to create pipe"));
/* XXX - should not install handler if ignored by default. */
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sudo_handler;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTSTP, &sa, NULL);
debug_return;
}

View File

@@ -184,8 +184,6 @@ void zero_bytes(volatile void *, size_t);
/* exec.c */ /* exec.c */
int pipe_nonblock(int fds[2]); int pipe_nonblock(int fds[2]);
int sudo_execute(struct command_details *details, struct command_status *cstat); int sudo_execute(struct command_details *details, struct command_status *cstat);
void restore_signals(void);
void save_signals(void);
/* term.c */ /* term.c */
int term_cbreak(int); int term_cbreak(int);
@@ -218,7 +216,6 @@ int run_command(struct command_details *details);
int os_init_common(int argc, char *argv[], char *envp[]); int os_init_common(int argc, char *argv[], char *envp[]);
extern const char *list_user, *runas_user, *runas_group; extern const char *list_user, *runas_user, *runas_group;
extern struct user_details user_details; extern struct user_details user_details;
extern int signal_pipe[2];
/* sudo_edit.c */ /* sudo_edit.c */
int sudo_edit(struct command_details *details); int sudo_edit(struct command_details *details);
@@ -267,4 +264,12 @@ int sudo_setgroups(int ngids, const GETGROUPS_T *gids);
/* ttyname.c */ /* ttyname.c */
char *get_process_ttyname(void); 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);
void init_signals(void);
void restore_signals(void);
void save_signals(void);
#endif /* _SUDO_SUDO_H */ #endif /* _SUDO_SUDO_H */