Rename script_execve to sudo_execve and rename script_foo in exec.c
This commit is contained in:
190
src/exec.c
190
src/exec.c
@@ -107,17 +107,17 @@ struct io_buffer {
|
|||||||
char buf[16 * 1024];
|
char buf[16 * 1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
static int script_fds[6] = { -1, -1, -1, -1, -1, -1};
|
static int io_fds[6] = { -1, -1, -1, -1, -1, -1};
|
||||||
static int pipeline = FALSE;
|
static int pipeline = FALSE;
|
||||||
|
|
||||||
static sig_atomic_t recvsig[NSIG];
|
static sig_atomic_t recvsig[NSIG];
|
||||||
static sig_atomic_t ttymode = TERM_COOKED;
|
|
||||||
static sig_atomic_t tty_initialized = 0;
|
|
||||||
|
|
||||||
static sigset_t ttyblock;
|
static sigset_t ttyblock;
|
||||||
|
|
||||||
static pid_t ppgrp, child;
|
static pid_t ppgrp, child;
|
||||||
static int foreground;
|
static int foreground;
|
||||||
|
static int ttymode = TERM_COOKED;
|
||||||
|
static int tty_initialized;
|
||||||
|
|
||||||
static char slavename[PATH_MAX];
|
static char slavename[PATH_MAX];
|
||||||
|
|
||||||
@@ -127,23 +127,23 @@ static int perform_io(struct io_buffer *iobufs, fd_set *fdsr, fd_set *fdsw);
|
|||||||
static void handler(int s);
|
static void handler(int s);
|
||||||
static int my_execve(const char *path, char *const argv[],
|
static int my_execve(const char *path, char *const argv[],
|
||||||
char *const envp[]);
|
char *const envp[]);
|
||||||
static int script_child(struct command_details *details, char *argv[],
|
static int exec_monitor(struct command_details *details, char *argv[],
|
||||||
char *envp[], int, int);
|
char *envp[], int, int);
|
||||||
static void script_run(struct command_details *detail, char *argv[],
|
static void exec_pty(struct command_details *detail, char *argv[],
|
||||||
char *envp[], int);
|
char *envp[], int);
|
||||||
static void sigwinch(int s);
|
static void sigwinch(int s);
|
||||||
static void sync_ttysize(int src, int dst);
|
static void sync_ttysize(int src, int dst);
|
||||||
static void deliver_signal(pid_t pid, int signo);
|
static void deliver_signal(pid_t pid, int signo);
|
||||||
static int safe_close(int fd);
|
static int safe_close(int fd);
|
||||||
|
|
||||||
extern struct user_details user_details; /* XXX */
|
extern struct user_details user_details; /* XXX need tty name for SELinux */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pty_setup(uid_t uid)
|
pty_setup(uid_t uid)
|
||||||
{
|
{
|
||||||
script_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
|
io_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
|
||||||
if (script_fds[SFD_USERTTY] != -1) {
|
if (io_fds[SFD_USERTTY] != -1) {
|
||||||
if (!get_pty(&script_fds[SFD_MASTER], &script_fds[SFD_SLAVE],
|
if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE],
|
||||||
slavename, sizeof(slavename), uid))
|
slavename, sizeof(slavename), uid))
|
||||||
error(1, "Can't get pty");
|
error(1, "Can't get pty");
|
||||||
}
|
}
|
||||||
@@ -267,12 +267,12 @@ log_stderr(char *buf, unsigned int n)
|
|||||||
static void
|
static void
|
||||||
check_foreground(void)
|
check_foreground(void)
|
||||||
{
|
{
|
||||||
if (script_fds[SFD_USERTTY] != -1) {
|
if (io_fds[SFD_USERTTY] != -1) {
|
||||||
foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == ppgrp;
|
foreground = tcgetpgrp(io_fds[SFD_USERTTY]) == ppgrp;
|
||||||
if (foreground && !tty_initialized) {
|
if (foreground && !tty_initialized) {
|
||||||
if (term_copy(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE])) {
|
if (term_copy(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE])) {
|
||||||
tty_initialized = 1;
|
tty_initialized = 1;
|
||||||
sync_ttysize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]);
|
sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,7 +300,7 @@ suspend_parent(int signo, struct io_buffer *iobufs)
|
|||||||
if (foreground) {
|
if (foreground) {
|
||||||
if (ttymode != TERM_RAW) {
|
if (ttymode != TERM_RAW) {
|
||||||
do {
|
do {
|
||||||
n = term_raw(script_fds[SFD_USERTTY], 0);
|
n = term_raw(io_fds[SFD_USERTTY], 0);
|
||||||
} while (!n && errno == EINTR);
|
} while (!n && errno == EINTR);
|
||||||
ttymode = TERM_RAW;
|
ttymode = TERM_RAW;
|
||||||
}
|
}
|
||||||
@@ -317,7 +317,7 @@ suspend_parent(int signo, struct io_buffer *iobufs)
|
|||||||
/* Restore original tty mode before suspending. */
|
/* Restore original tty mode before suspending. */
|
||||||
if (oldmode != TERM_COOKED) {
|
if (oldmode != TERM_COOKED) {
|
||||||
do {
|
do {
|
||||||
n = term_restore(script_fds[SFD_USERTTY], 0);
|
n = term_restore(io_fds[SFD_USERTTY], 0);
|
||||||
} while (!n && errno == EINTR);
|
} while (!n && errno == EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +341,7 @@ suspend_parent(int signo, struct io_buffer *iobufs)
|
|||||||
if (foreground) {
|
if (foreground) {
|
||||||
/* Set raw mode. */
|
/* Set raw mode. */
|
||||||
do {
|
do {
|
||||||
n = term_raw(script_fds[SFD_USERTTY], 0);
|
n = term_raw(io_fds[SFD_USERTTY], 0);
|
||||||
} while (!n && errno == EINTR);
|
} while (!n && errno == EINTR);
|
||||||
} else {
|
} else {
|
||||||
/* Background process, no access to tty. */
|
/* Background process, no access to tty. */
|
||||||
@@ -486,7 +486,7 @@ perform_io(struct io_buffer *iobufs, fd_set *fdsr, fd_set *fdsw)
|
|||||||
* controlling tty, belongs to child's session but has its own pgrp.
|
* controlling tty, belongs to child's session but has its own pgrp.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
script_execve(struct command_details *details, char *argv[], char *envp[],
|
sudo_execve(struct command_details *details, char *argv[], char *envp[],
|
||||||
struct command_status *cstat)
|
struct command_status *cstat)
|
||||||
{
|
{
|
||||||
sigaction_t sa;
|
sigaction_t sa;
|
||||||
@@ -510,7 +510,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
if (rbac_enabled) {
|
if (rbac_enabled) {
|
||||||
/* Must do SELinux setup before changing uid. */
|
/* Must do SELinux setup before changing uid. */
|
||||||
selinux_setup(details->selinux_role, details->selinux_type,
|
selinux_setup(details->selinux_role, details->selinux_type,
|
||||||
log_io ? slavename : user_details.tty, script_fds[SFD_SLAVE]);
|
log_io ? slavename : user_details.tty, io_fds[SFD_SLAVE]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -538,7 +538,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
sigaction(SIGTERM, &sa, NULL);
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
|
||||||
if (log_io) {
|
if (log_io) {
|
||||||
if (script_fds[SFD_USERTTY] != -1) {
|
if (io_fds[SFD_USERTTY] != -1) {
|
||||||
sa.sa_flags = SA_RESTART;
|
sa.sa_flags = SA_RESTART;
|
||||||
sa.sa_handler = sigwinch;
|
sa.sa_handler = sigwinch;
|
||||||
sigaction(SIGWINCH, &sa, NULL);
|
sigaction(SIGWINCH, &sa, NULL);
|
||||||
@@ -555,21 +555,21 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
/*
|
/*
|
||||||
* Setup stdin/stdout/stderr for child, to be duped after forking.
|
* Setup stdin/stdout/stderr for child, to be duped after forking.
|
||||||
*/
|
*/
|
||||||
script_fds[SFD_STDIN] = script_fds[SFD_SLAVE];
|
io_fds[SFD_STDIN] = io_fds[SFD_SLAVE];
|
||||||
script_fds[SFD_STDOUT] = script_fds[SFD_SLAVE];
|
io_fds[SFD_STDOUT] = io_fds[SFD_SLAVE];
|
||||||
script_fds[SFD_STDERR] = script_fds[SFD_SLAVE];
|
io_fds[SFD_STDERR] = io_fds[SFD_SLAVE];
|
||||||
|
|
||||||
/* Copy /dev/tty -> pty master */
|
/* Copy /dev/tty -> pty master */
|
||||||
if (script_fds[SFD_USERTTY] != -1) {
|
if (io_fds[SFD_USERTTY] != -1) {
|
||||||
iobufs = io_buf_new(script_fds[SFD_USERTTY], script_fds[SFD_MASTER],
|
iobufs = io_buf_new(io_fds[SFD_USERTTY], io_fds[SFD_MASTER],
|
||||||
log_ttyin, iobufs);
|
log_ttyin, iobufs);
|
||||||
|
|
||||||
/* Copy pty master -> /dev/tty */
|
/* Copy pty master -> /dev/tty */
|
||||||
iobufs = io_buf_new(script_fds[SFD_MASTER], script_fds[SFD_USERTTY],
|
iobufs = io_buf_new(io_fds[SFD_MASTER], io_fds[SFD_USERTTY],
|
||||||
log_ttyout, iobufs);
|
log_ttyout, iobufs);
|
||||||
|
|
||||||
/* Are we the foreground process? */
|
/* Are we the foreground process? */
|
||||||
foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == ppgrp;
|
foreground = tcgetpgrp(io_fds[SFD_USERTTY]) == ppgrp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -583,7 +583,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
error(1, "unable to create pipe");
|
error(1, "unable to create pipe");
|
||||||
iobufs = io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
|
iobufs = io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
|
||||||
log_stdin, iobufs);
|
log_stdin, iobufs);
|
||||||
script_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
|
io_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
|
||||||
}
|
}
|
||||||
if (!isatty(STDOUT_FILENO)) {
|
if (!isatty(STDOUT_FILENO)) {
|
||||||
pipeline = TRUE;
|
pipeline = TRUE;
|
||||||
@@ -591,14 +591,14 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
error(1, "unable to create pipe");
|
error(1, "unable to create pipe");
|
||||||
iobufs = io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
|
iobufs = io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
|
||||||
log_stdout, iobufs);
|
log_stdout, iobufs);
|
||||||
script_fds[SFD_STDOUT] = io_pipe[STDOUT_FILENO][1];
|
io_fds[SFD_STDOUT] = io_pipe[STDOUT_FILENO][1];
|
||||||
}
|
}
|
||||||
if (!isatty(STDERR_FILENO)) {
|
if (!isatty(STDERR_FILENO)) {
|
||||||
if (pipe(io_pipe[STDERR_FILENO]) != 0)
|
if (pipe(io_pipe[STDERR_FILENO]) != 0)
|
||||||
error(1, "unable to create pipe");
|
error(1, "unable to create pipe");
|
||||||
iobufs = io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO,
|
iobufs = io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO,
|
||||||
log_stderr, iobufs);
|
log_stderr, iobufs);
|
||||||
script_fds[SFD_STDERR] = io_pipe[STDERR_FILENO][1];
|
io_fds[SFD_STDERR] = io_pipe[STDERR_FILENO][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Job control signals to relay from parent to child. */
|
/* Job control signals to relay from parent to child. */
|
||||||
@@ -612,16 +612,16 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
|
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
/* Copy terminal attrs from user tty -> pty slave. */
|
/* Copy terminal attrs from user tty -> pty slave. */
|
||||||
if (term_copy(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE])) {
|
if (term_copy(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE])) {
|
||||||
tty_initialized = 1;
|
tty_initialized = 1;
|
||||||
sync_ttysize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]);
|
sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start out in raw mode if we are not part of a pipeline. */
|
/* Start out in raw mode if we are not part of a pipeline. */
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
ttymode = TERM_RAW;
|
ttymode = TERM_RAW;
|
||||||
do {
|
do {
|
||||||
n = term_raw(script_fds[SFD_USERTTY], 0);
|
n = term_raw(io_fds[SFD_USERTTY], 0);
|
||||||
} while (!n && errno == EINTR);
|
} while (!n && errno == EINTR);
|
||||||
if (!n)
|
if (!n)
|
||||||
error(1, "Can't set terminal to raw mode");
|
error(1, "Can't set terminal to raw mode");
|
||||||
@@ -642,7 +642,6 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
/* child */
|
/* child */
|
||||||
close(sv[0]);
|
close(sv[0]);
|
||||||
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
|
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
|
||||||
/* XXX - defer call to exec_setup() until my_execve()? */
|
|
||||||
if (exec_setup(details) == TRUE) {
|
if (exec_setup(details) == TRUE) {
|
||||||
/* headed for execve() */
|
/* headed for execve() */
|
||||||
if (log_io) {
|
if (log_io) {
|
||||||
@@ -653,7 +652,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
close(io_pipe[STDOUT_FILENO][0]);
|
close(io_pipe[STDOUT_FILENO][0]);
|
||||||
if (io_pipe[STDERR_FILENO][0])
|
if (io_pipe[STDERR_FILENO][0])
|
||||||
close(io_pipe[STDERR_FILENO][0]);
|
close(io_pipe[STDERR_FILENO][0]);
|
||||||
script_child(details, argv, envp, sv[1], rbac_enabled);
|
exec_monitor(details, argv, envp, sv[1], rbac_enabled);
|
||||||
} else {
|
} else {
|
||||||
if (details->closefrom >= 0)
|
if (details->closefrom >= 0)
|
||||||
closefrom(details->closefrom);
|
closefrom(details->closefrom);
|
||||||
@@ -750,12 +749,12 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
}
|
}
|
||||||
/* Don't read/write /dev/tty if we are not in the foreground. */
|
/* Don't read/write /dev/tty if we are not in the foreground. */
|
||||||
if (iob->rfd != -1 &&
|
if (iob->rfd != -1 &&
|
||||||
(ttymode == TERM_RAW || iob->rfd != script_fds[SFD_USERTTY])) {
|
(ttymode == TERM_RAW || iob->rfd != io_fds[SFD_USERTTY])) {
|
||||||
if (iob->len != sizeof(iob->buf))
|
if (iob->len != sizeof(iob->buf))
|
||||||
FD_SET(iob->rfd, fdsr);
|
FD_SET(iob->rfd, fdsr);
|
||||||
}
|
}
|
||||||
if (iob->wfd != -1 &&
|
if (iob->wfd != -1 &&
|
||||||
(foreground || iob->wfd != script_fds[SFD_USERTTY])) {
|
(foreground || iob->wfd != io_fds[SFD_USERTTY])) {
|
||||||
if (iob->len > iob->off)
|
if (iob->len > iob->off)
|
||||||
FD_SET(iob->wfd, fdsw);
|
FD_SET(iob->wfd, fdsw);
|
||||||
}
|
}
|
||||||
@@ -837,18 +836,18 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
|
|
||||||
if (log_io) {
|
if (log_io) {
|
||||||
/* Flush any remaining output (the plugin already got it) */
|
/* Flush any remaining output (the plugin already got it) */
|
||||||
if (script_fds[SFD_USERTTY] != -1) {
|
if (io_fds[SFD_USERTTY] != -1) {
|
||||||
n = fcntl(script_fds[SFD_USERTTY], F_GETFL, 0);
|
n = fcntl(io_fds[SFD_USERTTY], F_GETFL, 0);
|
||||||
if (n != -1 && ISSET(n, O_NONBLOCK)) {
|
if (n != -1 && ISSET(n, O_NONBLOCK)) {
|
||||||
CLR(n, O_NONBLOCK);
|
CLR(n, O_NONBLOCK);
|
||||||
(void) fcntl(script_fds[SFD_USERTTY], F_SETFL, n);
|
(void) fcntl(io_fds[SFD_USERTTY], F_SETFL, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flush_output(iobufs);
|
flush_output(iobufs);
|
||||||
|
|
||||||
if (script_fds[SFD_USERTTY] != -1) {
|
if (io_fds[SFD_USERTTY] != -1) {
|
||||||
do {
|
do {
|
||||||
n = term_restore(script_fds[SFD_USERTTY], 0);
|
n = term_restore(io_fds[SFD_USERTTY], 0);
|
||||||
} while (!n && errno == EINTR);
|
} while (!n && errno == EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -856,8 +855,8 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
int signo = WTERMSIG(cstat->val);
|
int signo = WTERMSIG(cstat->val);
|
||||||
if (signo && signo != SIGINT && signo != SIGPIPE) {
|
if (signo && signo != SIGINT && signo != SIGPIPE) {
|
||||||
char *reason = strsignal(signo);
|
char *reason = strsignal(signo);
|
||||||
n = script_fds[SFD_USERTTY] != -1 ?
|
n = io_fds[SFD_USERTTY] != -1 ?
|
||||||
script_fds[SFD_USERTTY] : STDOUT_FILENO;
|
io_fds[SFD_USERTTY] : STDOUT_FILENO;
|
||||||
write(n, reason, strlen(reason));
|
write(n, reason, strlen(reason));
|
||||||
if (WCOREDUMP(cstat->val))
|
if (WCOREDUMP(cstat->val))
|
||||||
write(n, " (core dumped)", 14);
|
write(n, " (core dumped)", 14);
|
||||||
@@ -910,14 +909,14 @@ deliver_signal(pid_t pid, int signo)
|
|||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
/* foreground process, grant it controlling tty. */
|
/* foreground process, grant it controlling tty. */
|
||||||
do {
|
do {
|
||||||
status = tcsetpgrp(script_fds[SFD_SLAVE], pid);
|
status = tcsetpgrp(io_fds[SFD_SLAVE], pid);
|
||||||
} while (status == -1 && errno == EINTR);
|
} while (status == -1 && errno == EINTR);
|
||||||
killpg(pid, SIGCONT);
|
killpg(pid, SIGCONT);
|
||||||
break;
|
break;
|
||||||
case SIGUSR2:
|
case SIGUSR2:
|
||||||
/* background process, I take controlling tty. */
|
/* background process, I take controlling tty. */
|
||||||
do {
|
do {
|
||||||
status = tcsetpgrp(script_fds[SFD_SLAVE], getpid());
|
status = tcsetpgrp(io_fds[SFD_SLAVE], getpid());
|
||||||
} while (status == -1 && errno == EINTR);
|
} while (status == -1 && errno == EINTR);
|
||||||
killpg(pid, SIGCONT);
|
killpg(pid, SIGCONT);
|
||||||
break;
|
break;
|
||||||
@@ -990,14 +989,14 @@ handle_sigchld(int backchannel, struct command_status *cstat)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Child process that creates a new session with the controlling tty,
|
* Monitor process that creates a new session with the controlling tty,
|
||||||
* resets signal handlers and forks a child to call script_run().
|
* resets signal handlers and forks a child to call exec_pty().
|
||||||
* Waits for status changes from the command and relays them to the
|
* Waits for status changes from the command and relays them to the
|
||||||
* parent and relays signals from the parent to the command.
|
* parent and relays signals from the parent to the command.
|
||||||
* Returns an error if fork(2) fails, else calls _exit(2).
|
* Returns an error if fork(2) fails, else calls _exit(2).
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
script_child(struct command_details *details, char *argv[], char *envp[],
|
exec_monitor(struct command_details *details, char *argv[], char *envp[],
|
||||||
int backchannel, int rbac)
|
int backchannel, int rbac)
|
||||||
{
|
{
|
||||||
struct command_status cstat;
|
struct command_status cstat;
|
||||||
@@ -1008,12 +1007,12 @@ script_child(struct command_details *details, char *argv[], char *envp[],
|
|||||||
int alive = TRUE;
|
int alive = TRUE;
|
||||||
|
|
||||||
/* Close unused fds. */
|
/* Close unused fds. */
|
||||||
if (script_fds[SFD_MASTER] != -1)
|
if (io_fds[SFD_MASTER] != -1)
|
||||||
close(script_fds[SFD_MASTER]);
|
close(io_fds[SFD_MASTER]);
|
||||||
if (script_fds[SFD_USERTTY] != -1)
|
if (io_fds[SFD_USERTTY] != -1)
|
||||||
close(script_fds[SFD_USERTTY]);
|
close(io_fds[SFD_USERTTY]);
|
||||||
|
|
||||||
/* Reset signal handlers. */
|
/* Reset SIGWINCH and SIGALRM. */
|
||||||
zero_bytes(&sa, sizeof(sa));
|
zero_bytes(&sa, sizeof(sa));
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = SA_RESTART;
|
sa.sa_flags = SA_RESTART;
|
||||||
@@ -1053,9 +1052,9 @@ script_child(struct command_details *details, char *argv[], char *envp[],
|
|||||||
# endif
|
# endif
|
||||||
setpgrp(0, 0);
|
setpgrp(0, 0);
|
||||||
#endif
|
#endif
|
||||||
if (script_fds[SFD_SLAVE] != -1) {
|
if (io_fds[SFD_SLAVE] != -1) {
|
||||||
#ifdef TIOCSCTTY
|
#ifdef TIOCSCTTY
|
||||||
if (ioctl(script_fds[SFD_SLAVE], TIOCSCTTY, NULL) != 0)
|
if (ioctl(io_fds[SFD_SLAVE], TIOCSCTTY, NULL) != 0)
|
||||||
error(1, "unable to set controlling tty");
|
error(1, "unable to set controlling tty");
|
||||||
#else
|
#else
|
||||||
/* Set controlling tty by reopening slave. */
|
/* Set controlling tty by reopening slave. */
|
||||||
@@ -1082,27 +1081,13 @@ script_child(struct command_details *details, char *argv[], char *envp[],
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (child == 0) {
|
if (child == 0) {
|
||||||
/* Reset signal handlers. */
|
|
||||||
sa.sa_flags = SA_RESTART;
|
|
||||||
sa.sa_handler = SIG_DFL;
|
|
||||||
sigaction(SIGHUP, &sa, NULL);
|
|
||||||
sigaction(SIGTERM, &sa, NULL);
|
|
||||||
sigaction(SIGINT, &sa, NULL);
|
|
||||||
sigaction(SIGQUIT, &sa, NULL);
|
|
||||||
sigaction(SIGTSTP, &sa, NULL);
|
|
||||||
sigaction(SIGTTIN, &sa, NULL);
|
|
||||||
sigaction(SIGTTOU, &sa, NULL);
|
|
||||||
sigaction(SIGUSR1, &sa, NULL);
|
|
||||||
sigaction(SIGUSR2, &sa, NULL);
|
|
||||||
sigaction(SIGCHLD, &sa, NULL);
|
|
||||||
|
|
||||||
/* We pass errno back to our parent via pipe on exec failure. */
|
/* We pass errno back to our parent via pipe on exec failure. */
|
||||||
close(backchannel);
|
close(backchannel);
|
||||||
close(errpipe[0]);
|
close(errpipe[0]);
|
||||||
fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);
|
fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
/* setup tty and exec command */
|
/* setup tty and exec command */
|
||||||
script_run(details, argv, envp, rbac);
|
exec_pty(details, argv, envp, rbac);
|
||||||
cstat.type = CMD_ERRNO;
|
cstat.type = CMD_ERRNO;
|
||||||
cstat.val = errno;
|
cstat.val = errno;
|
||||||
write(errpipe[1], &cstat, sizeof(cstat));
|
write(errpipe[1], &cstat, sizeof(cstat));
|
||||||
@@ -1111,12 +1096,12 @@ script_child(struct command_details *details, char *argv[], char *envp[],
|
|||||||
close(errpipe[1]);
|
close(errpipe[1]);
|
||||||
|
|
||||||
/* If any of stdin/stdout/stderr are pipes, close them in parent. */
|
/* If any of stdin/stdout/stderr are pipes, close them in parent. */
|
||||||
if (script_fds[SFD_STDIN] != script_fds[SFD_SLAVE])
|
if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE])
|
||||||
close(script_fds[SFD_STDIN]);
|
close(io_fds[SFD_STDIN]);
|
||||||
if (script_fds[SFD_STDOUT] != script_fds[SFD_SLAVE])
|
if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE])
|
||||||
close(script_fds[SFD_STDOUT]);
|
close(io_fds[SFD_STDOUT]);
|
||||||
if (script_fds[SFD_STDERR] != script_fds[SFD_SLAVE])
|
if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE])
|
||||||
close(script_fds[SFD_STDERR]);
|
close(io_fds[SFD_STDERR]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put child in its own process group. If we are starting the command
|
* Put child in its own process group. If we are starting the command
|
||||||
@@ -1125,7 +1110,7 @@ script_child(struct command_details *details, char *argv[], char *envp[],
|
|||||||
setpgid(child, child);
|
setpgid(child, child);
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
do {
|
do {
|
||||||
status = tcsetpgrp(script_fds[SFD_SLAVE], child);
|
status = tcsetpgrp(io_fds[SFD_SLAVE], child);
|
||||||
} while (status == -1 && errno == EINTR);
|
} while (status == -1 && errno == EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1239,7 +1224,7 @@ flush_output(struct io_buffer *iobufs)
|
|||||||
nwriters = 0;
|
nwriters = 0;
|
||||||
for (iob = iobufs; iob; iob = iob->next) {
|
for (iob = iobufs; iob; iob = iob->next) {
|
||||||
/* Don't read from /dev/tty while flushing. */
|
/* Don't read from /dev/tty while flushing. */
|
||||||
if (script_fds[SFD_USERTTY] != -1 && iob->rfd == script_fds[SFD_USERTTY])
|
if (io_fds[SFD_USERTTY] != -1 && iob->rfd == io_fds[SFD_USERTTY])
|
||||||
continue;
|
continue;
|
||||||
if (iob->rfd == -1 && iob->wfd == -1)
|
if (iob->rfd == -1 && iob->wfd == -1)
|
||||||
continue;
|
continue;
|
||||||
@@ -1282,38 +1267,55 @@ flush_output(struct io_buffer *iobufs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets up file descriptors and executes the actual command.
|
* Sets up std{in,out,err} and executes the actual command.
|
||||||
* Returns only if execve() fails.
|
* Returns only if execve() fails.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
script_run(struct command_details *details, char *argv[], char *envp[],
|
exec_pty(struct command_details *details, char *argv[], char *envp[],
|
||||||
int rbac_enabled)
|
int rbac_enabled)
|
||||||
{
|
{
|
||||||
|
sigaction_t sa;
|
||||||
pid_t self = getpid();
|
pid_t self = getpid();
|
||||||
|
|
||||||
|
/* Reset signal handlers. */
|
||||||
|
zero_bytes(&sa, sizeof(sa));
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = SA_RESTART;
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
sigaction(SIGHUP, &sa, NULL);
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
sigaction(SIGQUIT, &sa, NULL);
|
||||||
|
sigaction(SIGTSTP, &sa, NULL);
|
||||||
|
sigaction(SIGTTIN, &sa, NULL);
|
||||||
|
sigaction(SIGTTOU, &sa, NULL);
|
||||||
|
sigaction(SIGUSR1, &sa, NULL);
|
||||||
|
sigaction(SIGUSR2, &sa, NULL);
|
||||||
|
sigaction(SIGCHLD, &sa, NULL);
|
||||||
|
|
||||||
/* Set child process group here too to avoid a race. */
|
/* Set child process group here too to avoid a race. */
|
||||||
setpgid(0, self);
|
setpgid(0, self);
|
||||||
|
|
||||||
/* Wire up standard fds, note that stdout/stderr may be pipes. */
|
/* Wire up standard fds, note that stdout/stderr may be pipes. */
|
||||||
dup2(script_fds[SFD_STDIN], STDIN_FILENO);
|
dup2(io_fds[SFD_STDIN], STDIN_FILENO);
|
||||||
dup2(script_fds[SFD_STDOUT], STDOUT_FILENO);
|
dup2(io_fds[SFD_STDOUT], STDOUT_FILENO);
|
||||||
dup2(script_fds[SFD_STDERR], STDERR_FILENO);
|
dup2(io_fds[SFD_STDERR], STDERR_FILENO);
|
||||||
|
|
||||||
/* Wait for parent to grant us the tty if we are foreground. */
|
/* Wait for parent to grant us the tty if we are foreground. */
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
while (tcgetpgrp(script_fds[SFD_SLAVE]) != self)
|
while (tcgetpgrp(io_fds[SFD_SLAVE]) != self)
|
||||||
; /* spin */
|
; /* spin */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have guaranteed that the slave fd is > 2 */
|
/* We have guaranteed that the slave fd is > 2 */
|
||||||
if (script_fds[SFD_SLAVE] != -1)
|
if (io_fds[SFD_SLAVE] != -1)
|
||||||
close(script_fds[SFD_SLAVE]);
|
close(io_fds[SFD_SLAVE]);
|
||||||
if (script_fds[SFD_STDIN] != script_fds[SFD_SLAVE])
|
if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE])
|
||||||
close(script_fds[SFD_STDIN]);
|
close(io_fds[SFD_STDIN]);
|
||||||
if (script_fds[SFD_STDOUT] != script_fds[SFD_SLAVE])
|
if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE])
|
||||||
close(script_fds[SFD_STDOUT]);
|
close(io_fds[SFD_STDOUT]);
|
||||||
if (script_fds[SFD_STDERR] != script_fds[SFD_SLAVE])
|
if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE])
|
||||||
close(script_fds[SFD_STDERR]);
|
close(io_fds[SFD_STDERR]);
|
||||||
|
|
||||||
if (details->closefrom >= 0)
|
if (details->closefrom >= 0)
|
||||||
closefrom(details->closefrom);
|
closefrom(details->closefrom);
|
||||||
@@ -1363,7 +1365,7 @@ sigwinch(int s)
|
|||||||
{
|
{
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
|
|
||||||
sync_ttysize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]);
|
sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]);
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1375,7 +1377,7 @@ static int
|
|||||||
safe_close(int fd)
|
safe_close(int fd)
|
||||||
{
|
{
|
||||||
/* Avoid closing /dev/tty or std{in,out,err}. */
|
/* Avoid closing /dev/tty or std{in,out,err}. */
|
||||||
if (fd < 3 || fd == script_fds[SFD_USERTTY]) {
|
if (fd < 3 || fd == io_fds[SFD_USERTTY]) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@@ -792,7 +792,7 @@ run_command(struct command_details *details, char *argv[], char *envp[])
|
|||||||
* XXX - no background support
|
* XXX - no background support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
script_execve(details, argv, envp, &cstat);
|
sudo_execve(details, argv, envp, &cstat);
|
||||||
|
|
||||||
switch (cstat.type) {
|
switch (cstat.type) {
|
||||||
case CMD_ERRNO:
|
case CMD_ERRNO:
|
||||||
|
@@ -157,8 +157,8 @@ int tty_present(void);
|
|||||||
/* zero_bytes.c */
|
/* zero_bytes.c */
|
||||||
void zero_bytes(volatile void *, size_t);
|
void zero_bytes(volatile void *, size_t);
|
||||||
|
|
||||||
/* script.c */
|
/* exec.c */
|
||||||
int script_execve(struct command_details *details, char *argv[], char *envp[],
|
int sudo_execve(struct command_details *details, char *argv[], char *envp[],
|
||||||
struct command_status *cstat);
|
struct command_status *cstat);
|
||||||
|
|
||||||
/* term.c */
|
/* term.c */
|
||||||
|
Reference in New Issue
Block a user