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