If any of std{in,out,err} are not hooked up to a tty only interpose
ourselves with a pipe if the plugin will actually log the data. This avoids a problem with non-interactive commands where no tty is present where sudo will consume stdin even when log_input is not enabled in sudoers.
This commit is contained in:
@@ -390,10 +390,26 @@ exec_cmnd_pty(struct command_details *details, bool foreground, int errfd)
|
|||||||
setpgid(0, self);
|
setpgid(0, self);
|
||||||
|
|
||||||
/* Wire up standard fds, note that stdout/stderr may be pipes. */
|
/* Wire up standard fds, note that stdout/stderr may be pipes. */
|
||||||
if (dup2(io_fds[SFD_STDIN], STDIN_FILENO) == -1 ||
|
if (io_fds[SFD_STDIN] != STDIN_FILENO) {
|
||||||
dup2(io_fds[SFD_STDOUT], STDOUT_FILENO) == -1 ||
|
if (dup2(io_fds[SFD_STDIN], STDIN_FILENO) == -1)
|
||||||
dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1)
|
sudo_fatal("dup2");
|
||||||
sudo_fatal("dup2");
|
if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE])
|
||||||
|
close(io_fds[SFD_STDIN]);
|
||||||
|
}
|
||||||
|
if (io_fds[SFD_STDOUT] != STDOUT_FILENO) {
|
||||||
|
if (dup2(io_fds[SFD_STDOUT], STDOUT_FILENO) == -1)
|
||||||
|
sudo_fatal("dup2");
|
||||||
|
if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE])
|
||||||
|
close(io_fds[SFD_STDOUT]);
|
||||||
|
}
|
||||||
|
if (io_fds[SFD_STDERR] != STDERR_FILENO) {
|
||||||
|
if (dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1)
|
||||||
|
sudo_fatal("dup2");
|
||||||
|
if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE])
|
||||||
|
close(io_fds[SFD_STDERR]);
|
||||||
|
}
|
||||||
|
if (io_fds[SFD_SLAVE] != -1)
|
||||||
|
close(io_fds[SFD_SLAVE]);
|
||||||
|
|
||||||
/* Wait for parent to grant us the tty if we are foreground. */
|
/* Wait for parent to grant us the tty if we are foreground. */
|
||||||
if (foreground && !ISSET(details->flags, CD_EXEC_BG)) {
|
if (foreground && !ISSET(details->flags, CD_EXEC_BG)) {
|
||||||
@@ -402,16 +418,6 @@ exec_cmnd_pty(struct command_details *details, bool foreground, int errfd)
|
|||||||
nanosleep(&ts, NULL);
|
nanosleep(&ts, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have guaranteed that the slave fd is > 2 */
|
|
||||||
if (io_fds[SFD_SLAVE] != -1)
|
|
||||||
close(io_fds[SFD_SLAVE]);
|
|
||||||
if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE])
|
|
||||||
close(io_fds[SFD_STDIN]);
|
|
||||||
if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE])
|
|
||||||
close(io_fds[SFD_STDOUT]);
|
|
||||||
if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE])
|
|
||||||
close(io_fds[SFD_STDERR]);
|
|
||||||
|
|
||||||
/* Execute command; only returns on error. */
|
/* Execute command; only returns on error. */
|
||||||
exec_cmnd(details, errfd);
|
exec_cmnd(details, errfd);
|
||||||
|
|
||||||
|
@@ -642,8 +642,10 @@ io_buf_new(int rfd, int wfd,
|
|||||||
static int
|
static int
|
||||||
fork_pty(struct command_details *details, int sv[], sigset_t *omask)
|
fork_pty(struct command_details *details, int sv[], sigset_t *omask)
|
||||||
{
|
{
|
||||||
|
struct plugin_container *plugin;
|
||||||
struct command_status cstat;
|
struct command_status cstat;
|
||||||
int io_pipe[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } };
|
int io_pipe[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } };
|
||||||
|
bool interpose[3] = { false, false, false };
|
||||||
sigaction_t sa;
|
sigaction_t sa;
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
pid_t child;
|
pid_t child;
|
||||||
@@ -669,6 +671,16 @@ fork_pty(struct command_details *details, int sv[], sigset_t *omask)
|
|||||||
sigaddset(&ttyblock, SIGTTIN);
|
sigaddset(&ttyblock, SIGTTIN);
|
||||||
sigaddset(&ttyblock, SIGTTOU);
|
sigaddset(&ttyblock, SIGTTOU);
|
||||||
|
|
||||||
|
/* Determine whether any of std{in,out,err} should be logged. */
|
||||||
|
TAILQ_FOREACH(plugin, &io_plugins, entries) {
|
||||||
|
if (plugin->u.io->log_stdin)
|
||||||
|
interpose[STDIN_FILENO] = true;
|
||||||
|
if (plugin->u.io->log_stdout)
|
||||||
|
interpose[STDOUT_FILENO] = true;
|
||||||
|
if (plugin->u.io->log_stderr)
|
||||||
|
interpose[STDERR_FILENO] = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup stdin/stdout/stderr for child, to be duped after forking.
|
* Setup stdin/stdout/stderr for child, to be duped after forking.
|
||||||
* In background mode there is no stdin.
|
* In background mode there is no stdin.
|
||||||
@@ -694,34 +706,64 @@ fork_pty(struct command_details *details, int sv[], sigset_t *omask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If either stdin, stdout or stderr is not a tty we use a pipe
|
* If stdin, stdout or stderr is not a tty and logging is enabled,
|
||||||
* to interpose ourselves instead of duping the pty fd.
|
* use a pipe to interpose ourselves instead of using the pty fd.
|
||||||
*/
|
*/
|
||||||
if (io_fds[SFD_STDIN] == -1 || !isatty(STDIN_FILENO)) {
|
if (io_fds[SFD_STDIN] == -1 || !isatty(STDIN_FILENO)) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO, "stdin not a tty, creating a pipe");
|
if (!interpose[STDIN_FILENO]) {
|
||||||
pipeline = true;
|
/* Not logging stdin, do not interpose. */
|
||||||
if (pipe(io_pipe[STDIN_FILENO]) != 0)
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
sudo_fatal(U_("unable to create pipe"));
|
"stdin not a tty, not logging");
|
||||||
io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
|
io_fds[SFD_STDIN] = dup(STDIN_FILENO);
|
||||||
log_stdin, &iobufs);
|
if (io_fds[SFD_STDIN] == -1)
|
||||||
io_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
|
sudo_fatal("dup");
|
||||||
|
} else {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
|
"stdin not a tty, creating a pipe");
|
||||||
|
pipeline = true;
|
||||||
|
if (pipe(io_pipe[STDIN_FILENO]) != 0)
|
||||||
|
sudo_fatal(U_("unable to create pipe"));
|
||||||
|
io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
|
||||||
|
log_stdin, &iobufs);
|
||||||
|
io_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (io_fds[SFD_STDOUT] == -1 || !isatty(STDOUT_FILENO)) {
|
if (io_fds[SFD_STDOUT] == -1 || !isatty(STDOUT_FILENO)) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO, "stdout not a tty, creating a pipe");
|
if (!interpose[STDOUT_FILENO]) {
|
||||||
pipeline = true;
|
/* Not logging stdout, do not interpose. */
|
||||||
if (pipe(io_pipe[STDOUT_FILENO]) != 0)
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
sudo_fatal(U_("unable to create pipe"));
|
"stdout not a tty, not logging");
|
||||||
io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
|
io_fds[SFD_STDOUT] = dup(STDOUT_FILENO);
|
||||||
log_stdout, &iobufs);
|
if (io_fds[SFD_STDOUT] == -1)
|
||||||
io_fds[SFD_STDOUT] = io_pipe[STDOUT_FILENO][1];
|
sudo_fatal("dup");
|
||||||
|
} else {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
|
"stdout not a tty, creating a pipe");
|
||||||
|
pipeline = true;
|
||||||
|
if (pipe(io_pipe[STDOUT_FILENO]) != 0)
|
||||||
|
sudo_fatal(U_("unable to create pipe"));
|
||||||
|
io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
|
||||||
|
log_stdout, &iobufs);
|
||||||
|
io_fds[SFD_STDOUT] = io_pipe[STDOUT_FILENO][1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (io_fds[SFD_STDERR] == -1 || !isatty(STDERR_FILENO)) {
|
if (io_fds[SFD_STDERR] == -1 || !isatty(STDERR_FILENO)) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO, "stderr not a tty, creating a pipe");
|
if (!interpose[STDERR_FILENO]) {
|
||||||
if (pipe(io_pipe[STDERR_FILENO]) != 0)
|
/* Not logging stderr, do not interpose. */
|
||||||
sudo_fatal(U_("unable to create pipe"));
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO,
|
"stderr not a tty, not logging");
|
||||||
log_stderr, &iobufs);
|
io_fds[SFD_STDERR] = dup(STDERR_FILENO);
|
||||||
io_fds[SFD_STDERR] = io_pipe[STDERR_FILENO][1];
|
if (io_fds[SFD_STDERR] == -1)
|
||||||
|
sudo_fatal("dup");
|
||||||
|
} else {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
|
"stderr not a tty, creating a pipe");
|
||||||
|
if (pipe(io_pipe[STDERR_FILENO]) != 0)
|
||||||
|
sudo_fatal(U_("unable to create pipe"));
|
||||||
|
io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO,
|
||||||
|
log_stderr, &iobufs);
|
||||||
|
io_fds[SFD_STDERR] = io_pipe[STDERR_FILENO][1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
|
Reference in New Issue
Block a user