From a73730b72c863748ab5f7874109e8ca1519a2687 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 27 Aug 2012 15:38:57 -0400 Subject: [PATCH] Pass on SIGTSTP to the command if it was sent by a user process (not the kernel or the terminal) when we are not I/O logging and set the default SIGTSTP handler when we re-send the signal to ourself, restoring our handler after we resume. --HG-- branch : 1.7 --- exec.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/exec.c b/exec.c index 65d505b02..d737fce1e 100644 --- a/exec.c +++ b/exec.c @@ -130,8 +130,17 @@ static int fork_cmnd(path, argv, envp, sv, rbac_enabled) ppgrp = getpgrp(); /* parent's process group */ /* - * XXX - should only send SIGCONT when command pgrp != parent pgrp - * OR we were suspended by a user (not kernel or tty) signal. + * Handle suspend/restore of sudo and the command. + * In most cases, the command will be in the same process group as + * sudo and job control will "just work". However, if the command + * changes its process group ID and does not change it back (or is + * kill by SIGSTOP which is not catchable), we need to resume the + * command manually. Also, if SIGTSTP is sent directly to sudo, + * we need to suspend the command, and then suspend ourself, restoring + * the default SIGTSTP handler temporarily. + * + * XXX - currently we send SIGCONT upon resume in some cases where + * we don't need to (e.g. command pgrp == parent pgrp). */ zero_bytes(&sa, sizeof(sa)); sigemptyset(&sa.sa_mask); @@ -143,6 +152,10 @@ static int fork_cmnd(path, argv, envp, sv, rbac_enabled) sa.sa_handler = handler; #endif sigaction(SIGCONT, &sa, NULL); +#ifdef SA_SIGINFO + sa.sa_sigaction = handler_user_only; +#endif + sigaction(SIGTSTP, &sa, NULL); cmnd_pid = fork(); switch (cmnd_pid) { @@ -581,15 +594,25 @@ handle_signals(sv, child, cstat) * with SIGTTOU while the command continues to run. */ #ifdef HAVE_TCSETPGRP + sigaction_t sa, osa; pid_t saved_pgrp = (pid_t)-1; + int signo = WSTOPSIG(status); int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0); if (fd != -1) { if ((saved_pgrp = tcgetpgrp(fd)) == ppgrp) saved_pgrp = -1; } #endif /* HAVE_TCSETPGRP */ - if (kill(getpid(), WSTOPSIG(status)) != 0) - warning("kill(%d, %d)", getpid(), WSTOPSIG(status)); + if (signo == SIGTSTP) { + zero_bytes(&sa, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + sigaction(SIGTSTP, &sa, NULL); + } + if (kill(getpid(), signo) != 0) + warning("kill(%d, %d)", getpid(), signo); + if (signo == SIGTSTP) + sigaction(SIGTSTP, &osa, NULL); #ifdef HAVE_TCSETPGRP if (fd != -1) { /* -- 2.40.0