diff --git a/include/sudo_compat.h b/include/sudo_compat.h index d070006fb..d62dea7d6 100644 --- a/include/sudo_compat.h +++ b/include/sudo_compat.h @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 1996, 1998-2005, 2008, 2009-2018 + * Copyright (c) 1996, 1998-2005, 2008, 2009-2022 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -290,12 +290,6 @@ extern int errno; # define WCOREDUMP(x) ((x) & 0x80) #endif -/* Older systems may not support WCONTINUED */ -#if !defined(WCONTINUED) && !defined(WIFCONTINUED) -# define WCONTINUED 0 -# define WIFCONTINUED(x) 0 -#endif - /* W_EXITCODE is not POSIX but the encoding of wait status is. */ #ifndef W_EXITCODE # define W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) diff --git a/src/exec_monitor.c b/src/exec_monitor.c index be4946169..f4b6b08d0 100644 --- a/src/exec_monitor.c +++ b/src/exec_monitor.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2009-2021 Todd C. Miller + * Copyright (c) 2009-2022 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -197,23 +197,23 @@ mon_handle_sigchld(struct monitor_closure *mc) /* Read command status. */ do { - pid = waitpid(mc->cmnd_pid, &status, WUNTRACED|WCONTINUED|WNOHANG); + pid = waitpid(mc->cmnd_pid, &status, WUNTRACED|WNOHANG); } while (pid == -1 && errno == EINTR); switch (pid) { + case -1: + if (errno != ECHILD) { + sudo_warn(U_("%s: %s"), __func__, "waitpid"); + debug_return; + } + FALLTHROUGH; case 0: /* Nothing to wait for. */ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no process to wait for", __func__); debug_return; - case -1: - sudo_warn(U_("%s: %s"), __func__, "waitpid"); - debug_return; } - if (WIFCONTINUED(status)) { - sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) resumed", - __func__, (int)mc->cmnd_pid); - } else if (WIFSTOPPED(status)) { + if (WIFSTOPPED(status)) { if (sig2str(WSTOPSIG(status), signame) == -1) (void)snprintf(signame, sizeof(signame), "%d", WSTOPSIG(status)); sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) stopped, SIG%s", @@ -230,7 +230,7 @@ mon_handle_sigchld(struct monitor_closure *mc) mc->cmnd_pid = -1; } else { sudo_debug_printf(SUDO_DEBUG_WARN, - "%s: unexpected wait status %d for command (%d)", + "%s: unexpected wait status 0x%x for command (%d)", __func__, status, (int)mc->cmnd_pid); } @@ -238,18 +238,15 @@ mon_handle_sigchld(struct monitor_closure *mc) if (mc->cstat->type == CMD_INVALID) { /* * Store wait status in cstat and forward to parent if stopped. - * Parent does not expect SIGCONT so don't bother sending it. */ - if (!WIFCONTINUED(status)) { - mc->cstat->type = CMD_WSTATUS; - mc->cstat->val = status; - if (WIFSTOPPED(status)) { - /* Save the foreground pgid so we can restore it later. */ - pid = tcgetpgrp(io_fds[SFD_FOLLOWER]); - if (pid != mc->mon_pgrp) - mc->cmnd_pgrp = pid; - send_status(mc->backchannel, mc->cstat); - } + mc->cstat->type = CMD_WSTATUS; + mc->cstat->val = status; + if (WIFSTOPPED(status)) { + /* Save the foreground pgid so we can restore it later. */ + pid = tcgetpgrp(io_fds[SFD_FOLLOWER]); + if (pid != mc->mon_pgrp) + mc->cmnd_pgrp = pid; + send_status(mc->backchannel, mc->cstat); } } else { sudo_debug_printf(SUDO_DEBUG_WARN, diff --git a/src/exec_nopty.c b/src/exec_nopty.c index 67b8fb21e..86ba79092 100644 --- a/src/exec_nopty.c +++ b/src/exec_nopty.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2009-2020 Todd C. Miller + * Copyright (c) 2009-2022 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -493,23 +493,23 @@ handle_sigchld_nopty(struct exec_closure_nopty *ec) /* Read command status. */ do { - pid = waitpid(ec->cmnd_pid, &status, WUNTRACED|WCONTINUED|WNOHANG); + pid = waitpid(ec->cmnd_pid, &status, WUNTRACED|WNOHANG); } while (pid == -1 && errno == EINTR); switch (pid) { + case -1: + if (errno != ECHILD) { + sudo_warn(U_("%s: %s"), __func__, "waitpid"); + debug_return; + } + FALLTHROUGH; case 0: /* Nothing to wait for. */ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no process to wait for", __func__); debug_return; - case -1: - sudo_warn(U_("%s: %s"), __func__, "waitpid"); - debug_return; } - if (WIFCONTINUED(status)) { - sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) resumed", - __func__, (int)ec->cmnd_pid); - } else if (WIFSTOPPED(status)) { + if (WIFSTOPPED(status)) { /* * Save the controlling terminal's process group so we can restore it * after we resume, if needed. Most well-behaved shells change the @@ -594,10 +594,15 @@ handle_sigchld_nopty(struct exec_closure_nopty *ec) (void)snprintf(signame, sizeof(signame), "%d", WTERMSIG(status)); sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) killed, SIG%s", __func__, (int)ec->cmnd_pid, signame); - } else { + } else if (WIFEXITED(status)) { sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) exited: %d", __func__, (int)ec->cmnd_pid, WEXITSTATUS(status)); + } else { + sudo_debug_printf(SUDO_DEBUG_WARN, + "%s: unexpected wait status 0x%x for command (%d)", + __func__, status, (int)ec->cmnd_pid); } + /* Don't overwrite execve() failure with command exit status. */ if (ec->cstat->type == CMD_INVALID) { ec->cstat->type = CMD_WSTATUS; diff --git a/src/exec_pty.c b/src/exec_pty.c index 634a7f577..6d9e122a3 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2009-2021 Todd C. Miller + * Copyright (c) 2009-2022 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1049,17 +1049,20 @@ handle_sigchld_pty(struct exec_closure_pty *ec) * Monitor process was signaled; wait for it as needed. */ do { - pid = waitpid(ec->monitor_pid, &status, WUNTRACED|WCONTINUED|WNOHANG); + pid = waitpid(ec->monitor_pid, &status, WUNTRACED|WNOHANG); } while (pid == -1 && errno == EINTR); switch (pid) { + case -1: + if (errno != ECHILD) { + sudo_warn(U_("%s: %s"), __func__, "waitpid"); + debug_return; + } + FALLTHROUGH; case 0: /* Nothing to wait for. */ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no process to wait for", __func__); debug_return; - case -1: - sudo_warn(U_("%s: %s"), __func__, "waitpid"); - debug_return; } /* @@ -1067,10 +1070,7 @@ handle_sigchld_pty(struct exec_closure_pty *ec) * If it was stopped, we should stop too (the command keeps * running in its pty) and continue it when we come back. */ - if (WIFCONTINUED(status)) { - sudo_debug_printf(SUDO_DEBUG_INFO, "%s: monitor (%d) resumed", - __func__, (int)ec->monitor_pid); - } else if (WIFSTOPPED(status)) { + if (WIFSTOPPED(status)) { sudo_debug_printf(SUDO_DEBUG_INFO, "monitor stopped, suspending sudo"); n = suspend_sudo(ec, WSTOPSIG(status)); @@ -1085,10 +1085,14 @@ handle_sigchld_pty(struct exec_closure_pty *ec) sudo_debug_printf(SUDO_DEBUG_INFO, "%s: monitor (%d) killed, SIG%s", __func__, (int)ec->monitor_pid, signame); ec->monitor_pid = -1; - } else { + } else if (WIFEXITED(status)) { sudo_debug_printf(SUDO_DEBUG_INFO, "%s: monitor exited, status %d", __func__, WEXITSTATUS(status)); ec->monitor_pid = -1; + } else { + sudo_debug_printf(SUDO_DEBUG_WARN, + "%s: unexpected wait status 0x%x for monitor (%d)", + __func__, status, (int)ec->monitor_pid); } debug_return; }