dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.12k stars 4.7k forks source link

ArgumentOutOfRangeException in NtProcessInfoHelper.GetProcessInfos when retrieving Process.SessionId #108798

Open marius-bughiu opened 5 days ago

marius-bughiu commented 5 days ago

Description

Hi team 👋 , I'm running into the following ArgumentOutOfRangeException on all of the machines of a certain customer, when making a simple call to retrieve the current process' SessionId. For context, we're talking about a .NET 8.0.0 (sdk: 8.0.100) WPF application.

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
   at System.Diagnostics.NtProcessInfoHelper.GetProcessInfos(ReadOnlySpan`1 data, Nullable`1 processIdFilter, String processNameFilter)
   at System.Diagnostics.NtProcessInfoHelper.GetProcessInfos(Nullable`1 processIdFilter, String processNameFilter)
   at System.Diagnostics.ProcessManager.GetProcessInfo(Int32 processId, String machineName)
   at System.Diagnostics.Process.EnsureState(State state)
   at System.Diagnostics.Process.get_SessionId()

The exception occurs when trying to Slice the ReadOnlySpan.

0:000> !clrstack2
DbgId ThreadId Apartment Kind CLR           GC Mode    GC Suspending?
    0     3c74 STA            v8.0.23.53103 Preemptive no

SP               IP               Function                                                                                                                                                                                                            Source
000000d307f79038 0000000000000000 HelperMethodFrame                                                                                                                                                                                                   
000000d307f79130 00007ffab8f6bd36 System.ThrowHelper.ThrowArgumentOutOfRangeException()                                                                                                                                                               /_/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs @ 82
000000d307f79170 00007ffb17098329 System.ReadOnlySpan`1[[System.Byte, System.Private.CoreLib]].Slice(Int32)                                                                                                                                           /_/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs @ 351
000000d307f791a0 00007ffb1b1b13ff System.Diagnostics.NtProcessInfoHelper.GetProcessInfos(System.ReadOnlySpan`1<Byte>, System.Nullable`1<Int32>, System.String)                                                                                        /_/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Win32.cs @ 334
000000d307f792e0 00007ffb1b1b129a System.Diagnostics.NtProcessInfoHelper.GetProcessInfos(System.Nullable`1<Int32>, System.String)                                                                                                                     /_/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Win32.cs @ 307

This is the code triggering the exception:

using var process = Process.GetCurrentProcess();
CurrentProcessId = process.Id;
CurrentSessionId = process.SessionId;

We cannot debug on the customer's machine, but we were able to capture a memory dump of the process when it crashed. Based on that dump, I've managed to extract the byte[] returned by NtQuerySystemInformation and what happens is:

I've turned the dotnet code upside down and on all sides, and I cannot figure out a code path on which this could possibly happen. Interop.NtDll.NtQuerySystemInformation looks to provide a snapshot in time of the processes, so there should be no overrun due to newly created processes. The only other option is that Interop.NtDll.NtQuerySystemInformation returns invalid data.

_Some other things we've tried:

Thoughts on why this might happen / how we could troubleshoot this further? Any help would be greatly appreciated, thank you!

Reproduction Steps

using var process = Process.GetCurrentProcess();
CurrentProcessId = process.Id;
CurrentSessionId = process.SessionId;

Expected behavior

No exception is thrown and the correct SessionId is returned.

Actual behavior

ArgumentOutOfRangeException is thrown when retrieving the SessionId.

Regression?

On the same machines, a .NET 6 version of the same application works without any issues. Though this might no be very relevant, since we're not able to reproduce this with a .NET 8 console application either.

Known Workarounds

No response

Configuration

Other information

No response

dotnet-policy-service[bot] commented 5 days ago

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process See info in area-owners.md if you want to be subscribed.

jkotas commented 4 days ago

Thoughts on why this might happen / how we could troubleshoot this further?

Since this happens on all of the machines of a certain customer, I would double check for a buggy security monitoring software:

The security monitoring software often intercept Windows OS APIs and make the APIs behave incorrectly. (For example, hang tracked by https://github.com/dotnet/runtime/issues/108144 is a different issue caused by a buggy security software.)