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

commit 3ca80d1ac7be09b33125258c1efbeb1351147f01
Author:     Corinna Vinschen <cori...@vinschen.de>
AuthorDate: Thu Jul 3 12:57:10 2025 +0200
Commit:     Corinna Vinschen <cori...@vinschen.de>
CommitDate: Thu Jul 3 12:59:19 2025 +0200

    Cygwin: format_process_maps: avoid crashing PID when fetching heap info
    
    To fetch heap info for a process in our /proc/PID/maps emulation,
    we call RtlQueryProcessDebugInformation on this process since
    commit b4966f91396b ("(heap_info::heap_info): Rearrange using
    RtlQueryProcessDebugInformation").
    
    However, it turns out that this call can crash the targeted
    process, if it's called from multiple threads or processes in
    parallel.
    
    Worse, the entire code from creating the debug buffer, over
    fetching the debug info, subsequent collecting the information
    from said debug buffer, up to destroying the buffer, needs to be
    guarded against parallel access.
    
    We do this by adding a global mutex object, serializing access to
    the debug info of a process.
    
    Reported-by: Christian Franke <christian.fra...@t-online.de>
    Fixes: b4966f91396b ("(heap_info::heap_info): Rearrange using 
RtlQueryProcessDebugInformation")
    Signed-off-by: Corinna Vinschen <cori...@vinschen.de>
    (cherry picked from commit f075f3ba2720b4cca65e63b67c865959ba6b6c92)

Diff:
---
 winsup/cygwin/fhandler/process.cc | 33 ++++++++++++++++++++++++++++++---
 winsup/cygwin/release/3.6.4       |  4 ++++
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/fhandler/process.cc 
b/winsup/cygwin/fhandler/process.cc
index 8fae9be5f678..e00cae58d7b2 100644
--- a/winsup/cygwin/fhandler/process.cc
+++ b/winsup/cygwin/fhandler/process.cc
@@ -621,14 +621,39 @@ struct heap_info
     : heap_vm_chunks (NULL)
   {
     PDEBUG_BUFFER buf;
+    wchar_t mtx_name [32];
+    HANDLE mtx;
     NTSTATUS status;
     PDEBUG_HEAP_ARRAY harray;
 
+    /* We need a global mutex here, because RtlQueryProcessDebugInformation
+       is neither thread-safe, nor multi-process-safe.  If it's called in
+       parallel on the same process it can crash that process.  We can't
+       avoid this if a non-Cygwin app calls RtlQueryProcessDebugInformation
+       on the same process in parallel, but we can avoid Cygwin processes
+       crashing process PID just because they open /proc/PID/maps in parallel
+       by serializing RtlQueryProcessDebugInformation on the same process.
+
+       Note that the mutex guards the entire code from
+       RtlCreateQueryDebugBuffer to RtlDestroyQueryDebugBuffer including the
+       code accessing the debug buffer.  Apparently the debug buffer needs
+       safeguarded against parallel access all the time it's used!!! */
+    __small_swprintf (mtx_name, L"cyg-heapinfo-mtx-%u", pid);
+    mtx = CreateMutexW (&sec_none_nih, FALSE, mtx_name);
+    if (!mtx)
+      return;
+    WaitForSingleObject (mtx, INFINITE);
     buf = RtlCreateQueryDebugBuffer (16 * 65536, FALSE);
+    if (buf)
+      status = RtlQueryProcessDebugInformation (pid,
+                                               PDI_HEAPS | PDI_HEAP_BLOCKS,
+                                               buf);
     if (!buf)
-      return;
-    status = RtlQueryProcessDebugInformation (pid, PDI_HEAPS | PDI_HEAP_BLOCKS,
-                                             buf);
+      {
+       ReleaseMutex (mtx);
+       CloseHandle (mtx);
+       return;
+      }
     if (NT_SUCCESS (status)
        && (harray = (PDEBUG_HEAP_ARRAY) buf->HeapInformation) != NULL)
       for (ULONG hcnt = 0; hcnt < harray->Count; ++hcnt)
@@ -653,6 +678,8 @@ struct heap_info
              }
        }
     RtlDestroyQueryDebugBuffer (buf);
+    ReleaseMutex (mtx);
+    CloseHandle (mtx);
   }
 
   char *fill_if_match (char *base, ULONG type, char *dest)
diff --git a/winsup/cygwin/release/3.6.4 b/winsup/cygwin/release/3.6.4
index eb0d92bd498e..3286991cc081 100644
--- a/winsup/cygwin/release/3.6.4
+++ b/winsup/cygwin/release/3.6.4
@@ -21,3 +21,7 @@ Fixes:
 
 - Fix unexpected blocking mode change by pipe_data_available()
   Addresses: 
https://github.com/git-for-windows/git/issues/5682#issuecomment-2997428207
+
+- Fix potential crashing a process PID by accessing /proc/PID/maps
+  in parallel.
+  Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258198.html

Reply via email to