Add ProcessStartInfo.InheritedHandles to restrict child process handle inheritance#126318
Add ProcessStartInfo.InheritedHandles to restrict child process handle inheritance#126318
Conversation
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/9d1807f7-d4f3-4d70-bf98-1a9cdca1ea2f Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…sAddRef ordering, test robustness Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/9d1807f7-d4f3-4d70-bf98-1a9cdca1ea2f Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please address my feedback
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
…OEX refactoring, auto-property, RemoteExecutor tests Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/8ed756c4-f9e3-4311-902b-2e2b283c2682 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please address my feedback
src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateProcessWithLogon.cs
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ProcThreadAttributeList.cs
Outdated
Show resolved
Hide resolved
… improve tests Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/cbca9e9f-f00e-4bc2-86ee-96f18d939d95 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… where it is used Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/8109f39a-053e-4c14-840d-2d6c4e6cd104 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please address my feedback
src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ProcThreadAttributeList.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.cs
Outdated
Show resolved
Hide resolved
…ts, fdwalk support Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/87042cef-4c5c-4a21-971b-4c746ab48ee8 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
All addressed in 6d4cbac. Summary of changes:
|
| // Ignore errors - if the kernel doesn't support it, continue anyway | ||
| #elif HAVE_FDWALK | ||
| // On Illumos/Solaris, use fdwalk() to set FD_CLOEXEC on all open fds >= 3. | ||
| fdwalk(SetCloexecForFd, NULL); |
There was a problem hiding this comment.
to other reviewers: the alternative would be to have a fallback (for both distros that don't support any of these and OSes where the above sys-calls have failed) and just iterate over all opened fd.
It would be executed in following cases (ofc when the feature would be enabled):
- Linux: seccomp sandbox or very old Linux that we don't officially support anyway (RHEL is fine, so is Azure Linux)
- macOS: case where username and password were provided
- FreeBSD: very old BSD? I am not sure if we support these
- Android: very old Android? I am not sure if we support these but anyway running processes on mobile is not a common thing
There was a problem hiding this comment.
@jkotas @stephentoub please let me know what do you think would be best
cc @tmds
There was a problem hiding this comment.
What is the use case that we are designing this API for? Should the docs say when people should use this API?
If the use case is correctness, it does not sound right to fail silently like the current implementation does.
| throw new InvalidOperationException(SR.CantRedirectStreams); | ||
| } | ||
|
|
||
| if (UseShellExecute && InheritedHandles is not null && InheritedHandles.Count > 0) |
There was a problem hiding this comment.
to other reviewers: we could support it on Unix, but it would not be consistent with Windows
🤖 Copilot Code Review — PR #126318Note This review was generated by GitHub Copilot. Holistic AssessmentMotivation: Well-justified. This addresses the long-standing issue #13943 (from 2019) and implements the API approved in #125838. Explicit handle inheritance control is a real need for security and resource management. Approach: The overall approach is sound — using Summary: Detailed Findings
|
src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs
Outdated
Show resolved
Hide resolved
| #elif HAVE_CLOSE_RANGE_SYSCALL | ||
| // On Linux with older glibc that doesn't expose close_range() as a function, | ||
| // use the raw syscall number if the kernel supports it (kernel >= 5.9). | ||
| syscall(__NR_close_range, 3, ~0U, CLOSE_RANGE_CLOEXEC); |
There was a problem hiding this comment.
Are either of these two paths compiled into our official builds?
(We are compiling against glibc 2.27 for .NET 11 - #120826 - so I assume that the above path is not taken.)
There was a problem hiding this comment.
-- Looking for close_range
-- Looking for close_range - not found
-- Looking for __NR_close_range
-- Looking for __NR_close_range - not found
This is flagged by failing InheritedHandles_CanRestrictHandleInheritance.
There was a problem hiding this comment.
It means you need a local copy to make this work. Look for __NR_copy_file_range for existing art.
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs
Outdated
Show resolved
Hide resolved
…ShellExecute validation Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0552d117-e8d0-4995-852e-396fda9f00c1 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
| // set CLOEXEC on all FDs >= 3 in one call. FDs 0-2 are stdin/stdout/stderr. | ||
| // This must be called AFTER the dup2 calls above so that if stdinFd/stdoutFd/stderrFd | ||
| // are >= 3, they don't get CLOEXEC set before being duplicated to 0/1/2. | ||
| close_range(3, ~0U, CLOSE_RANGE_CLOEXEC); |
There was a problem hiding this comment.
Do we need to pass the CLOSE_RANGE_CLOEXEC flag?
There was a problem hiding this comment.
Ah yes, we're adding CLOEXEC here and we'll remove it from the inherited handles later.
Might be useful to put this in a comment.
| check_symbol_exists( | ||
| __NR_close_range | ||
| "sys/syscall.h" | ||
| HAVE_CLOSE_RANGE_SYSCALL) | ||
|
|
There was a problem hiding this comment.
| check_symbol_exists( | |
| __NR_close_range | |
| "sys/syscall.h" | |
| HAVE_CLOSE_RANGE_SYSCALL) |
This should not be needed.
LPPROC_THREAD_ATTRIBUTE_LISTstruct; usevoid*in all related P/Invoke signatures (InitializeProcThreadAttributeList,UpdateProcThreadAttribute,DeleteProcThreadAttributeList,STARTUPINFOEX.lpAttributeList)CreateProcess/CreateProcessWithLogonWP/Invokes to useSTARTUPINFOEX*/PROCESS_INFORMATION*instead ofrefSafeProcessHandle.Windows.cs: removeLPPROC_THREAD_ATTRIBUTE_LISTvariable, simplifyBuildProcThreadAttributeListto use singlevoid*buffer, update call sites to use&startupInfoEx/&processInfoUseShellExecutevalidation: reject non-nullInheritedHandlesregardless of Count