2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 01:49:11 +00:00

When revoking the pty, kill the foreground process from the parent sudo.

There's no need to send messages back and forth to the monitor
when the main process can just do it.  GitHub issue #367.
This commit is contained in:
Todd C. Miller 2024-05-18 19:15:14 -06:00
parent 52772ae6eb
commit 62e4d29f8e
3 changed files with 30 additions and 59 deletions

View File

@ -310,41 +310,6 @@ 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 the session leader
* (sudo) exiting by sending SIGHUP to the foreground process group.
* The monitor process will not actually exit until the command exits.
*/
static void
mon_handle_revoke(int fd, pid_t pgrp, struct command_status *cstat)
{
debug_decl(mon_handle_revoke, SUDO_DEBUG_EXEC);
/*
* Signal the foreground process group (or the command's process group
* if no pty). We must do this before the pty is revoked by 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. This fixes a
* problem on Linux with, e.g. "sudo su" where su(1) blocks SIGHUP.
*/
if (io_fds[SFD_FOLLOWER] != -1) {
const pid_t tcpgrp = tcgetpgrp(io_fds[SFD_FOLLOWER]);
if (tcpgrp != -1)
pgrp = tcpgrp;
}
sudo_debug_printf(SUDO_DEBUG_NOTICE, "%s: killpg(%d, SIGHUP)",
__func__, (int)pgrp);
killpg(pgrp, SIGHUP);
/*
* Now that the foreground process as been signaled, send the
* parent CMD_REVOKE to close the pty leader, revoking the pty.
*/
send_status(fd, cstat);
}
static void
mon_backchannel_cb(int fd, int what, void *v)
{
@ -371,17 +336,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_REVOKE:
mon_handle_revoke(fd, mc->cmnd_pid, &cstmp);
break;
case CMD_SIGNO:
if (cstmp.type == CMD_SIGNO) {
deliver_signal(mc, cstmp.val, true);
break;
default:
} else {
sudo_warnx(U_("unexpected reply type on backchannel: %d"),
cstmp.type);
break;
}
}
debug_return;

View File

@ -332,6 +332,32 @@ sigttin(int signo)
got_sigttin = 1;
}
/*
* Close the leader fd to revoke the pty and signal the foreground pgrp.
* We send SIGHUP to the foreground process group (or the command's
* process group if no pty) after closing the leader fd. We cannot
* just forward the SIGHUP we receive from the kernel since the
* command may not be the foreground process. This fixes a problem
* on Linux with, e.g. "sudo su" where su(1) blocks SIGHUP.
*/
static void
revoke_pty(struct exec_closure *ec)
{
pid_t pgrp = ec->cmnd_pid;
debug_decl(revoke_pty, SUDO_DEBUG_EXEC);
sudo_debug_printf(SUDO_DEBUG_NOTICE, "user's tty revoked");
if (io_fds[SFD_LEADER] != -1) {
const pid_t tcpgrp = tcgetpgrp(io_fds[SFD_LEADER]);
if (tcpgrp != -1)
pgrp = tcpgrp;
close(io_fds[SFD_LEADER]);
}
sudo_debug_printf(SUDO_DEBUG_NOTICE, "%s: killpg(%d, SIGHUP)",
__func__, (int)pgrp);
kill(pgrp, SIGHUP);
}
/*
* Read an iobuf that is ready.
*/
@ -390,8 +416,7 @@ read_callback(int fd, int what, void *v)
*/
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_REVOKE, 0);
revoke_pty(iob->ec);
} else {
safe_close(wfd);
}
@ -478,8 +503,7 @@ write_callback(int fd, int what, void *v)
*/
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_REVOKE, 0);
revoke_pty(iob->ec);
} else {
safe_close(rfd);
}
@ -684,17 +708,6 @@ backchannel_cb(int fd, int what, void *v)
sudo_ev_loopbreak(ec->evbase);
*ec->cstat = cstat;
break;
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 signaled 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",

View File

@ -224,7 +224,6 @@ struct command_status {
#define CMD_WSTATUS 2
#define CMD_SIGNO 3
#define CMD_PID 4
#define CMD_REVOKE 5
int type;
int val;
};