From 5cb928c512f7edfa18b581b5e1b700cc3d9e07d4 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 23 Feb 2013 14:19:07 -0500 Subject: [PATCH] If the policy plugin does not provide a close function, there is no command timeout and no pty is required, skip the event loop and just exec the command directly. --- src/exec.c | 37 +++++++------------------------------ src/exec_common.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/exec_pty.c | 37 ++++++++----------------------------- src/sudo_exec.h | 2 ++ src/sudo_plugin_int.h | 2 +- 5 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/exec.c b/src/exec.c index 41f7e2f98..10199c20d 100644 --- a/src/exec.c +++ b/src/exec.c @@ -137,35 +137,7 @@ static int fork_cmnd(struct command_details *details, int sv[2]) close(signal_pipe[0]); close(signal_pipe[1]); fcntl(sv[1], F_SETFD, FD_CLOEXEC); - restore_signals(); - if (exec_setup(details, NULL, -1) == true) { - /* headed for execve() */ - sudo_debug_execve(SUDO_DEBUG_INFO, details->command, - details->argv, details->envp); - if (details->closefrom >= 0) { - int maxfd = details->closefrom; - dup2(sv[1], maxfd); - (void)fcntl(maxfd, F_SETFD, FD_CLOEXEC); - sv[1] = maxfd++; - if (sudo_debug_fd_set(maxfd) != -1) - maxfd++; - closefrom(maxfd); - } -#ifdef HAVE_SELINUX - if (ISSET(details->flags, CD_RBAC_ENABLED)) { - selinux_execve(details->command, details->argv, details->envp, - ISSET(details->flags, CD_NOEXEC)); - } else -#endif - { - sudo_execve(details->command, details->argv, details->envp, - ISSET(details->flags, CD_NOEXEC)); - } - sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s", - details->command, strerror(errno)); - } - cstat.type = CMD_ERRNO; - cstat.val = errno; + exec_cmnd(details, &cstat, &sv[1]); send(sv[1], &cstat, sizeof(cstat), 0); sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 1); _exit(1); @@ -224,6 +196,11 @@ sudo_execute(struct command_details *details, struct command_status *cstat) utmp_user = details->utmp_user ? details->utmp_user : user_details.username; sudo_debug_printf(SUDO_DEBUG_INFO, "allocate pty for I/O logging"); pty_setup(details->euid, user_details.tty, utmp_user); + } else if (!ISSET(details->flags, CD_SET_TIMEOUT) && + policy_plugin.u.policy->close == NULL) { + /* If no I/O logging, timeout or policy close we can exec directly. */ + exec_cmnd(details, cstat, NULL); + goto done; } /* @@ -432,7 +409,7 @@ do_tty_io: tq_remove(&sigfwd_list, sigfwd); efree(sigfwd); } - +done: debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0); } diff --git a/src/exec_common.c b/src/exec_common.c index 045c702de..e23b628d1 100644 --- a/src/exec_common.c +++ b/src/exec_common.c @@ -39,6 +39,7 @@ # include #endif #include +#include #include #include "sudo.h" @@ -156,3 +157,44 @@ sudo_execve(const char *path, char *const argv[], char *const envp[], int noexec } return -1; } + +void +exec_cmnd(struct command_details *details, struct command_status *cstat, + int *errfd) +{ + debug_decl(exec_cmnd, SUDO_DEBUG_EXEC) + + restore_signals(); + if (exec_setup(details, NULL, -1) == true) { + /* headed for execve() */ + sudo_debug_execve(SUDO_DEBUG_INFO, details->command, + details->argv, details->envp); + if (details->closefrom >= 0) { + int maxfd = details->closefrom; + /* Preserve back channel if present. */ + if (errfd != NULL) { + dup2(*errfd, maxfd); + (void)fcntl(maxfd, F_SETFD, FD_CLOEXEC); + *errfd = maxfd++; + } + if (sudo_debug_fd_set(maxfd) != -1) + maxfd++; + closefrom(maxfd); + } +#ifdef HAVE_SELINUX + if (ISSET(details->flags, CD_RBAC_ENABLED)) { + selinux_execve(details->command, details->argv, details->envp, + ISSET(details->flags, CD_NOEXEC)); + } else +#endif + { + sudo_execve(details->command, details->argv, details->envp, + ISSET(details->flags, CD_NOEXEC)); + } + cstat->type = CMD_ERRNO; + cstat->val = errno; + sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s", + details->command, strerror(errno)); + } + debug_return; +} diff --git a/src/exec_pty.c b/src/exec_pty.c index 243012a33..c7cca8132 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -98,7 +98,8 @@ static struct io_buffer *iobufs; static void flush_output(void); static int exec_monitor(struct command_details *details, int backchannel); -static void exec_pty(struct command_details *detail, int *errfd); +static void exec_pty(struct command_details *details, + struct command_status *cstat, int *errfd); static void sigwinch(int s); static void sync_ttysize(int src, int dst); static void deliver_signal(pid_t pid, int signo, bool from_parent); @@ -1077,9 +1078,7 @@ exec_monitor(struct command_details *details, int backchannel) restore_signals(); /* setup tty and exec command */ - exec_pty(details, &errpipe[1]); - cstat.type = CMD_ERRNO; - cstat.val = errno; + exec_pty(details, &cstat, &errpipe[1]); ignore_result(write(errpipe[1], &cstat, sizeof(cstat))); _exit(1); } @@ -1283,7 +1282,8 @@ flush_output(void) * Returns only if execve() fails. */ static void -exec_pty(struct command_details *details, int *errfd) +exec_pty(struct command_details *details, + struct command_status *cstat, int *errfd) { pid_t self = getpid(); debug_decl(exec_pty, SUDO_DEBUG_EXEC); @@ -1316,30 +1316,9 @@ exec_pty(struct command_details *details, int *errfd) if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE]) close(io_fds[SFD_STDERR]); - sudo_debug_execve(SUDO_DEBUG_INFO, details->command, - details->argv, details->envp); - - if (details->closefrom >= 0) { - int maxfd = details->closefrom; - dup2(*errfd, maxfd); - (void)fcntl(maxfd, F_SETFD, FD_CLOEXEC); - *errfd = maxfd++; - if (sudo_debug_fd_set(maxfd) != -1) - maxfd++; - closefrom(maxfd); - } -#ifdef HAVE_SELINUX - if (ISSET(details->flags, CD_RBAC_ENABLED)) { - selinux_execve(details->command, details->argv, details->envp, - ISSET(details->flags, CD_NOEXEC)); - } else -#endif - { - sudo_execve(details->command, details->argv, details->envp, - ISSET(details->flags, CD_NOEXEC)); - } - sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s", - details->command, strerror(errno)); + /* Execute command; only returns on error. */ + exec_cmnd(details, cstat, errfd); + debug_return; } diff --git a/src/sudo_exec.h b/src/sudo_exec.h index ec8450db9..5a0277cd8 100644 --- a/src/sudo_exec.h +++ b/src/sudo_exec.h @@ -54,6 +54,8 @@ struct command_status; int fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask); int perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat); int suspend_parent(int signo); +void exec_cmnd(struct command_details *details, struct command_status *cstat, + int *errfd); void fd_set_iobs(fd_set *fdsr, fd_set *fdsw); #ifdef SA_SIGINFO void handler(int s, siginfo_t *info, void *context); diff --git a/src/sudo_plugin_int.h b/src/sudo_plugin_int.h index aff2344fb..bed15c686 100644 --- a/src/sudo_plugin_int.h +++ b/src/sudo_plugin_int.h @@ -97,7 +97,7 @@ struct plugin_container { }; TQ_DECLARE(plugin_container) -extern struct plugin_container_list policy_plugins; +extern struct plugin_container policy_plugin; extern struct plugin_container_list io_plugins; int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], -- 2.50.1