to report an exec error should one occur.
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;
+}
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);
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 */
/* 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);
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);
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)
* 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);
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;
}
#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);