From 3c9e5f28fc8ba0f14dde2f4c0ddecff0555c8d05 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 31 May 2011 12:49:22 -0400 Subject: [PATCH] Fix compressed io log corruption in background mode by using _exit() instead of exit() to avoid flushing buffers twice. Improved background mode support. When not allocating a pty, the command is run in its own process group. This prevents write access to the tty. When running in a pty, stdin is not hooked up and we never read from /dev/tty, which results in similar behavior. --- src/exec.c | 11 +++++------ src/exec_pty.c | 14 +++++++++----- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/exec.c b/src/exec.c index 3551ba531..52dbdbb1d 100644 --- a/src/exec.c +++ b/src/exec.c @@ -216,20 +216,19 @@ sudo_execve(struct command_details *details, struct command_status *cstat) cstat->val = errno; return -1; case 0: - /* child continues in a new session in a different pty */ - SET(details->flags, CD_USE_PTY); - (void)setsid(); + /* child continues without controlling terminal */ + (void)setpgid(0, 0); break; default: - /* parent exits */ - exit(0); + /* parent exits (but does not flush buffers) */ + _exit(0); } } /* * If we have an I/O plugin or the policy plugin has requested one, we * need to allocate a pty. It is OK to set log_io in the pty-only case - * as the tailqueue plugin will be empty and no I/O logging will occur. + * as the io plugin tailqueue will be empty and no I/O logging will occur. */ if (!tq_empty(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) { log_io = TRUE; diff --git a/src/exec_pty.c b/src/exec_pty.c index 44d251f4c..b24d691b6 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -493,17 +493,21 @@ fork_pty(struct command_details *details, int sv[], int *maxfd) /* * Setup stdin/stdout/stderr for child, to be duped after forking. + * In background mode there is no stdin. */ - io_fds[SFD_STDIN] = io_fds[SFD_SLAVE]; + if (!ISSET(details->flags, CD_BACKGROUND)) + io_fds[SFD_STDIN] = io_fds[SFD_SLAVE]; io_fds[SFD_STDOUT] = io_fds[SFD_SLAVE]; io_fds[SFD_STDERR] = io_fds[SFD_SLAVE]; - /* Copy /dev/tty -> pty master */ if (io_fds[SFD_USERTTY] != -1) { - iobufs = io_buf_new(io_fds[SFD_USERTTY], io_fds[SFD_MASTER], - log_ttyin, iobufs); + /* Read from /dev/tty, write to pty master */ + if (!ISSET(details->flags, CD_BACKGROUND)) { + iobufs = io_buf_new(io_fds[SFD_USERTTY], io_fds[SFD_MASTER], + log_ttyin, iobufs); + } - /* Copy pty master -> /dev/tty */ + /* Read from pty master, write to /dev/tty */ iobufs = io_buf_new(io_fds[SFD_MASTER], io_fds[SFD_USERTTY], log_ttyout, iobufs);