summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTodd C. Miller <Todd.Miller@sudo.ws>2023-03-21 15:30:54 -0600
committerTodd C. Miller <Todd.Miller@sudo.ws>2023-03-21 15:30:54 -0600
commit2020f51ee10255334ec285dde351bb3f03d217ce (patch)
tree04f58f7ddd3607a0aef6dfce7cd6e5260903ccd3 /src
parenta6f593ea89d2692631d9c87cad33c70bf537721e (diff)
downloadsudo-2020f51ee10255334ec285dde351bb3f03d217ce.tar.gz
Move updating of the window size back to the main sudo process.
We can use the leader file descriptor with TIOCGWINSZ to set the window size of the pty. Thanks to Duncan Overbruck for the hint.
Diffstat (limited to 'src')
-rw-r--r--src/exec_monitor.c60
-rw-r--r--src/exec_pty.c23
-rw-r--r--src/sudo.h1
3 files changed, 18 insertions, 66 deletions
diff --git a/src/exec_monitor.c b/src/exec_monitor.c
index a92ed4099..2f2e0bd83 100644
--- a/src/exec_monitor.c
+++ b/src/exec_monitor.c
@@ -24,7 +24,6 @@
#include <config.h>
#include <sys/types.h>
-#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <stdio.h>
@@ -35,7 +34,6 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
-#include <termios.h>
#include "sudo.h"
#include "sudo_exec.h"
@@ -62,8 +60,6 @@ struct monitor_closure {
int backchannel;
};
-static bool tty_initialized;
-
/*
* Deliver a signal to the running command.
* The signal was either forwarded to us by the parent sudo process
@@ -103,11 +99,6 @@ deliver_signal(struct monitor_closure *mc, int signo, bool from_parent)
"%s: unable to set foreground pgrp to %d (command)",
__func__, (int)mc->cmnd_pgrp);
}
- /* Lazily initialize the pty if needed. */
- if (!tty_initialized) {
- if (sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_FOLLOWER]))
- tty_initialized = true;
- }
killpg(mc->cmnd_pid, SIGCONT);
break;
case SIGCONT_BG:
@@ -131,34 +122,6 @@ deliver_signal(struct monitor_closure *mc, int signo, bool from_parent)
}
/*
- * Unpack rows and cols from a CMD_TTYWINCH value, set the new window
- * size on the pty follower and inform the command of the change.
- */
-static void
-handle_winch(struct monitor_closure *mc, unsigned int wsize_packed)
-{
- struct winsize wsize, owsize;
- debug_decl(handle_winch, SUDO_DEBUG_EXEC);
-
- /* Rows and columns are stored as two shorts packed into a single int. */
- wsize.ws_row = wsize_packed & 0xffff;
- wsize.ws_col = (wsize_packed >> 16) & 0xffff;
-
- if (ioctl(io_fds[SFD_FOLLOWER], TIOCGWINSZ, &owsize) == 0 &&
- (wsize.ws_row != owsize.ws_row || wsize.ws_col != owsize.ws_col)) {
-
- sudo_debug_printf(SUDO_DEBUG_INFO,
- "window size change %dx%d -> %dx%d",
- owsize.ws_col, owsize.ws_row, wsize.ws_col, wsize.ws_row);
-
- (void)ioctl(io_fds[SFD_FOLLOWER], TIOCSWINSZ, &wsize);
- deliver_signal(mc, SIGWINCH, true);
- }
-
- debug_return;
-}
-
-/*
* Send status to parent over socketpair.
* Return value is the same as send(2).
*/
@@ -368,16 +331,11 @@ mon_backchannel_cb(int fd, int what, void *v)
mc->cstat->val = n ? EIO : ECONNRESET;
sudo_ev_loopbreak(mc->evbase);
} else {
- switch (cstmp.type) {
- case CMD_TTYWINCH:
- handle_winch(mc, cstmp.val);
- break;
- case CMD_SIGNO:
+ if (cstmp.type == CMD_SIGNO) {
deliver_signal(mc, cstmp.val, true);
- break;
- default:
- sudo_warnx(U_("unexpected reply type on backchannel: %d"), cstmp.type);
- break;
+ } else {
+ sudo_warnx(U_("unexpected reply type on backchannel: %d"),
+ cstmp.type);
}
}
debug_return;
@@ -556,9 +514,11 @@ exec_monitor(struct command_details *details, sigset_t *oset,
int errpipe[2];
debug_decl(exec_monitor, SUDO_DEBUG_EXEC);
- /* The pty leader is not used by the monitor. */
+ /* Close fds the monitor doesn't use. */
if (io_fds[SFD_LEADER] != -1)
close(io_fds[SFD_LEADER]);
+ if (io_fds[SFD_USERTTY] != -1)
+ close(io_fds[SFD_USERTTY]);
/* Ignore any SIGTTIN or SIGTTOU we receive (shouldn't be possible). */
memset(&sa, 0, sizeof(sa));
@@ -570,10 +530,6 @@ exec_monitor(struct command_details *details, sigset_t *oset,
if (sudo_sigaction(SIGTTOU, &sa, NULL) != 0)
sudo_warn(U_("unable to set handler for signal %d"), SIGTTOU);
- /* If we are starting in the foreground, the pty was already initialized. */
- if (foreground)
- tty_initialized = true;
-
/*
* Start a new session with the parent as the session leader
* and the follower device as the controlling terminal.
@@ -630,8 +586,6 @@ exec_monitor(struct command_details *details, sigset_t *oset,
/* child */
close(backchannel);
close(errpipe[0]);
- if (io_fds[SFD_USERTTY] != -1)
- close(io_fds[SFD_USERTTY]);
/* setup tty and exec command */
exec_cmnd_pty(details, oset, foreground, intercept_fd, errpipe[1]);
if (write(errpipe[1], &errno, sizeof(int)) == -1)
diff --git a/src/exec_pty.c b/src/exec_pty.c
index 9a8ddfab1..e764564aa 100644
--- a/src/exec_pty.c
+++ b/src/exec_pty.c
@@ -59,6 +59,7 @@ static struct monitor_message_list monitor_messages =
static char ptyname[PATH_MAX];
static bool foreground, pipeline;
+static bool tty_initialized;
static const char *utmp_user;
static void sync_ttysize(struct exec_closure *ec);
@@ -159,6 +160,10 @@ check_foreground(struct exec_closure *ec)
if (io_fds[SFD_USERTTY] != -1) {
if ((ret = tcgetpgrp(io_fds[SFD_USERTTY])) != -1) {
foreground = ret == ec->ppgrp;
+ if (foreground && !tty_initialized) {
+ if (sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_FOLLOWER]))
+ tty_initialized = true;
+ }
/* Also check for window size changes. */
sync_ttysize(ec);
@@ -840,11 +845,6 @@ fwdchannel_cb(int sock, int what, void *v)
sudo_debug_printf(SUDO_DEBUG_INFO,
"sending SIG%s to monitor over backchannel", signame);
break;
- case CMD_TTYWINCH:
- sudo_debug_printf(SUDO_DEBUG_INFO, "sending window size change "
- "to monitor over backchannelL %d x %d",
- msg->cstat.val & 0xffff, (msg->cstat.val >> 16) & 0xffff);
- break;
default:
sudo_debug_printf(SUDO_DEBUG_INFO,
"sending cstat type %d, value %d to monitor over backchannel",
@@ -1192,6 +1192,7 @@ exec_pty(struct command_details *details, struct command_status *cstat)
if (sudo_term_raw(io_fds[SFD_USERTTY], 0))
ttymode = TERM_RAW;
}
+ tty_initialized = true;
}
}
@@ -1347,8 +1348,8 @@ exec_pty(struct command_details *details, struct command_status *cstat)
}
/*
- * Check for tty size changes.
- * Passes the new window size to the I/O plugin and to the monitor.
+ * Propagate tty size change to pty being used by the command, pass
+ * new window size to I/O plugins and deliver SIGWINCH to the command.
*/
static void
sync_ttysize(struct exec_closure *ec)
@@ -1358,14 +1359,12 @@ sync_ttysize(struct exec_closure *ec)
if (ioctl(io_fds[SFD_USERTTY], TIOCGWINSZ, &wsize) == 0) {
if (wsize.ws_row != ec->rows || wsize.ws_col != ec->cols) {
- const unsigned int wsize_packed = (wsize.ws_row & 0xffff) |
- ((wsize.ws_col & 0xffff) << 16);
-
/* Log window change event. */
log_winchange(ec, wsize.ws_row, wsize.ws_col);
- /* Send window change event to monitor process. */
- send_command_status(ec, CMD_TTYWINCH, wsize_packed);
+ /* Update pty window size and send command SIGWINCH. */
+ (void)ioctl(io_fds[SFD_LEADER], TIOCSWINSZ, &wsize);
+ killpg(ec->cmnd_pid, SIGWINCH);
/* Update rows/cols. */
ec->rows = wsize.ws_row;
diff --git a/src/sudo.h b/src/sudo.h
index acb89b751..204c3e76e 100644
--- a/src/sudo.h
+++ b/src/sudo.h
@@ -225,7 +225,6 @@ struct command_status {
#define CMD_WSTATUS 2
#define CMD_SIGNO 3
#define CMD_PID 4
-#define CMD_TTYWINCH 5
int type;
int val;
};