!142 Backport patches from upstream community
From: @fly_fzc Reviewed-by: @houmingyong, @HuaxinLuGitee Signed-off-by: @HuaxinLuGitee
This commit is contained in:
commit
b5579133e8
225
backport-Avoid-using-ioctl-TIOCNOTTY-in-the-monitor.patch
Normal file
225
backport-Avoid-using-ioctl-TIOCNOTTY-in-the-monitor.patch
Normal file
@ -0,0 +1,225 @@
|
||||
From a2d01a957d31e133c37d77ae149527f9483e4f19 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
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 <Todd.Miller@sudo.ws>
|
||||
+ * Copyright (c) 2009-2024 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* 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 <Todd.Miller@sudo.ws>
|
||||
+ * Copyright (c) 2009-2024 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* 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
|
||||
|
||||
@ -0,0 +1,212 @@
|
||||
From 41978a56e042977923c1a55191b887218c536145 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
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
|
||||
|
||||
@ -0,0 +1,234 @@
|
||||
From adb84293abfc1c3349ab34c03b036f1756e89aca Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
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 <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 {
|
||||
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
|
||||
|
||||
@ -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)
|
||||
Requires: pam
|
||||
@ -193,6 +196,9 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/etc/pam.d/sudo-i
|
||||
%exclude %{_pkgdocdir}/ChangeLog
|
||||
|
||||
%changelog
|
||||
* Fri Apr 18 2025 fuanan <fuanan3@h-partners.com> - 1.9.8p2-18
|
||||
- Backport patch from upstream community
|
||||
|
||||
* Wed Jan 31 2024 fuanan <fuanan3@h-partners.com> - 1.9.8p2-17
|
||||
- Backport patch from upstream community
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user