diff --git a/src/exec.c b/src/exec.c index db3c8f4ce..d572b2a1b 100644 --- a/src/exec.c +++ b/src/exec.c @@ -48,6 +48,14 @@ #include "sudo_plugin.h" #include "sudo_plugin_int.h" +#ifdef HAVE_PTRACE_INTERCEPT +static void +handler(int signo) +{ + /* just return */ +} +#endif /* HAVE_PTRACE_INTERCEPT */ + static void close_fds(struct command_details *details, int errfd, int intercept_fd) { @@ -245,10 +253,35 @@ done: * If the exec fails, cstat is filled in with the value of errno. */ void -exec_cmnd(struct command_details *details, int intercept_fd, int errfd) +exec_cmnd(struct command_details *details, sigset_t *mask, + int intercept_fd, int errfd) { debug_decl(exec_cmnd, SUDO_DEBUG_EXEC); +#ifdef HAVE_PTRACE_INTERCEPT + if (ISSET(details->flags, CD_USE_PTRACE)) { + struct sigaction sa; + sigset_t set; + + /* Tracer will send us SIGUSR1 when it is time to proceed. */ + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sa.sa_handler = handler; + if (sudo_sigaction(SIGUSR1, &sa, NULL) != 0) { + sudo_warn(U_("unable to set handler for signal %d"), + SIGUSR1); + } + + /* Suspend child until tracer seizes control and sends SIGUSR1. */ + sigfillset(&set); + sigdelset(&set, SIGUSR1); + sigsuspend(&set); + } +#endif /* HAVE_PTRACE_INTERCEPT */ + + if (mask != NULL) + sigprocmask(SIG_SETMASK, mask, NULL); restore_signals(); if (exec_setup(details, intercept_fd, errfd) == true) { /* headed for execve() */ @@ -440,7 +473,7 @@ sudo_execute(struct command_details *details, struct command_status *cstat) */ if (direct_exec_allowed(details)) { if (!sudo_terminated(cstat)) { - exec_cmnd(details, -1, -1); + exec_cmnd(details, NULL, -1, -1); cstat->type = CMD_ERRNO; cstat->val = errno; } diff --git a/src/exec_monitor.c b/src/exec_monitor.c index 0f4b784ac..8c94182a4 100644 --- a/src/exec_monitor.c +++ b/src/exec_monitor.c @@ -386,8 +386,8 @@ mon_backchannel_cb(int fd, int what, void *v) * Returns only if execve() fails. */ static void -exec_cmnd_pty(struct command_details *details, bool foreground, - int intercept_fd, int errfd) +exec_cmnd_pty(struct command_details *details, sigset_t *mask, + bool foreground, int intercept_fd, int errfd) { volatile pid_t self = getpid(); debug_decl(exec_cmnd_pty, SUDO_DEBUG_EXEC); @@ -430,7 +430,7 @@ exec_cmnd_pty(struct command_details *details, bool foreground, /* Execute command; only returns on error. */ sudo_debug_printf(SUDO_DEBUG_INFO, "executing %s in the %s", details->command, foreground ? "foreground" : "background"); - exec_cmnd(details, intercept_fd, errfd); + exec_cmnd(details, mask, intercept_fd, errfd); debug_return; } @@ -536,14 +536,6 @@ fill_exec_closure_monitor(struct monitor_closure *mc, debug_return; } -#ifdef HAVE_PTRACE_INTERCEPT -static void -handler(int signo) -{ - /* just return */ -} -#endif /* HAVE_PTRACE_INTERCEPT */ - /* * Monitor process that creates a new session with the controlling tty, * resets signal handlers and forks a child to call exec_cmnd_pty(). @@ -638,28 +630,8 @@ exec_monitor(struct command_details *details, sigset_t *oset, close(errpipe[0]); if (io_fds[SFD_USERTTY] != -1) close(io_fds[SFD_USERTTY]); -#ifdef HAVE_PTRACE_INTERCEPT - if (ISSET(details->flags, CD_USE_PTRACE)) { - sigset_t set; - - /* Tracer will send us SIGUSR1 when it is time to proceed. */ - sa.sa_handler = handler; - if (sudo_sigaction(SIGUSR1, &sa, NULL) != 0) { - sudo_warn(U_("unable to set handler for signal %d"), - SIGUSR1); - } - - /* Suspend child until tracer seizes control and sends SIGUSR1. */ - sigfillset(&set); - sigdelset(&set, SIGUSR1); - sigsuspend(&set); - } -#endif /* HAVE_PTRACE_INTERCEPT */ - sigprocmask(SIG_SETMASK, oset, NULL); - restore_signals(); - /* setup tty and exec command */ - exec_cmnd_pty(details, foreground, intercept_fd, errpipe[1]); + exec_cmnd_pty(details, oset, foreground, intercept_fd, errpipe[1]); if (write(errpipe[1], &errno, sizeof(int)) == -1) sudo_warn(U_("unable to execute %s"), details->command); _exit(EXIT_FAILURE); diff --git a/src/exec_nopty.c b/src/exec_nopty.c index 4e5869203..95e1a3f7d 100644 --- a/src/exec_nopty.c +++ b/src/exec_nopty.c @@ -348,14 +348,6 @@ free_exec_closure_nopty(struct exec_closure_nopty *ec) debug_return; } -#ifdef HAVE_PTRACE_INTERCEPT -static void -handler(int signo) -{ - /* just return */ -} -#endif /* HAVE_PTRACE_INTERCEPT */ - /* * Execute a command and wait for it to finish. */ @@ -426,27 +418,7 @@ exec_nopty(struct command_details *details, struct command_status *cstat) close(errpipe[0]); if (intercept_sv[0] != -1) close(intercept_sv[0]); -#ifdef HAVE_PTRACE_INTERCEPT - if (ISSET(details->flags, CD_USE_PTRACE)) { - struct sigaction sa; - - /* Tracer will send us SIGUSR1 when it is time to proceed. */ - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sa.sa_handler = handler; - if (sudo_sigaction(SIGUSR1, &sa, NULL) != 0) { - sudo_warn(U_("unable to set handler for signal %d"), - SIGUSR1); - } - - /* Suspend child until tracer seizes control and sends SIGUSR1. */ - sigdelset(&set, SIGUSR1); - sigsuspend(&set); - } -#endif /* HAVE_PTRACE_INTERCEPT */ - sigprocmask(SIG_SETMASK, &oset, NULL); - exec_cmnd(details, intercept_sv[1], errpipe[1]); + exec_cmnd(details, &oset, intercept_sv[1], errpipe[1]); while (write(errpipe[1], &errno, sizeof(int)) == -1) { if (errno != EINTR) break; diff --git a/src/sudo_exec.h b/src/sudo_exec.h index f37901b42..d225524d5 100644 --- a/src/sudo_exec.h +++ b/src/sudo_exec.h @@ -113,7 +113,7 @@ struct sudo_event_base; struct stat; /* exec.c */ -void exec_cmnd(struct command_details *details, int intercept_fd, int errfd); +void exec_cmnd(struct command_details *details, sigset_t *mask, int intercept_fd, int errfd); void terminate_command(pid_t pid, bool use_pgrp); bool sudo_terminated(struct command_status *cstat);