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);
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;
}
/*
tq_remove(&sigfwd_list, sigfwd);
efree(sigfwd);
}
-
+done:
debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0);
}
# include <priv.h>
#endif
#include <errno.h>
+#include <fcntl.h>
#include <signal.h>
#include "sudo.h"
}
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;
+}
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);
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);
}
* 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);
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;
}
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);
};
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[],