]> granicus.if.org Git - sudo/commitdiff
If any of std{in,out,err} are not hooked up to a tty only interpose
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 5 May 2017 20:27:42 +0000 (14:27 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 5 May 2017 20:27:42 +0000 (14:27 -0600)
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.

src/exec_monitor.c
src/exec_pty.c

index 15e6ff8935db77d319f94a6e693a0df7de2c0952..f8a21a5cab910e110bd9d6f7c7f59606b084d048 100644 (file)
@@ -390,10 +390,26 @@ exec_cmnd_pty(struct command_details *details, bool foreground, int errfd)
     setpgid(0, self);
 
     /* Wire up standard fds, note that stdout/stderr may be pipes. */
-    if (dup2(io_fds[SFD_STDIN], STDIN_FILENO) == -1 ||
-       dup2(io_fds[SFD_STDOUT], STDOUT_FILENO) == -1 ||
-       dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1)
-       sudo_fatal("dup2");
+    if (io_fds[SFD_STDIN] != STDIN_FILENO) {
+       if (dup2(io_fds[SFD_STDIN], STDIN_FILENO) == -1)
+           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. */
     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);
     }
 
-    /* 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. */
     exec_cmnd(details, errfd);
 
index 4a05ee01249c0da01edff58aca18e088671ff6d9..7e30b66e2c532e3c75c0108021c1b2cfd982d331 100644 (file)
@@ -642,8 +642,10 @@ io_buf_new(int rfd, int wfd,
 static int
 fork_pty(struct command_details *details, int sv[], sigset_t *omask)
 {
+    struct plugin_container *plugin;
     struct command_status cstat;
     int io_pipe[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } };
+    bool interpose[3] = { false, false, false };
     sigaction_t sa;
     sigset_t mask;
     pid_t child;
@@ -669,6 +671,16 @@ fork_pty(struct command_details *details, int sv[], sigset_t *omask)
     sigaddset(&ttyblock, SIGTTIN);
     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.
      * 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
-     * to interpose ourselves instead of duping the pty fd.
+     * If stdin, stdout or stderr is not a tty and logging is enabled,
+     * use a pipe to interpose ourselves instead of using the pty fd.
      */
     if (io_fds[SFD_STDIN] == -1 || !isatty(STDIN_FILENO)) {
-       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 (!interpose[STDIN_FILENO]) {
+           /* Not logging stdin, do not interpose. */
+           sudo_debug_printf(SUDO_DEBUG_INFO,
+               "stdin not a tty, not logging");
+           io_fds[SFD_STDIN] = dup(STDIN_FILENO);
+           if (io_fds[SFD_STDIN] == -1)
+               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)) {
-       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 (!interpose[STDOUT_FILENO]) {
+           /* Not logging stdout, do not interpose. */
+           sudo_debug_printf(SUDO_DEBUG_INFO,
+               "stdout not a tty, not logging");
+           io_fds[SFD_STDOUT] = dup(STDOUT_FILENO);
+           if (io_fds[SFD_STDOUT] == -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)) {
-       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 (!interpose[STDERR_FILENO]) {
+           /* Not logging stderr, do not interpose. */
+           sudo_debug_printf(SUDO_DEBUG_INFO,
+               "stderr not a tty, not logging");
+           io_fds[SFD_STDERR] = dup(STDERR_FILENO);
+           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) {