[newlib-cygwin] Cygwin: pty: Guard get_winpid_to_hand_over() with attach_mutex
Takashi Yano via Cygwin-cvs <[email protected]> Sun, 29 Mar 2026 00:44:05 +0000 (GMT)
| Newsgroups | gmane.os.cygwin.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D3adbd41f5ba= bda5a42430fb25d9a02205c416542 commit 3adbd41f5babda5a42430fb25d9a02205c416542 Author: Takashi Yano <[email protected]> Date: Tue Mar 17 11:59:21 2026 +0900 Cygwin: pty: Guard get_winpid_to_hand_over() with attach_mutex =20 The master process (e.g. mintty) temporarily attaches to the pseudo console's conhost in `transfer_input()` so it can read INPUT_RECORDs via `ReadConsoleInputA()`. During that brief window, `get_console_process_id()` inside `get_winpid_to_hand_over()` calls `GetConsoleProcessList()`, which sees the master among the console's attached processes and may select it as the handover target. That is wrong because the master will detach immediately after the read. =20 Until now, `attach_mutex` was a process-local unnamed mutex, so the slave's `get_winpid_to_hand_over()` could not serialize with the master's temporary attachment. Make `attach_mutex` a cross-process named mutex (`ATTACH_MUTEX`) shared within the PTY, and acquire it around the `get_console_process_id()` calls in `get_winpid_to_hand_over()`. This ensures the console process list enumeration never observes the master while it is temporarily attached. =20 Fixes: 1e6c51d74136 ("Cygwin: pty: Reorganize the code path of setting = up and closing pcon.") Signed-off-by: Takashi Yano <[email protected]> Reviewed-by: Johannes Schindelin <[email protected]> Diff: --- winsup/cygwin/fhandler/pty.cc | 16 ++++++++++++++-- winsup/cygwin/local_includes/tty.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index 90c7a9710..ac5f67bc4 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -774,6 +774,12 @@ fhandler_pty_slave::open (int flags, mode_t) errmsg =3D "open pipe switch mutex failed, %E"; goto err; } + if (!(attach_mutex + =3D get_ttyp ()->open_mutex (ATTACH_MUTEX, MAXIMUM_ALLOWED))) + { + errmsg =3D "open attach mutex failed, %E"; + goto err; + } shared_name (buf, INPUT_AVAILABLE_EVENT, get_minor ()); if (!(input_available_event =3D OpenEvent (MAXIMUM_ALLOWED, TRUE, buf))) { @@ -2525,6 +2531,9 @@ void fhandler_pty_slave::fixup_after_fork (HANDLE parent) { create_invisible_console (); + /* attach_mutex is initialized not only in the fork() case, but also in + the exec() case, since fixup_after_exec() calls fixup_after_fork(). */ + attach_mutex =3D get_ttyp ()->open_mutex (ATTACH_MUTEX, MAXIMUM_ALLOWED); =20 // fork_fixup (parent, inuse, "inuse"); // fhandler_pty_common::fixup_after_fork (parent); @@ -3161,8 +3170,9 @@ fhandler_pty_master::setup () if (!(pipe_sw_mutex =3D CreateMutex (&sa, FALSE, buf))) goto err; =20 - if (!attach_mutex) - attach_mutex =3D CreateMutex (&sec_none_nih, FALSE, NULL); + errstr =3D shared_name (buf, ATTACH_MUTEX, unit); + if (!(attach_mutex =3D CreateMutex (&sa, FALSE, buf))) + goto err; =20 /* Create master control pipe which allows the master to duplicate the pty pipe handles to processes which deserve it. */ @@ -3716,6 +3726,7 @@ fhandler_pty_slave::get_winpid_to_hand_over (tty *tty= p, DWORD current_pid =3D myself->exec_dwProcessId ?: myself->dwProcessI= d; if (ttyp->nat_pipe_owner_pid =3D=3D GetCurrentProcessId ()) current_pid =3D GetCurrentProcessId (); + acquire_attach_mutex (mutex_timeout); switch_to =3D get_console_process_id (current_pid, false, true, true, true); if (!switch_to) @@ -3724,6 +3735,7 @@ fhandler_pty_slave::get_winpid_to_hand_over (tty *tty= p, if (!switch_to && ttyp->pcon_activated) switch_to =3D get_console_process_id (current_pid, false, false, false, false); + release_attach_mutex (); } return switch_to; } diff --git a/winsup/cygwin/local_includes/tty.h b/winsup/cygwin/local_inclu= des/tty.h index cd1e202f1..962697782 100644 --- a/winsup/cygwin/local_includes/tty.h +++ b/winsup/cygwin/local_includes/tty.h @@ -22,6 +22,7 @@ details. */ #define OUTPUT_MUTEX "cygtty.output.mutex" #define INPUT_MUTEX "cygtty.input.mutex" #define PIPE_SW_MUTEX "cygtty.pipe_sw.mutex" +#define ATTACH_MUTEX "cygtty.attach.mutex" #define TTY_SLAVE_ALIVE "cygtty.slave_alive" #define TTY_SLAVE_READING "cygtty.slave_reading"