diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index bc5028c23..cfed9cdc1 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -722,12 +722,8 @@ exec_mailer(int pipein) #endif /* NO_ROOT_MAILER */ debug_decl(exec_mailer, SUDOERS_DEBUG_LOGGING) - /* Set stdin to read side of the pipe or clear FD_CLOEXEC */ - if (pipein == STDIN_FILENO) - i = fcntl(pipein, F_SETFD, 0); - else - i = dup2(pipein, STDIN_FILENO); - if (i == -1) { + /* Set stdin to read side of the pipe. */ + if (dup3(pipein, STDIN_FILENO, 0) == -1) { mysyslog(LOG_ERR, _("unable to dup stdin: %m")); sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to dup stdin: %s", strerror(errno)); diff --git a/src/exec_monitor.c b/src/exec_monitor.c index 020fe3b7b..cdecb9b86 100644 --- a/src/exec_monitor.c +++ b/src/exec_monitor.c @@ -404,33 +404,18 @@ 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 (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]); - } else { - if (fcntl(io_fds[SFD_STDIN], F_SETFD, 0) == -1) - sudo_fatal("fcntl"); - } - 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]); - } else { - if (fcntl(io_fds[SFD_STDOUT], F_SETFD, 0) == -1) - sudo_fatal("fcntl"); - } - 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]); - } else { - if (fcntl(io_fds[SFD_STDERR], F_SETFD, 0) == -1) - sudo_fatal("fcntl"); - } + if (dup3(io_fds[SFD_STDIN], STDIN_FILENO, 0) == -1) + sudo_fatal("dup3"); + if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE]) + close(io_fds[SFD_STDIN]); + if (dup3(io_fds[SFD_STDOUT], STDOUT_FILENO, 0) == -1) + sudo_fatal("dup3"); + if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE]) + close(io_fds[SFD_STDOUT]); + if (dup3(io_fds[SFD_STDERR], STDERR_FILENO, 0) == -1) + sudo_fatal("dup3"); + if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE]) + close(io_fds[SFD_STDERR]); /* Wait for parent to grant us the tty if we are foreground. */ if (foreground && !ISSET(details->flags, CD_EXEC_BG)) { diff --git a/src/selinux.c b/src/selinux.c index ae37355aa..678b8d4b8 100644 --- a/src/selinux.c +++ b/src/selinux.c @@ -227,6 +227,8 @@ relabel_tty(const char *ttyn, int ptyfd) } if (ptyfd != -1) { + int oflags, flags = 0; + /* Reopen pty that was relabeled, std{in,out,err} are reset later. */ se_state.ttyfd = open(ttyn, O_RDWR|O_NOCTTY, 0); if (se_state.ttyfd == -1 || fstat(se_state.ttyfd, &sb) == -1) { @@ -238,8 +240,21 @@ relabel_tty(const char *ttyn, int ptyfd) ttyn); goto bad; } - if (dup2(se_state.ttyfd, ptyfd) == -1) { - sudo_warn("dup2"); + /* Preserve O_NONBLOCK and the close-on-exec flags. */ + if ((oflags = fcntl(ptyfd, F_GETFL)) == -1) { + sudo_warn("F_GETFL"); + goto bad; + } + if (ISSET(oflags, O_NONBLOCK)) + flags |= O_NONBLOCK; + if ((oflags = fcntl(ptyfd, F_GETFD)) == -1) { + sudo_warn("F_GETFD"); + goto bad; + } + if (ISSET(oflags, FD_CLOEXEC)) + flags |= O_CLOEXEC; + if (dup3(se_state.ttyfd, ptyfd, flags) == -1) { + sudo_warn("dup3"); goto bad; } } else { diff --git a/src/tgetpass.c b/src/tgetpass.c index 7464fdd07..69cecd077 100644 --- a/src/tgetpass.c +++ b/src/tgetpass.c @@ -311,17 +311,10 @@ sudo_askpass(const char *askpass, const char *prompt) sudo_fatal(U_("unable to fork")); if (child == 0) { - /* child, set stdout to write side of the pipe or clear FD_CLOEXEC */ - if (pfd[1] == STDOUT_FILENO) { - if (fcntl(pfd[1], F_SETFD, 0) == -1) { - sudo_warn("fcntl"); - _exit(255); - } - } else { - if (dup2(pfd[1], STDOUT_FILENO) == -1) { - sudo_warn("dup2"); - _exit(255); - } + /* child, set stdout to write side of the pipe */ + if (dup3(pfd[1], STDOUT_FILENO, 0) == -1) { + sudo_warn("dup3"); + _exit(255); } if (setuid(ROOT_UID) == -1) sudo_warn("setuid(%d)", ROOT_UID);