]> granicus.if.org Git - sudo/commitdiff
Do not close error pipe or debug fd via closefrom() as we need them
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 30 Nov 2011 00:51:24 +0000 (19:51 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 30 Nov 2011 00:51:24 +0000 (19:51 -0500)
to report an exec error should one occur.

common/sudo_debug.c
include/sudo_debug.h
src/exec.c
src/exec_pty.c

index a51851fbcfaf977d6add796c66c8b741bf059858..4ec9a4e3fe7fc3a39374c4c5ab8e59fcb406a853 100644 (file)
@@ -398,3 +398,20 @@ sudo_debug_execve2(int level, const char *path, char *const argv[], char *const
     sudo_debug_write(buf, buflen);
     free(buf);
 }
+
+/*
+ * Dup sudo_debug_fd to the specified value so we don't
+ * close it when calling closefrom().
+ */
+int
+sudo_debug_fd_set(int fd)
+{
+    if (sudo_debug_fd != -1 && fd != sudo_debug_fd) {
+       if (dup2(sudo_debug_fd, fd) == -1)
+           return -1;
+       (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
+       close(sudo_debug_fd);
+       sudo_debug_fd = fd;
+    }
+    return sudo_debug_fd;
+}
index f63138f6adad1bd264ec690175dc28a790d980ac..63f12c8adba31fb1401419458bea5c37333e0c82 100644 (file)
@@ -180,6 +180,7 @@ extern const char *const sudo_debug_priorities[];
 extern const char *const sudo_debug_subsystems[];
 
 void sudo_debug_enter(const char *func, const char *file, int line, int subsys);
+void sudo_debug_execve2(int level, const char *path, char *const argv[], char *const envp[]);
 void sudo_debug_exit(const char *func, const char *file, int line, int subsys);
 void sudo_debug_exit_int(const char *func, const char *file, int line, int subsys, int rval);
 void sudo_debug_exit_long(const char *func, const char *file, int line, int subsys, long rval);
@@ -188,9 +189,9 @@ void sudo_debug_exit_bool(const char *func, const char *file, int line, int subs
 void sudo_debug_exit_str(const char *func, const char *file, int line, int subsys, const char *rval);
 void sudo_debug_exit_str_masked(const char *func, const char *file, int line, int subsys, const char *rval);
 void sudo_debug_exit_ptr(const char *func, const char *file, int line, int subsys, const void *rval);
+int sudo_debug_fd_set(int fd);
 int sudo_debug_init(const char *debugfile, const char *settings);
 void sudo_debug_printf2(int level, const char *format, ...) __printflike(2, 3);
 void sudo_debug_write(const char *str, int len);
-void sudo_debug_execve2(int level, const char *path, char *const argv[], char *const envp[]);
 
 #endif /* _SUDO_DEBUG_H */
index 1742887e3168a2bbb5e17715d3a7e1673d08c836..e1129100f1938ae7a17b574177e9a50f8326adee 100644 (file)
@@ -136,8 +136,15 @@ static int fork_cmnd(struct command_details *details, int sv[2])
            /* headed for execve() */
            sudo_debug_execve(SUDO_DEBUG_INFO, details->command,
                details->argv, details->envp);
-           if (details->closefrom >= 0)
-               closefrom(details->closefrom);
+           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);
index 9af4a05feb264824eaefc4ae13ac38b7b2e197f9..8c2350f4ffa4b421ab54103ff116b8ee3a24732b 100644 (file)
@@ -101,7 +101,7 @@ static struct io_buffer *iobufs;
 
 static void flush_output(void);
 static int exec_monitor(struct command_details *details, int backchannel);
-static void exec_pty(struct command_details *detail);
+static void exec_pty(struct command_details *detail, int *errfd);
 static void sigwinch(int s);
 static void sync_ttysize(int src, int dst);
 static void deliver_signal(pid_t pid, int signo);
@@ -936,7 +936,7 @@ exec_monitor(struct command_details *details, int backchannel)
        restore_signals();
 
        /* setup tty and exec command */
-       exec_pty(details);
+       exec_pty(details, &errpipe[1]);
        cstat.type = CMD_ERRNO;
        cstat.val = errno;
        if (write(errpipe[1], &cstat, sizeof(cstat)) == -1)
@@ -1137,7 +1137,7 @@ flush_output(void)
  * Returns only if execve() fails.
  */
 static void
-exec_pty(struct command_details *details)
+exec_pty(struct command_details *details, int *errfd)
 {
     pid_t self = getpid();
     debug_decl(exec_pty, SUDO_DEBUG_EXEC);
@@ -1170,14 +1170,23 @@ exec_pty(struct command_details *details)
     sudo_debug_execve(SUDO_DEBUG_INFO, details->command,
        details->argv, details->envp);
 
-    if (details->closefrom >= 0)
-       closefrom(details->closefrom);
+    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);
     else
 #endif
        my_execve(details->command, details->argv, details->envp);
+    sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s",
+       details->command, strerror(errno));
     debug_return;
 }
 
@@ -1190,7 +1199,7 @@ sync_ttysize(int src, int dst)
 #ifdef TIOCGWINSZ
     struct winsize wsize;
     pid_t pgrp;
-    debug_decl(exec_pty, SUDO_DEBUG_EXEC);
+    debug_decl(sync_ttysize, SUDO_DEBUG_EXEC);
 
     if (ioctl(src, TIOCGWINSZ, &wsize) == 0) {
            ioctl(dst, TIOCSWINSZ, &wsize);