Segfault if /proc/PID/maps is opened in parallel threads [CAUSE: RtlQueryProcessDebugInformation]
Christian Franke
Christian.Franke@t-online.de
Wed Jul 2 14:18:13 GMT 2025
On Tue, 27 May 2025 17:44:10 +0200 Christian Franke wrote:
> On Sun, 25 May 2025 16:46:49 +0200, Christian Franke wrote:
>> On Sat, 24 May 2025 15:19:10 +0200, Christian Franke wrote:
>>> If /proc/PID/maps is opened in parallel threads, the process PID may
>>> segfault.
>>>
>>> Testcase:
>>>
>>> ...
>>>
>>> Problem is not reproducible with any of the other /proc/PID/* files.
>>>
>>
>> A closer look shows that the problem is unrelated to thread safety.
>> The segfault also occurs when the following command is run
>> simultaneously in two terminals:
>>
>> $ while cat /proc/1234/maps > /dev/null; do printf .; done
>> .............cat: /proc/1234/maps: No such file or directory
>>
>
> The root of the problem is the call of
> RtlQueryProcessDebugInformation() here:
> https://cygwin.com/git/?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/fhandler/process.cc;h=8fae9be5#l630
>
>
> If this part is removed, the segfault does no longer occur. Then
> /proc/PID/maps still work but the "[win heap ...]" information is
> missing. No patch provided because I don't know whether this could
> possibly be fixed without removing this functionality.
>
> A test with a separate test program shows that the problem is
> unrelated to Cygwin: Parallel calls to
> RtlQueryProcessDebugInformation() with the same PID could be used to
> crash this process. It also "worked" with Notepad.exe.
>
> Possible Windows (Version 10.0.22631.5039) bug?
>
Testcase (attached):
$ gcc -o querydebug querydebug.c -lntdll
$ sleep 3600 &
[1] 3940
$ ps -p 3940
PID PPID PGID WINPID TTY UID STIME COMMAND
3940 1379 3940 18036 pty0 197609 15:52:50
/usr/bin/sleep
$ while ./querydebug 18036; do printf .; done & \
while ./querydebug 18036; do printf +; done
[2] 3943
.+.+.+.+.+RtlQueryProcessDebugInformation(): NTSTATUS = 0xC0000005
+RtlQueryProcessDebugInformation(): NTSTATUS = 0xC000000B
[1]- Done sleep 3600
[2]+ Done while ./querydebug ...
Conclusion: Possible Windows bug in RtlQueryProcessDebugInformation().
Cygwin should not use this function to provide "nice to have" types of
information like "[win heap...]" if this may crash the target process.
--
Regards,
Christian
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
// From ntdll.h
typedef struct { int dummy; } *PDEBUG_BUFFER;
PDEBUG_BUFFER RtlCreateQueryDebugBuffer (ULONG, BOOLEAN);
NTSTATUS RtlQueryProcessDebugInformation (ULONG, ULONG, PDEBUG_BUFFER);
NTSTATUS RtlDestroyQueryDebugBuffer (PDEBUG_BUFFER);
#define PDI_HEAPS 0x04
#define PDI_HEAP_BLOCKS 0x10
// From ntdll.h end
int main(int argc, char **argv)
{
if (argc != 2) {
printf("Usage: %s WINPID\n", argv[0]); return 1;
}
int pid = atoi(argv[1]);
PDEBUG_BUFFER buf = RtlCreateQueryDebugBuffer(0x100000, FALSE);
if (!buf) {
printf("RtlCreateQueryDebugBuffer(): failed\n"); return 1;
}
NTSTATUS s = RtlQueryProcessDebugInformation(pid,
PDI_HEAPS | PDI_HEAP_BLOCKS, buf);
RtlDestroyQueryDebugBuffer(buf);
if (s < 0) {
// Observed:
// STATUS_ACCESS_VIOLATION (0xC0000005)
// STATUS_INVALID_CID (0xC000000B)
// STATUS_PROCESS_IS_TERMINATING (0xC000010A)
printf("RtlQueryProcessDebugInformation(): NTSTATUS = 0x%X\n", s);
return 1;
}
return 0;
}
More information about the Cygwin
mailing list