Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ internal static partial class Sys
internal static unsafe int ForkAndExecProcess(
string filename, string[] argv, IDictionary<string, string?> env, string? cwd,
bool setUser, uint userId, uint groupId, uint[]? groups,
out int lpChildPid, SafeFileHandle? stdinFd, SafeFileHandle? stdoutFd, SafeFileHandle? stderrFd, bool shouldThrow = true)
out int lpChildPid, SafeFileHandle? stdinFd, SafeFileHandle? stdoutFd, SafeFileHandle? stderrFd,
IList<SafeHandle>? inheritedHandles = null, bool shouldThrow = true)
{
byte** argvPtr = null, envpPtr = null;
int result = -1;

bool stdinRefAdded = false, stdoutRefAdded = false, stderrRefAdded = false;
bool inheritedHandleRefsAdded = false;
try
{
int stdinRawFd = -1, stdoutRawFd = -1, stderrRawFd = -1;
Expand All @@ -44,14 +46,33 @@ internal static unsafe int ForkAndExecProcess(
stderrRawFd = stderrFd.DangerousGetHandle().ToInt32();
}

// inheritedFdCount == -1 means no restriction; >= 0 means restrict to stdio + list
int inheritedFdCount = -1;
int[]? inheritedFds = null;

if (inheritedHandles is not null)
{
inheritedFdCount = inheritedHandles.Count;
inheritedFds = new int[inheritedFdCount];

for (int i = 0; i < inheritedFdCount; i++)
{
SafeHandle handle = inheritedHandles[i];
handle.DangerousAddRef(ref inheritedHandleRefsAdded);
inheritedFds[i] = handle.DangerousGetHandle().ToInt32();
}
}

AllocArgvArray(argv, ref argvPtr);
AllocEnvpArray(env, ref envpPtr);
fixed (uint* pGroups = groups)
fixed (int* pInheritedFds = inheritedFds)
{
result = ForkAndExecProcess(
filename, argvPtr, envpPtr, cwd,
setUser ? 1 : 0, userId, groupId, pGroups, groups?.Length ?? 0,
out lpChildPid, stdinRawFd, stdoutRawFd, stderrRawFd);
out lpChildPid, stdinRawFd, stdoutRawFd, stderrRawFd,
pInheritedFds, inheritedFdCount);
}
return result == 0 ? 0 : Marshal.GetLastPInvokeError();
}
Expand All @@ -66,14 +87,23 @@ internal static unsafe int ForkAndExecProcess(
stdoutFd!.DangerousRelease();
if (stderrRefAdded)
stderrFd!.DangerousRelease();

if (inheritedHandleRefsAdded && inheritedHandles is not null)
{
for (int i = 0; i < inheritedHandles.Count; i++)
{
inheritedHandles[i].DangerousRelease();
}
}
}
}

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_ForkAndExecProcess", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)]
private static unsafe partial int ForkAndExecProcess(
string filename, byte** argv, byte** envp, string? cwd,
int setUser, uint userId, uint groupId, uint* groups, int groupsLength,
out int lpChildPid, int stdinFd, int stdoutFd, int stderrFd);
out int lpChildPid, int stdinFd, int stdoutFd, int stderrFd,
int* inheritedFds, int inheritedFdCount);

/// <summary>
/// Allocates a single native memory block containing both a null-terminated pointer array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ internal static unsafe partial bool CreateProcessWithLogonW(
int creationFlags,
IntPtr environmentBlock,
string? lpCurrentDirectory,
ref Interop.Kernel32.STARTUPINFO lpStartupInfo,
ref Interop.Kernel32.PROCESS_INFORMATION lpProcessInformation);
Interop.Kernel32.STARTUPINFOEX* lpStartupInfo,
Interop.Kernel32.PROCESS_INFORMATION* lpProcessInformation);

[Flags]
internal enum LogonFlags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
Expand All @@ -19,10 +17,10 @@
ref SECURITY_ATTRIBUTES threadSecAttrs,
[MarshalAs(UnmanagedType.Bool)] bool bInheritHandles,
int dwCreationFlags,
IntPtr lpEnvironment,
char* lpEnvironment,
string? lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
ref PROCESS_INFORMATION lpProcessInformation
STARTUPINFOEX* lpStartupInfo,
PROCESS_INFORMATION* lpProcessInformation
);

[StructLayout(LayoutKind.Sequential)]
Expand Down Expand Up @@ -56,5 +54,37 @@
internal IntPtr hStdOutput;
internal IntPtr hStdError;
}

internal const int PROC_THREAD_ATTRIBUTE_HANDLE_LIST = 0x00020002;
internal const int EXTENDED_STARTUPINFO_PRESENT = 0x00080000;

[StructLayout(LayoutKind.Sequential)]
internal struct STARTUPINFOEX
{
internal STARTUPINFO StartupInfo;
internal void* lpAttributeList;

Check failure on line 65 in src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop (Build linux-x64 debug Libraries_WithPackages)

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs#L65

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs(65,22): error CS0214: (NETCORE_ENGINEERING_TELEMETRY=Build) Pointers and fixed size buffers may only be used in an unsafe context

Check failure on line 65 in src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop (Build Source-Build (Linux_x64))

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs#L65

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs(65,22): error CS0214: (NETCORE_ENGINEERING_TELEMETRY=Build) Pointers and fixed size buffers may only be used in an unsafe context

Check failure on line 65 in src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs#L65

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs(65,22): error CS0214: (NETCORE_ENGINEERING_TELEMETRY=Build) Pointers and fixed size buffers may only be used in an unsafe context

Check failure on line 65 in src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs#L65

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs(65,22): error CS0214: (NETCORE_ENGINEERING_TELEMETRY=Build) Pointers and fixed size buffers may only be used in an unsafe context
}

[LibraryImport(Libraries.Kernel32, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool InitializeProcThreadAttributeList(
void* lpAttributeList,
int dwAttributeCount,
int dwFlags,
ref nuint lpSize);

[LibraryImport(Libraries.Kernel32, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool UpdateProcThreadAttribute(
void* lpAttributeList,
int dwFlags,
IntPtr attribute,
void* lpValue,
nuint cbSize,
void* lpPreviousValue,
nuint lpReturnSize);

[LibraryImport(Libraries.Kernel32, SetLastError = true)]
internal static unsafe partial void DeleteProcThreadAttributeList(void* lpAttributeList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ public ProcessStartInfo(string fileName, System.Collections.Generic.IEnumerable<
public Microsoft.Win32.SafeHandles.SafeFileHandle? StandardOutputHandle { get { throw null; } set { } }
public System.Text.Encoding? StandardInputEncoding { get { throw null; } set { } }
public System.Text.Encoding? StandardOutputEncoding { get { throw null; } set { } }
public System.Collections.Generic.IList<System.Runtime.InteropServices.SafeHandle>? InheritedHandles { get { throw null; } set { } }
[System.Diagnostics.CodeAnalysis.AllowNullAttribute]
public string UserName { get { throw null; } set { } }
public bool UseShellExecute { get { throw null; } set { } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ private static SafeProcessHandle ForkAndExecProcess(
errno = Interop.Sys.ForkAndExecProcess(
resolvedFilename, argv, env, cwd,
setCredentials, userId, groupId, groups,
out childPid, stdinHandle, stdoutHandle, stderrHandle);
out childPid, stdinHandle, stdoutHandle, stderrHandle,
startInfo.InheritedHandles);

if (errno == 0)
{
Expand Down
Loading
Loading