From 84af812b8ca31c81ddd2b466fa9861b8adae86a7 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Thu, 7 Sep 2017 11:32:30 -0600 Subject: [PATCH] If /dev/tty is not available and no I/O logging plugins are configured, fall back on exec_nopty() even if the policy plugin requested a pty. We never allocate a pty when sudo is not run from a terminal anyway. --- src/exec.c | 41 ++++++++++++++++++++++------------------- src/exec_nopty.c | 6 +++--- src/exec_pty.c | 9 ++++++--- src/sudo_exec.h | 4 ++-- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/exec.c b/src/exec.c index 2bf967f01..2e8499932 100644 --- a/src/exec.c +++ b/src/exec.c @@ -380,34 +380,37 @@ sudo_execute(struct command_details *details, struct command_status *cstat) } /* - * If we have an I/O plugin or the policy plugin has requested one, we - * need to allocate a pty. + * Run the command in a new pty if there is an I/O plugin or the policy + * has requested a pty. If /dev/tty is unavailable and no I/O plugin + * is configured, this returns false and we run the command without a pty. */ if (!TAILQ_EMPTY(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) { - /* - * Run the command in a new pty, wait for it to finish and - * send the plugin the exit status. - */ - exec_pty(details, cstat); - } else if (!ISSET(details->flags, CD_SET_TIMEOUT|CD_SUDOEDIT) && + if (exec_pty(details, cstat)) + goto done; + } + + /* + * If we are not running the command in a pty, we were not invoked + * as sudoedit, there is no command timeout and there is no close + * function, just exec directly. Only returns on error. + */ + if (!ISSET(details->flags, CD_SET_TIMEOUT|CD_SUDOEDIT) && policy_plugin.u.policy->close == NULL) { - /* - * If we are not running the command in a pty, we were not invoked - * as sudoedit, there is no command timeout and there is no close - * function, just exec directly. Only returns on error. - */ if (!sudo_terminated(cstat)) { exec_cmnd(details, -1); cstat->type = CMD_ERRNO; cstat->val = errno; } - } else { - /* - * No pty but we need to wait for the command to finish to - * send the plugin the exit status. - */ - exec_nopty(details, cstat); + goto done; } + + /* + * Run the command in the existing tty (if any) and wait for it to finish. + */ + exec_nopty(details, cstat); + +done: + /* The caller will run any plugin close functions. */ debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0); } diff --git a/src/exec_nopty.c b/src/exec_nopty.c index 7e044a05e..ae41282cf 100644 --- a/src/exec_nopty.c +++ b/src/exec_nopty.c @@ -340,7 +340,7 @@ free_exec_closure_nopty(struct exec_closure_nopty *ec) /* * Execute a command and wait for it to finish. */ -int +void exec_nopty(struct command_details *details, struct command_status *cstat) { struct exec_closure_nopty ec = { 0 }; @@ -371,7 +371,7 @@ exec_nopty(struct command_details *details, struct command_status *cstat) /* Check for early termination or suspend signals before we fork. */ if (sudo_terminated(cstat)) { sigprocmask(SIG_SETMASK, &oset, NULL); - debug_return_int(0); + debug_return; } ec.cmnd_pid = sudo_debug_fork(); @@ -436,7 +436,7 @@ exec_nopty(struct command_details *details, struct command_status *cstat) /* Free things up. */ free_exec_closure_nopty(&ec); - debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0); + debug_return; } /* diff --git a/src/exec_pty.c b/src/exec_pty.c index b45c2f806..309c9b34b 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -1149,7 +1149,7 @@ free_exec_closure_pty(struct exec_closure_pty *ec) * This is a little bit tricky due to how POSIX job control works and * we fact that we have two different controlling terminals to deal with. */ -int +bool exec_pty(struct command_details *details, struct command_status *cstat) { int io_pipe[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } }; @@ -1169,6 +1169,9 @@ exec_pty(struct command_details *details, struct command_status *cstat) if (pty_setup(details->euid, user_details.tty)) { if (ISSET(details->flags, CD_SET_UTMP)) utmp_user = details->utmp_user ? details->utmp_user : user_details.username; + } else if (TAILQ_EMPTY(&io_plugins)) { + /* Not logging I/O and didn't allocate a pty. */ + debug_return_bool(false); } /* @@ -1332,7 +1335,7 @@ exec_pty(struct command_details *details, struct command_status *cstat) /* Check for early termination or suspend signals before we fork. */ if (sudo_terminated(cstat)) { sigprocmask(SIG_SETMASK, &oset, NULL); - debug_return_int(0); + debug_return_int(true); } ec.monitor_pid = sudo_debug_fork(); @@ -1422,7 +1425,7 @@ exec_pty(struct command_details *details, struct command_status *cstat) TAILQ_FOREACH_SAFE(sigfwd, &ec.sigfwd_list, entries, sigfwd_next) { free(sigfwd); } - debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0); + debug_return_bool(true); } /* diff --git a/src/sudo_exec.h b/src/sudo_exec.h index 1e9cfc72a..42c7102d0 100644 --- a/src/sudo_exec.h +++ b/src/sudo_exec.h @@ -92,10 +92,10 @@ int sudo_execve(int fd, const char *path, char *const argv[], char *envp[], bool char **disable_execute(char *envp[], const char *dso); /* exec_nopty.c */ -int exec_nopty(struct command_details *details, struct command_status *cstat); +void exec_nopty(struct command_details *details, struct command_status *cstat); /* exec_pty.c */ -int exec_pty(struct command_details *details, struct command_status *cstat); +bool exec_pty(struct command_details *details, struct command_status *cstat); void pty_cleanup(void); int pty_make_controlling(void); extern int io_fds[6]; -- 2.40.0