From: Todd C. Miller Date: Tue, 10 Apr 2012 14:18:39 +0000 (-0400) Subject: Linux select() may return ENOMEM if there is a kernel resource X-Git-Tag: SUDO_1_8_5~1^2~67 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=df04ccb207bd79365d7b1a26f3eb2ad6785f8875;p=sudo Linux select() may return ENOMEM if there is a kernel resource shortage. Older Solaris select() may return EIO instead of EBADF when the tty goes away. If we get an unhandled select() failure, kill the child and exit cleanly. --- diff --git a/src/exec.c b/src/exec.c index 285176009..1aa41ae54 100644 --- a/src/exec.c +++ b/src/exec.c @@ -335,13 +335,18 @@ sudo_execute(struct command_details *details, struct command_status *cstat) nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL); sudo_debug_printf(SUDO_DEBUG_DEBUG, "select returns %d", nready); if (nready == -1) { - if (errno == EINTR) + if (errno == EINTR || errno == ENOMEM) continue; - if (errno == EBADF) { + if (errno == EBADF || errno == EIO) { /* One of the ttys must have gone away. */ goto do_tty_io; } - error(1, _("select failed")); + warning(_("select failed")); + sudo_debug_printf(SUDO_DEBUG_ERROR, + "select failure, terminating child"); + schedule_signal(SIGKILL); + forward_signals(sv[0]); + break; } if (FD_ISSET(sv[0], fdsw)) { forward_signals(sv[0]); diff --git a/src/exec_pty.c b/src/exec_pty.c index dd14f8ad5..51733f63a 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -1015,9 +1015,10 @@ exec_monitor(struct command_details *details, int backchannel) if (n <= 0) { if (n == 0) goto done; - if (errno == EINTR) + if (errno == EINTR || errno == ENOMEM) continue; - error(1, "monitor: %s", _("select failed")); + warning("monitor: %s", _("select failed")); + break; } if (FD_ISSET(signal_pipe[0], fdsr)) { @@ -1152,11 +1153,11 @@ flush_output(void) if (nready <= 0) { if (nready == 0) break; /* all I/O flushed */ - if (errno == EINTR) + if (errno == EINTR || errno == ENOMEM) continue; - error(1, _("select failed")); + warning(_("select failed")); } - if (perform_io(fdsr, fdsw, NULL) != 0) + if (perform_io(fdsr, fdsw, NULL) != 0 || nready == -1) break; } efree(fdsr);