[newlib-cygwin/cygwin-3_6-branch] Cygwin: pty: Guard get_winpid_to_hand_over() with attach_mutex

Takashi Yano tyan0@sourceware.org
Sun Mar 29 00:43:35 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=07ddd855a89dc7f94d74c0339c27294087588a46

commit 07ddd855a89dc7f94d74c0339c27294087588a46
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date:   Tue Mar 17 11:59:21 2026 +0900

    Cygwin: pty: Guard get_winpid_to_hand_over() with attach_mutex
    
    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.
    
    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.
    
    Fixes: 1e6c51d74136 ("Cygwin: pty: Reorganize the code path of setting up and closing pcon.")
    Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
    Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
    (cherry picked from commit 3adbd41f5babda5a42430fb25d9a02205c416542)

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 44b8f4f29..d0bf947d4 100644
--- a/winsup/cygwin/fhandler/pty.cc
+++ b/winsup/cygwin/fhandler/pty.cc
@@ -773,6 +773,12 @@ fhandler_pty_slave::open (int flags, mode_t)
       errmsg = "open pipe switch mutex failed, %E";
       goto err;
     }
+  if (!(attach_mutex
+	= get_ttyp ()->open_mutex (ATTACH_MUTEX, MAXIMUM_ALLOWED)))
+    {
+      errmsg = "open attach mutex failed, %E";
+      goto err;
+    }
   shared_name (buf, INPUT_AVAILABLE_EVENT, get_minor ());
   if (!(input_available_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf)))
     {
@@ -2503,6 +2509,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 = get_ttyp ()->open_mutex (ATTACH_MUTEX, MAXIMUM_ALLOWED);
 
   // fork_fixup (parent, inuse, "inuse");
   // fhandler_pty_common::fixup_after_fork (parent);
@@ -3164,8 +3173,9 @@ fhandler_pty_master::setup ()
   if (!(pipe_sw_mutex = CreateMutex (&sa, FALSE, buf)))
     goto err;
 
-  if (!attach_mutex)
-    attach_mutex = CreateMutex (&sec_none_nih, FALSE, NULL);
+  errstr = shared_name (buf, ATTACH_MUTEX, unit);
+  if (!(attach_mutex = CreateMutex (&sa, FALSE, buf)))
+    goto err;
 
   /* Create master control pipe which allows the master to duplicate
      the pty pipe handles to processes which deserve it. */
@@ -3719,6 +3729,7 @@ fhandler_pty_slave::get_winpid_to_hand_over (tty *ttyp,
       DWORD current_pid = myself->exec_dwProcessId ?: myself->dwProcessId;
       if (ttyp->nat_pipe_owner_pid == GetCurrentProcessId ())
 	current_pid = GetCurrentProcessId ();
+      acquire_attach_mutex (mutex_timeout);
       switch_to = get_console_process_id (current_pid,
 					  false, true, true, true);
       if (!switch_to)
@@ -3727,6 +3738,7 @@ fhandler_pty_slave::get_winpid_to_hand_over (tty *ttyp,
       if (!switch_to && ttyp->pcon_activated)
 	switch_to = 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_includes/tty.h
index 7d80ab401..6e70a74cd 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"


More information about the Cygwin-cvs mailing list