Now that we can use pipes for stdin/stdout/stderr there is no
longer a need to error out when there is no tty. We just need to make sure we don't try to use the tty fd if it is -1.
This commit is contained in:
102
src/script.c
102
src/script.c
@@ -121,7 +121,7 @@ static int foreground;
|
|||||||
|
|
||||||
static char slavename[PATH_MAX];
|
static char slavename[PATH_MAX];
|
||||||
|
|
||||||
static int suspend_parent(int signo, int fd, struct io_buffer *output);
|
static int suspend_parent(int signo, struct io_buffer *iobufs);
|
||||||
static void flush_output(struct io_buffer *iobufs);
|
static void flush_output(struct io_buffer *iobufs);
|
||||||
static int perform_io(struct io_buffer *iobufs, fd_set *fdsr, fd_set *fdsw);
|
static int perform_io(struct io_buffer *iobufs, fd_set *fdsr, fd_set *fdsw);
|
||||||
static void handler(int s);
|
static void handler(int s);
|
||||||
@@ -138,12 +138,11 @@ void
|
|||||||
script_setup(uid_t uid)
|
script_setup(uid_t uid)
|
||||||
{
|
{
|
||||||
script_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
|
script_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
|
||||||
if (script_fds[SFD_USERTTY] == -1)
|
if (script_fds[SFD_USERTTY] != -1) {
|
||||||
errorx(1, "tty required for transcript support");
|
if (!get_pty(&script_fds[SFD_MASTER], &script_fds[SFD_SLAVE],
|
||||||
|
slavename, sizeof(slavename), uid))
|
||||||
if (!get_pty(&script_fds[SFD_MASTER], &script_fds[SFD_SLAVE],
|
error(1, "Can't get pty");
|
||||||
slavename, sizeof(slavename), uid))
|
}
|
||||||
error(1, "Can't get pty");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call I/O plugin tty input log method. */
|
/* Call I/O plugin tty input log method. */
|
||||||
@@ -264,11 +263,13 @@ log_stderr(char *buf, unsigned int n)
|
|||||||
static void
|
static void
|
||||||
check_foreground(void)
|
check_foreground(void)
|
||||||
{
|
{
|
||||||
foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == ppgrp;
|
if (script_fds[SFD_USERTTY] != -1) {
|
||||||
if (foreground && !tty_initialized) {
|
foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == ppgrp;
|
||||||
if (term_copy(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE])) {
|
if (foreground && !tty_initialized) {
|
||||||
tty_initialized = 1;
|
if (term_copy(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE])) {
|
||||||
sync_ttysize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]);
|
tty_initialized = 1;
|
||||||
|
sync_ttysize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,7 +279,7 @@ check_foreground(void)
|
|||||||
* Returns SIGUSR1 if the child should be resume in foreground else SIGUSR2.
|
* Returns SIGUSR1 if the child should be resume in foreground else SIGUSR2.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
suspend_parent(int signo, int fd, struct io_buffer *iobufs)
|
suspend_parent(int signo, struct io_buffer *iobufs)
|
||||||
{
|
{
|
||||||
sigaction_t sa, osa;
|
sigaction_t sa, osa;
|
||||||
int n, oldmode = ttymode, rval = 0;
|
int n, oldmode = ttymode, rval = 0;
|
||||||
@@ -534,9 +535,11 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
sigaction(SIGTERM, &sa, NULL);
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
|
||||||
if (log_io) {
|
if (log_io) {
|
||||||
sa.sa_flags = SA_RESTART;
|
if (script_fds[SFD_USERTTY] != -1) {
|
||||||
sa.sa_handler = sigwinch;
|
sa.sa_flags = SA_RESTART;
|
||||||
sigaction(SIGWINCH, &sa, NULL);
|
sa.sa_handler = sigwinch;
|
||||||
|
sigaction(SIGWINCH, &sa, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* So we can block tty-generated signals */
|
/* So we can block tty-generated signals */
|
||||||
sigemptyset(&ttyblock);
|
sigemptyset(&ttyblock);
|
||||||
@@ -546,9 +549,6 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
sigaddset(&ttyblock, SIGTTIN);
|
sigaddset(&ttyblock, SIGTTIN);
|
||||||
sigaddset(&ttyblock, SIGTTOU);
|
sigaddset(&ttyblock, SIGTTOU);
|
||||||
|
|
||||||
/* Are we the foreground process? */
|
|
||||||
foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == ppgrp;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup stdin/stdout/stderr for child, to be duped after forking.
|
* Setup stdin/stdout/stderr for child, to be duped after forking.
|
||||||
*/
|
*/
|
||||||
@@ -557,12 +557,17 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
script_fds[SFD_STDERR] = script_fds[SFD_SLAVE];
|
script_fds[SFD_STDERR] = script_fds[SFD_SLAVE];
|
||||||
|
|
||||||
/* Copy /dev/tty -> pty master */
|
/* Copy /dev/tty -> pty master */
|
||||||
iobufs = io_buf_new(script_fds[SFD_USERTTY], script_fds[SFD_MASTER],
|
if (script_fds[SFD_USERTTY] != -1) {
|
||||||
log_ttyin, iobufs);
|
iobufs = io_buf_new(script_fds[SFD_USERTTY], script_fds[SFD_MASTER],
|
||||||
|
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(script_fds[SFD_MASTER], script_fds[SFD_USERTTY],
|
||||||
log_ttyout, iobufs);
|
log_ttyout, iobufs);
|
||||||
|
|
||||||
|
/* Are we the foreground process? */
|
||||||
|
foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == ppgrp;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If either stdin, stdout or stderr is not a tty we use a pipe
|
* If either stdin, stdout or stderr is not a tty we use a pipe
|
||||||
@@ -790,7 +795,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
if (WIFSTOPPED(cstat->val)) {
|
if (WIFSTOPPED(cstat->val)) {
|
||||||
/* Suspend parent and tell child how to resume on return. */
|
/* Suspend parent and tell child how to resume on return. */
|
||||||
sudo_debug(8, "child stopped, suspending parent");
|
sudo_debug(8, "child stopped, suspending parent");
|
||||||
n = suspend_parent(WSTOPSIG(cstat->val), script_fds[SFD_USERTTY], iobufs);
|
n = suspend_parent(WSTOPSIG(cstat->val), iobufs);
|
||||||
recvsig[n] = TRUE;
|
recvsig[n] = TRUE;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
@@ -826,25 +831,31 @@ 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) */
|
||||||
n = fcntl(script_fds[SFD_USERTTY], F_GETFL, 0);
|
if (script_fds[SFD_USERTTY] != -1) {
|
||||||
if (n != -1 && ISSET(n, O_NONBLOCK)) {
|
n = fcntl(script_fds[SFD_USERTTY], F_GETFL, 0);
|
||||||
CLR(n, O_NONBLOCK);
|
if (n != -1 && ISSET(n, O_NONBLOCK)) {
|
||||||
(void) fcntl(script_fds[SFD_USERTTY], F_SETFL, n);
|
CLR(n, O_NONBLOCK);
|
||||||
|
(void) fcntl(script_fds[SFD_USERTTY], F_SETFL, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
flush_output(iobufs);
|
flush_output(iobufs);
|
||||||
|
|
||||||
do {
|
if (script_fds[SFD_USERTTY] != -1) {
|
||||||
n = term_restore(script_fds[SFD_USERTTY], 0);
|
do {
|
||||||
} while (!n && errno == EINTR);
|
n = term_restore(script_fds[SFD_USERTTY], 0);
|
||||||
|
} while (!n && errno == EINTR);
|
||||||
|
}
|
||||||
|
|
||||||
if (cstat->type == CMD_WSTATUS && WIFSIGNALED(cstat->val)) {
|
if (cstat->type == CMD_WSTATUS && WIFSIGNALED(cstat->val)) {
|
||||||
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);
|
||||||
write(script_fds[SFD_USERTTY], reason, strlen(reason));
|
n = script_fds[SFD_USERTTY] != -1 ?
|
||||||
|
script_fds[SFD_USERTTY] : STDOUT_FILENO;
|
||||||
|
write(n, reason, strlen(reason));
|
||||||
if (WCOREDUMP(cstat->val))
|
if (WCOREDUMP(cstat->val))
|
||||||
write(script_fds[SFD_USERTTY], " (core dumped)", 14);
|
write(n, " (core dumped)", 14);
|
||||||
write(script_fds[SFD_USERTTY], "\n", 1);
|
write(n, "\n", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -928,8 +939,10 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
|
|||||||
int alive = TRUE;
|
int alive = TRUE;
|
||||||
|
|
||||||
/* Close unused fds. */
|
/* Close unused fds. */
|
||||||
close(script_fds[SFD_MASTER]);
|
if (script_fds[SFD_MASTER] != -1)
|
||||||
close(script_fds[SFD_USERTTY]);
|
close(script_fds[SFD_MASTER]);
|
||||||
|
if (script_fds[SFD_USERTTY] != -1)
|
||||||
|
close(script_fds[SFD_USERTTY]);
|
||||||
|
|
||||||
/* Reset signal handlers. */
|
/* Reset signal handlers. */
|
||||||
zero_bytes(&sa, sizeof(sa));
|
zero_bytes(&sa, sizeof(sa));
|
||||||
@@ -971,14 +984,16 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
|
|||||||
# endif
|
# endif
|
||||||
setpgrp(0, 0);
|
setpgrp(0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
if (script_fds[SFD_SLAVE] != -1) {
|
||||||
#ifdef TIOCSCTTY
|
#ifdef TIOCSCTTY
|
||||||
if (ioctl(script_fds[SFD_SLAVE], TIOCSCTTY, NULL) != 0)
|
if (ioctl(script_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. */
|
||||||
if ((n = open(slavename, O_RDWR)) >= 0)
|
if ((n = open(slavename, O_RDWR)) >= 0)
|
||||||
close(n);
|
close(n);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If stdin/stdout is not a tty, start command in the background
|
* If stdin/stdout is not a tty, start command in the background
|
||||||
@@ -1237,7 +1252,8 @@ script_run(const char *path, char *argv[], char *envp[], int rbac_enabled)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We have guaranteed that the slave fd > 3 */
|
/* We have guaranteed that the slave fd > 3 */
|
||||||
close(script_fds[SFD_SLAVE]);
|
if (script_fds[SFD_SLAVE] != -1)
|
||||||
|
close(script_fds[SFD_SLAVE]);
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
if (rbac_enabled)
|
if (rbac_enabled)
|
||||||
|
Reference in New Issue
Block a user