Don't loop over read/write, recv/send or tcgetpgrp/tcsetpgrp trying

to handle EINTR.  We now use SA_RESTART with signals so this is not
needed and is potentially dangerous if it is possible to receive
SIGTTIN or SIGTTOU (which it currently is not).
This commit is contained in:
Todd C. Miller
2017-11-30 09:53:21 -07:00
parent 9298a2a42e
commit b9adb3dd51
3 changed files with 29 additions and 42 deletions

View File

@@ -70,7 +70,6 @@ static void
deliver_signal(struct monitor_closure *mc, int signo, bool from_parent)
{
char signame[SIG2STR_MAX];
int status;
debug_decl(deliver_signal, SUDO_DEBUG_EXEC);
/* Avoid killing more than a single process or process group. */
@@ -93,16 +92,20 @@ deliver_signal(struct monitor_closure *mc, int signo, bool from_parent)
break;
case SIGCONT_FG:
/* Continue in foreground, grant it controlling tty. */
do {
status = tcsetpgrp(io_fds[SFD_SLAVE], mc->cmnd_pgrp);
} while (status == -1 && errno == EINTR);
if (tcsetpgrp(io_fds[SFD_SLAVE], mc->cmnd_pgrp) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to set foreground pgrp to %d (command)",
__func__, (int)mc->cmnd_pgrp);
}
killpg(mc->cmnd_pid, SIGCONT);
break;
case SIGCONT_BG:
/* Continue in background, I take controlling tty. */
do {
status = tcsetpgrp(io_fds[SFD_SLAVE], mc->mon_pgrp);
} while (status == -1 && errno == EINTR);
if (tcsetpgrp(io_fds[SFD_SLAVE], mc->mon_pgrp) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to set foreground pgrp to %d (monitor)",
__func__, (int)mc->mon_pgrp);
}
killpg(mc->cmnd_pid, SIGCONT);
break;
case SIGKILL:
@@ -130,12 +133,10 @@ send_status(int fd, struct command_status *cstat)
sudo_debug_printf(SUDO_DEBUG_INFO,
"sending status message to parent: [%d, %d]",
cstat->type, cstat->val);
do {
n = send(fd, cstat, sizeof(*cstat), 0);
} while (n == -1 && errno == EINTR);
n = send(fd, cstat, sizeof(*cstat), 0);
if (n != sizeof(*cstat)) {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"unable to send status to parent: %s", strerror(errno));
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to send status to parent", __func__);
}
cstat->type = CMD_INVALID; /* prevent re-sending */
}
@@ -203,9 +204,7 @@ mon_handle_sigchld(struct monitor_closure *mc)
mc->cstat->val = status;
if (WIFSTOPPED(status)) {
/* Save the foreground pgid so we can restore it later. */
do {
pid = tcgetpgrp(io_fds[SFD_SLAVE]);
} while (pid == -1 && errno == EINTR);
pid = tcgetpgrp(io_fds[SFD_SLAVE]);
if (pid != mc->mon_pgrp)
mc->cmnd_pgrp = pid;
send_status(mc->backchannel, mc->cstat);
@@ -271,13 +270,10 @@ mon_errpipe_cb(int fd, int what, void *v)
* Read errno from child or EOF when command is executed.
* Note that the error pipe is *blocking*.
*/
do {
nread = read(fd, &errval, sizeof(errval));
} while (nread == -1 && errno == EINTR);
nread = read(fd, &errval, sizeof(errval));
switch (nread) {
case -1:
if (errno != EAGAIN) {
if (errno != EAGAIN && errno != EINTR) {
if (mc->cstat->val == CMD_INVALID) {
/* XXX - need a way to distinguish non-exec error. */
mc->cstat->type = CMD_ERRNO;
@@ -567,10 +563,8 @@ exec_monitor(struct command_details *details, sigset_t *oset,
/* setup tty and exec command */
exec_cmnd_pty(details, foreground, errpipe[1]);
while (write(errpipe[1], &errno, sizeof(int)) == -1) {
if (errno != EINTR)
break;
}
if (write(errpipe[1], &errno, sizeof(int)) == -1)
sudo_warn(U_("unable to execute %s"), details->command);
_exit(1);
}
close(errpipe[1]);
@@ -609,11 +603,11 @@ exec_monitor(struct command_details *details, sigset_t *oset,
/* Make the command the foreground process for the pty slave. */
if (foreground && !ISSET(details->flags, CD_EXEC_BG)) {
int n;
do {
n = tcsetpgrp(io_fds[SFD_SLAVE], mc.cmnd_pgrp);
} while (n == -1 && errno == EINTR);
if (tcsetpgrp(io_fds[SFD_SLAVE], mc.cmnd_pgrp) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to set foreground pgrp to %d (command)",
__func__, (int)mc.cmnd_pgrp);
}
}
/*