File sudo-dont-enable-read-after-pty_finish.patch of Package sudo.32917
From 19a660612f02d24b3cede13f99643cc40ba2a0b3 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Wed, 1 Mar 2023 13:25:17 -0700
Subject: [PATCH] write_callback: only enable /dev/tty reader if the command is
running This fixes a hang when there is /dev/tty data in a buffer to be
flushed by the final call to del_io_events(). We do not want to re-enable
the reader when flushing the buffers as part of pty_finish(). See PR #247 for
analysis of the problem and how to reproduce it.
---
src/exec_nopty.c | 11 ++++++++---
src/exec_pty.c | 11 +++++++----
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/src/exec_nopty.c b/src/exec_nopty.c
index b4b01871ac..60794f7b60 100644
--- a/src/exec_nopty.c
+++ b/src/exec_nopty.c
@@ -447,10 +447,15 @@ write_callback(int fd, int what, void *v)
ev_free_by_fd(evbase, fd);
}
}
- /* Enable reader if buffer is not full. */
+ /*
+ * Enable reader if buffer is not full but avoid reading
+ * /dev/tty if the command is no longer running.
+ */
if (iob->revent != NULL && iob->len != sizeof(iob->buf)) {
- if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1)
- sudo_fatal("%s", U_("unable to add event to queue"));
+ if (!USERTTY_EVENT(iob->revent) || iob->ec->cmnd_pid != -1) {
+ if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
}
}
diff --git a/src/exec_pty.c b/src/exec_pty.c
index ed8fa0f3de..9a8ddfab18 100644
--- a/src/exec_pty.c
+++ b/src/exec_pty.c
@@ -469,10 +469,13 @@ write_callback(int fd, int what, void *v)
ev_free_by_fd(evbase, fd);
}
}
- /* Enable reader if buffer is not full. */
- if (iob->revent != NULL &&
- (ttymode == TERM_RAW || !USERTTY_EVENT(iob->revent))) {
- if (iob->len != sizeof(iob->buf)) {
+ /*
+ * Enable reader if buffer is not full but avoid reading /dev/tty
+ * if not in raw mode or the command is no longer running.
+ */
+ if (iob->revent != NULL && iob->len != sizeof(iob->buf)) {
+ if (!USERTTY_EVENT(iob->revent) ||
+ (ttymode == TERM_RAW && iob->ec->cmnd_pid != -1)) {
if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1)
sudo_fatal("%s", U_("unable to add event to queue"));
}