Always resume the command in the foreground if sudo itself is the

foreground process.  This helps work around poorly behaved programs
that catch SIGTTOU/SIGTTIN but suspend themselves with SIGSTOP.  At
worst, sudo will go into the background but upon resume the command
will be runnable.  Otherwise, we can get into a situation where the
command will immediately suspend itself.
This commit is contained in:
Todd C. Miller
2013-01-11 10:09:06 -05:00
parent adbc8a574f
commit 8b3edcc4a8

View File

@@ -348,15 +348,15 @@ suspend_parent(int signo)
{
char signame[SIG2STR_MAX];
sigaction_t sa, osa;
int n, oldmode = ttymode, rval = 0;
int n, rval = 0;
debug_decl(suspend_parent, SUDO_DEBUG_EXEC);
switch (signo) {
case SIGTTOU:
case SIGTTIN:
/*
* If we are the foreground process, just resume the command.
* Otherwise, re-send the signal with the handler disabled.
* If sudo is already the foreground process, just resume the command
* in the foreground. If not, we'll suspend sudo and resume later.
*/
if (!foreground)
check_foreground();
@@ -370,7 +370,6 @@ suspend_parent(int signo)
rval = SIGCONT_FG; /* resume command in foreground */
break;
}
ttymode = TERM_RAW;
/* FALLTHROUGH */
case SIGSTOP:
case SIGTSTP:
@@ -378,7 +377,7 @@ suspend_parent(int signo)
flush_output();
/* Restore original tty mode before suspending. */
if (oldmode != TERM_COOKED) {
if (ttymode != TERM_COOKED) {
do {
n = term_restore(io_fds[SFD_USERTTY], 0);
} while (!n && errno == EINTR);
@@ -403,23 +402,27 @@ suspend_parent(int signo)
check_foreground();
/*
* Only modify term if we are foreground process and either
* the old tty mode was not cooked or command got SIGTT{IN,OU}
* We always resume the command in the foreground if sudo itself
* is the foreground process. This helps work around poorly behaved
* programs that catch SIGTTOU/SIGTTIN but suspend themselves with
* SIGSTOP. At worst, sudo will go into the background but upon
* resume the command will be runnable. Otherwise, we can get into
* a situation where the command will immediately suspend itself.
*/
sudo_debug_printf(SUDO_DEBUG_INFO, "parent is in %s, ttymode %d -> %d",
foreground ? "foreground" : "background", oldmode, ttymode);
foreground ? "foreground" : "background", ttymode,
foreground ? TERM_RAW : TERM_COOKED);
if (ttymode != TERM_COOKED) {
if (foreground) {
/* Set raw mode. */
/* Foreground process, set tty to raw mode. */
do {
n = term_raw(io_fds[SFD_USERTTY], 0);
} while (!n && errno == EINTR);
ttymode = TERM_RAW;
} else {
/* Background process, no access to tty. */
ttymode = TERM_COOKED;
}
}
if (signo != SIGSTOP)
sigaction(signo, &osa, NULL);