diff --git a/backport-Avoid-using-ioctl-TIOCNOTTY-in-the-monitor.patch b/backport-Avoid-using-ioctl-TIOCNOTTY-in-the-monitor.patch new file mode 100644 index 0000000000000000000000000000000000000000..379b0ac156995a41232850bc65db9b798a275df2 --- /dev/null +++ b/backport-Avoid-using-ioctl-TIOCNOTTY-in-the-monitor.patch @@ -0,0 +1,225 @@ +From a2d01a957d31e133c37d77ae149527f9483e4f19 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Sun, 28 Apr 2024 10:28:32 -0600 +Subject: [PATCH] Avoid using ioctl(TIOCNOTTY) in the monitor. + +We don't need to revoke the terminal in the monitor, just signal +the foreground process group. This is more portable and has the +same effect as ioctl(TIOCNOTTY) would on Linux. Since we now signal +the command from the monitor, there is no reason to forward SIGHUP +from the kernel. GitHub issue #367. + +Reference:https://github.com/sudo-project/sudo/commit/a2d01a957d31e133c37d77ae149527f9483e4f19 +Conflict:src/exec_monitor.c src/exec_pty.c + +--- + src/exec_monitor.c | 84 +++++++++++++++++++++++++--------------------- + src/exec_pty.c | 31 ++++++++++------- + src/sudo.h | 2 +- + 3 files changed, 64 insertions(+), 53 deletions(-) + +diff --git a/src/exec_monitor.c b/src/exec_monitor.c +index c570b5d86..524f5c8c9 100644 +--- a/src/exec_monitor.c ++++ b/src/exec_monitor.c +@@ -1,7 +1,7 @@ + /* + * SPDX-License-Identifier: ISC + * +- * Copyright (c) 2009-2021 Todd C. Miller ++ * Copyright (c) 2009-2024 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -310,6 +310,48 @@ mon_errsock_cb(int fd, int what, void *v) + debug_return; + } + ++/* ++ * Called when the user's terminal has gone away but before our pty is ++ * actually revoked. We simulate the effect of ioctl(TIOCNOTTY) on Linux ++ * by sending SIGHUP and SIGCONT to the foreground process group. ++ */ ++static void ++mon_handle_revoke(int fd, pid_t cmnd_pid, struct command_status *cstat) ++{ ++ debug_decl(mon_handle_revoke, SUDO_DEBUG_EXEC); ++ ++ /* ++ * Signal the foreground process group and the command's process group ++ * (if different). We must do this before the pty is revoked be the ++ * main sudo process so we can determine the foreground process group. ++ * Otherwise, if the foreground process group is different from the ++ * command's process group it will not be signaled. ++ */ ++ if (io_fds[SFD_FOLLOWER] != -1) { ++ const pid_t pgrp = tcgetpgrp(io_fds[SFD_FOLLOWER]); ++ if (pgrp != -1 && pgrp != cmnd_pid) { ++ sudo_debug_printf(SUDO_DEBUG_NOTICE, "%s: killpg(%d, SIGHUP)", ++ __func__, pgrp); ++ killpg(pgrp, SIGHUP); ++ sudo_debug_printf(SUDO_DEBUG_NOTICE, "%s: killpg(%d, SIGCONT)", ++ __func__, pgrp); ++ killpg(pgrp, SIGCONT); ++ } ++ } ++ sudo_debug_printf(SUDO_DEBUG_NOTICE, "%s: killpg(%d, SIGHUP)", ++ __func__, cmnd_pid); ++ killpg(cmnd_pid, SIGHUP); ++ sudo_debug_printf(SUDO_DEBUG_NOTICE, "%s: killpg(%d, SIGCONT)", ++ __func__, cmnd_pid); ++ killpg(cmnd_pid, SIGCONT); ++ ++ /* ++ * Now that the running command as been signaled, tell the ++ * parent it is OK to close the pty leader, revoking the pty. ++ */ ++ send_status(fd, cstat); ++} ++ + static void + mon_backchannel_cb(int fd, int what, void *v) + { +@@ -337,44 +379,8 @@ mon_backchannel_cb(int fd, int what, void *v) + sudo_ev_loopbreak(mc->evbase); + } else { + switch (cstmp.type) { +- case CMD_IOCTL: +- if (cstmp.val != TIOCNOTTY) { +- sudo_warnx(U_("unexpected ioctl on backchannel: %d"), +- cstmp.val); +- } else if (io_fds[SFD_FOLLOWER] != -1) { +- int result, ttyfd; +- +- /* +- * Parent asks us to revoke the terminal when the +- * user's terminal goes away. Doing this in the +- * monitor allows the foreground command to receive +- * SIGHUP before the terminal is revoked. +- */ +- result = ioctl(io_fds[SFD_FOLLOWER], TIOCNOTTY, NULL); +- if (result == -1) { +- sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, +- "%s: unable to revoke follower pty", __func__); +- ttyfd = open(_PATH_TTY, O_RDWR); +- if (ttyfd != -1) { +- result = ioctl(ttyfd, TIOCNOTTY, NULL); +- if (result == -1) { +- sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, +- "%s: unable to revoke controlling tty", +- __func__); +- } +- close(ttyfd); +- } else { +- sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, +- "%s: unable to open %s", __func__, _PATH_TTY); +- } +- } +- if (result == 0) { +- sudo_debug_printf(SUDO_DEBUG_INFO, +- "%s: revoked controlling tty for session", __func__); +- } +- /* Now tell the parent to close the pty leader. */ +- send_status(fd, &cstmp); +- } ++ case CMD_REVOKE: ++ mon_handle_revoke(fd, mc->cmnd_pid, &cstmp); + break; + case CMD_SIGNO: + deliver_signal(mc, cstmp.val, true); +diff --git a/src/exec_pty.c b/src/exec_pty.c +index fff9b8f1e..4dd5915ed 100644 +--- a/src/exec_pty.c ++++ b/src/exec_pty.c +@@ -1,7 +1,7 @@ + /* + * SPDX-License-Identifier: ISC + * +- * Copyright (c) 2009-2021 Todd C. Miller ++ * Copyright (c) 2009-2024 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -385,13 +385,13 @@ read_callback(int fd, int what, void *v) + /* If writer already consumed the buffer, close it too. */ + if (iob->wevent != NULL && iob->off == iob->len) { + /* +- * Don't close the pty leader, it will invalidate the pty. +- * We ask the monitor to revoke the pty nicely using TIOCNOTTY. ++ * Don't close the pty leader yet, it will invalidate the pty. ++ * We ask the monitor to signal the running process first. + */ + const int wfd = sudo_ev_get_fd(iob->wevent); + if (wfd == io_fds[SFD_LEADER]) { + sudo_debug_printf(SUDO_DEBUG_NOTICE, "user's tty revoked"); +- send_command_status(iob->ec, CMD_IOCTL, TIOCNOTTY); ++ send_command_status(iob->ec, CMD_REVOKE, 0); + } else { + safe_close(wfd); + } +@@ -474,12 +474,12 @@ write_callback(int fd, int what, void *v) + if (iob->revent != NULL) { + /* + * Don't close the pty leader, it will invalidate the pty. +- * We ask the monitor to revoke the pty nicely using TIOCNOTTY. ++ * We ask the monitor to signal the running process first. + */ + const int rfd = sudo_ev_get_fd(iob->revent); + if (rfd == io_fds[SFD_LEADER]) { + sudo_debug_printf(SUDO_DEBUG_NOTICE, "user's tty revoked"); +- send_command_status(iob->ec, CMD_IOCTL, TIOCNOTTY); ++ send_command_status(iob->ec, CMD_REVOKE, 0); + } else { + safe_close(rfd); + } +@@ -684,15 +684,11 @@ backchannel_cb(int fd, int what, void *v) + sudo_ev_loopbreak(ec->evbase); + *ec->cstat = cstat; + break; +- case CMD_IOCTL: +- if (cstat.val != TIOCNOTTY) { +- sudo_warnx(U_("unexpected ioctl on backchannel: %d"), +- cstat.val); +- } else if (io_fds[SFD_LEADER] != -1) { ++ case CMD_REVOKE: ++ if (io_fds[SFD_LEADER] != -1) { + /* + * Monitor requests that we revoke the user's terminal. +- * This must happen after the monitor has used TIOCNOTTY +- * to invalidate the session and gracefully kill the ++ * This must happen after the monitor has signaled the + * controlling terminal's process group. + */ + close(io_fds[SFD_LEADER]); +@@ -855,6 +851,15 @@ signal_cb_pty(int signo, int what, void *v) + case SIGWINCH: + sync_ttysize(ec); + break; ++ case SIGHUP: ++ /* ++ * Avoid forwarding SIGHUP sent by the kernel, it probably means ++ * that the user's terminal was revoked. When we detect that the ++ * terminal has been revoked, the monitor will send SIGHUP itself. ++ */ ++ if (!USER_SIGNALED(sc->siginfo)) ++ break; ++ FALLTHROUGH; + default: + /* + * Do not forward signals sent by a process in the command's process +diff --git a/src/sudo.h b/src/sudo.h +index ca245ca68..d3122ef4e 100644 +--- a/src/sudo.h ++++ b/src/sudo.h +@@ -225,7 +225,7 @@ struct command_status { + #define CMD_WSTATUS 2 + #define CMD_SIGNO 3 + #define CMD_PID 4 +-#define CMD_IOCTL 5 ++#define CMD_REVOKE 5 + int type; + int val; + }; +-- +2.33.0 + diff --git a/backport-If-user-s-tty-goes-away-tell-monitor-to-revoke-the-t.patch b/backport-If-user-s-tty-goes-away-tell-monitor-to-revoke-the-t.patch new file mode 100644 index 0000000000000000000000000000000000000000..e24e5c817c65726497678ca4019f182ae6c75f4a --- /dev/null +++ b/backport-If-user-s-tty-goes-away-tell-monitor-to-revoke-the-t.patch @@ -0,0 +1,212 @@ +From 41978a56e042977923c1a55191b887218c536145 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Sat, 27 Apr 2024 18:53:50 -0600 +Subject: [PATCH] If user's tty goes away, tell monitor to revoke the tty in + its session. + +Previously, we would simply close the pty leader in the main sudo +process. This had the effect of revoking the pty, but the foreground +process would not necessarily receive SIGHUP. By using TIOCNOTTY +in the monitor, the running command has a better chance of getting +SIGHUP. Once the monitor has revoked the pty, the main sudo process +will close the pty leader, invalidating the pty. GitHub issue #367. + +Reference:https://github.com/sudo-project/sudo/commit/41978a56e042977923c1a55191b887218c536145 +Conflict:src/exec_monitor.c src/exec_pty.c + +--- + src/exec_monitor.c | 48 +++++++++++++++++++++++++++++++++++-- + src/exec_pty.c | 60 ++++++++++++++++++++++++++++++++++++---------- + src/sudo.h | 1 + + 3 files changed, 95 insertions(+), 14 deletions(-) + +diff --git a/src/exec_monitor.c b/src/exec_monitor.c +index 05f5f8cd1..c570b5d86 100644 +--- a/src/exec_monitor.c ++++ b/src/exec_monitor.c +@@ -118,6 +118,8 @@ deliver_signal(struct monitor_closure *mc, int signo, bool from_parent) + /* NOTREACHED */ + default: + /* Relay signal to command. */ ++ sudo_debug_printf(SUDO_DEBUG_NOTICE, "%s: killpg(%d, %d)", ++ __func__, (int)mc->cmnd_pid, signo); + killpg(mc->cmnd_pid, signo); + break; + } +@@ -334,11 +336,53 @@ mon_backchannel_cb(int fd, int what, void *v) + mc->cstat->val = n ? EIO : ECONNRESET; + sudo_ev_loopbreak(mc->evbase); + } else { +- if (cstmp.type == CMD_SIGNO) { ++ switch (cstmp.type) { ++ case CMD_IOCTL: ++ if (cstmp.val != TIOCNOTTY) { ++ sudo_warnx(U_("unexpected ioctl on backchannel: %d"), ++ cstmp.val); ++ } else if (io_fds[SFD_FOLLOWER] != -1) { ++ int result, ttyfd; ++ ++ /* ++ * Parent asks us to revoke the terminal when the ++ * user's terminal goes away. Doing this in the ++ * monitor allows the foreground command to receive ++ * SIGHUP before the terminal is revoked. ++ */ ++ result = ioctl(io_fds[SFD_FOLLOWER], TIOCNOTTY, NULL); ++ if (result == -1) { ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, ++ "%s: unable to revoke follower pty", __func__); ++ ttyfd = open(_PATH_TTY, O_RDWR); ++ if (ttyfd != -1) { ++ result = ioctl(ttyfd, TIOCNOTTY, NULL); ++ if (result == -1) { ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, ++ "%s: unable to revoke controlling tty", ++ __func__); ++ } ++ close(ttyfd); ++ } else { ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, ++ "%s: unable to open %s", __func__, _PATH_TTY); ++ } ++ } ++ if (result == 0) { ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "%s: revoked controlling tty for session", __func__); ++ } ++ /* Now tell the parent to close the pty leader. */ ++ send_status(fd, &cstmp); ++ } ++ break; ++ case CMD_SIGNO: + deliver_signal(mc, cstmp.val, true); +- } else { ++ break; ++ default: + sudo_warnx(U_("unexpected reply type on backchannel: %d"), + cstmp.type); ++ break; + } + } + debug_return; +diff --git a/src/exec_pty.c b/src/exec_pty.c +index 6c0f7583e..fff9b8f1e 100644 +--- a/src/exec_pty.c ++++ b/src/exec_pty.c +@@ -61,6 +61,7 @@ static struct exec_closure pty_ec; + static pid_t check_foreground(struct exec_closure_pty *ec); + static void add_io_events(struct sudo_event_base *evbase); + static void schedule_signal(struct exec_closure_pty *ec, int signo); ++static void send_command_status(struct exec_closure_pty *ec, int type, int val); + + /* + * Cleanup hook for sudo_fatal()/sudo_fatalx() +@@ -383,8 +384,18 @@ read_callback(int fd, int what, void *v) + ev_free_by_fd(evbase, fd); + /* If writer already consumed the buffer, close it too. */ + if (iob->wevent != NULL && iob->off == iob->len) { +- safe_close(sudo_ev_get_fd(iob->wevent)); +- ev_free_by_fd(evbase, sudo_ev_get_fd(iob->wevent)); ++ /* ++ * Don't close the pty leader, it will invalidate the pty. ++ * We ask the monitor to revoke the pty nicely using TIOCNOTTY. ++ */ ++ const int wfd = sudo_ev_get_fd(iob->wevent); ++ if (wfd == io_fds[SFD_LEADER]) { ++ sudo_debug_printf(SUDO_DEBUG_NOTICE, "user's tty revoked"); ++ send_command_status(iob->ec, CMD_IOCTL, TIOCNOTTY); ++ } else { ++ safe_close(wfd); ++ } ++ ev_free_by_fd(evbase, wfd); + iob->off = iob->len = 0; + } + break; +@@ -461,8 +472,18 @@ write_callback(int fd, int what, void *v) + iob->len - iob->off, fd); + /* Close reader if there is one. */ + if (iob->revent != NULL) { +- safe_close(sudo_ev_get_fd(iob->revent)); +- ev_free_by_fd(evbase, sudo_ev_get_fd(iob->revent)); ++ /* ++ * Don't close the pty leader, it will invalidate the pty. ++ * We ask the monitor to revoke the pty nicely using TIOCNOTTY. ++ */ ++ const int rfd = sudo_ev_get_fd(iob->revent); ++ if (rfd == io_fds[SFD_LEADER]) { ++ sudo_debug_printf(SUDO_DEBUG_NOTICE, "user's tty revoked"); ++ send_command_status(iob->ec, CMD_IOCTL, TIOCNOTTY); ++ } else { ++ safe_close(rfd); ++ } ++ ev_free_by_fd(evbase, rfd); + } + safe_close(fd); + ev_free_by_fd(evbase, fd); +@@ -656,6 +677,28 @@ backchannel_cb(int fd, int what, void *v) + case sizeof(cstat): + /* Check command status. */ + switch (cstat.type) { ++ case CMD_ERRNO: ++ /* Monitor was unable to execute command or broken pipe. */ ++ sudo_debug_printf(SUDO_DEBUG_INFO, "errno from monitor: %s", ++ strerror(cstat.val)); ++ sudo_ev_loopbreak(ec->evbase); ++ *ec->cstat = cstat; ++ break; ++ case CMD_IOCTL: ++ if (cstat.val != TIOCNOTTY) { ++ sudo_warnx(U_("unexpected ioctl on backchannel: %d"), ++ cstat.val); ++ } else if (io_fds[SFD_LEADER] != -1) { ++ /* ++ * Monitor requests that we revoke the user's terminal. ++ * This must happen after the monitor has used TIOCNOTTY ++ * to invalidate the session and gracefully kill the ++ * controlling terminal's process group. ++ */ ++ close(io_fds[SFD_LEADER]); ++ io_fds[SFD_LEADER] = -1; ++ } ++ break; + case CMD_PID: + ec->cmnd_pid = cstat.val; + sudo_debug_printf(SUDO_DEBUG_INFO, "executed %s, pid %d", +@@ -693,13 +736,6 @@ backchannel_cb(int fd, int what, void *v) + *ec->cstat = cstat; + } + break; +- case CMD_ERRNO: +- /* Monitor was unable to execute command or broken pipe. */ +- sudo_debug_printf(SUDO_DEBUG_INFO, "errno from monitor: %s", +- strerror(cstat.val)); +- sudo_ev_loopbreak(ec->evbase); +- *ec->cstat = cstat; +- break; + } + /* Keep reading command status messages until EAGAIN or EOF. */ + break; +@@ -1382,7 +1418,7 @@ exec_pty(struct command_details *details, + if (sudo_ev_dispatch(ec.evbase) == -1) + sudo_warn("%s", U_("error in event loop")); + if (sudo_ev_got_break(ec.evbase)) { +- /* error from callback or monitor died */ ++ /* error from callback */ + sudo_debug_printf(SUDO_DEBUG_ERROR, "event loop exited prematurely"); + /* XXX: no good way to know if we should terminate the command. */ + if (cstat->val == CMD_INVALID && ec.cmnd_pid != -1) { +diff --git a/src/sudo.h b/src/sudo.h +index a7450dca9..ca245ca68 100644 +--- a/src/sudo.h ++++ b/src/sudo.h +@@ -225,6 +225,7 @@ struct command_status { + #define CMD_WSTATUS 2 + #define CMD_SIGNO 3 + #define CMD_PID 4 ++#define CMD_IOCTL 5 + int type; + int val; + }; +-- +2.33.0 + diff --git a/backport-Move-updating-of-the-window-size-back-to-the-main-su.patch b/backport-Move-updating-of-the-window-size-back-to-the-main-su.patch new file mode 100644 index 0000000000000000000000000000000000000000..20b8009a30a7d1468531dd305e55139d2e5d0518 --- /dev/null +++ b/backport-Move-updating-of-the-window-size-back-to-the-main-su.patch @@ -0,0 +1,234 @@ +From adb84293abfc1c3349ab34c03b036f1756e89aca Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Tue, 21 Mar 2023 15:30:54 -0600 +Subject: [PATCH] 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. + + +Reference:https://github.com/sudo-project/sudo/commit/adb84293abfc1c3349ab34c03b036f1756e89aca +Conflict:src/exec_monitor.c src/exec_pty.c + +--- + src/exec_monitor.c | 60 ++++++---------------------------------------- + src/exec_pty.c | 23 +++++++++--------- + src/sudo.h | 1 - + 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 + + #include +-#include + #include + #include + #include +@@ -35,7 +34,6 @@ + #include + #include + #include +-#include + + #include "sudo.h" + #include "sudo_exec.h" +@@ -62,8 +60,6 @@ struct monitor_closure { + struct sudo_event *sigchld_event; + }; + +-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: +@@ -130,34 +121,6 @@ deliver_signal(struct monitor_closure *mc, int signo, bool from_parent) + debug_return; + } + +-/* +- * 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, + sigprocmask(SIG_SETMASK, oset, NULL); + close(backchannel); + close(errpipe[0]); +- if (io_fds[SFD_USERTTY] != -1) +- close(io_fds[SFD_USERTTY]); + restore_signals(); + + /* setup tty and exec command */ +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]; + int io_fds[6] = { -1, -1, -1, -1, -1, -1}; + static bool foreground, pipeline; ++static bool tty_initialized; + static int ttymode = TERM_COOKED; + static sigset_t ttyblock; + static struct io_buffer_list iobufs; +@@ -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_pty *ec) +@@ -1358,14 +1359,12 @@ sync_ttysize(struct exec_closure_pty *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; + }; +-- +2.33.0 + diff --git a/sudo.spec b/sudo.spec index 0c52402e1132fa1d0dc0b70053d0247455ac35aa..33308592ae7c7051f98185ca80222ee1f3fd9925 100644 --- a/sudo.spec +++ b/sudo.spec @@ -1,6 +1,6 @@ Name: sudo Version: 1.9.8p2 -Release: 17 +Release: 18 Summary: Allows restricted root access for specified users License: ISC URL: http://www.courtesan.com/sudo/ @@ -43,6 +43,9 @@ Patch29: backport-Do-not-rely-on-the-definition-of-ALLOW-DENY-being-tr.patch Patch30: backport-CVE-2023-42465.patch Patch31: backport-Make-all-match-functions-return-ALLOW-DENY-.patch Patch32: backport-role_to_sudoers-only-try-to-reuse-a-privilege-if-one.patch +Patch33: backport-Move-updating-of-the-window-size-back-to-the-main-su.patch +Patch34: backport-If-user-s-tty-goes-away-tell-monitor-to-revoke-the-t.patch +Patch35: backport-Avoid-using-ioctl-TIOCNOTTY-in-the-monitor.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -194,6 +197,9 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/etc/pam.d/sudo-i %exclude %{_pkgdocdir}/ChangeLog %changelog +* Fri Apr 18 2025 fuanan - 1.9.8p2-18 +- Backport patch from upstream community + * Wed Jan 31 2024 fuanan - 1.9.8p2-17 - Backport patch from upstream community