226 lines
7.7 KiB
Diff
226 lines
7.7 KiB
Diff
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:NA
|
|
|
|
---
|
|
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-2023 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-2023 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 the command itself or a member of the
|
|
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
|
|
|