Skip to content
Open
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
7 changes: 7 additions & 0 deletions PCL.Core/App/Essentials/PromoteService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ private static void _PerformAsPromoteProcess(string pid)
var pipeName = _GetPromotePipeName(process.Id);
var pipe = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut);
pipe.Connect(10000);
var serverProcessId = (int)KernelInterop.GetNamedPipeServerProcessId(pipe.SafePipeHandle.DangerousGetHandle());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): 建议不要将服务器 PID 从 uint 强制转换为 int,以避免在较大的 PID 上发生潜在溢出和不匹配。

GetNamedPipeServerProcessId 返回 uint,而 Process.Idint。当数值超过 Int32.MaxValue 时,将 uint 强制转换为 int 会有溢出风险,并可能得到错误/负数的 PID。相反,建议保持服务器 PID 为 uint,并与 (uint)process.Id 进行比较:

var serverProcessId = KernelInterop.GetNamedPipeServerProcessId(pipe.SafePipeHandle.DangerousGetHandle());
if (serverProcessId != (uint)process.Id)
{
    // ...
}
Original comment in English

suggestion (bug_risk): Avoid casting the server PID from uint to int to prevent potential overflow and mismatches on large PIDs.

GetNamedPipeServerProcessId returns a uint while Process.Id is an int. Casting the uint to int risks overflow and an incorrect/negative PID if values exceed Int32.MaxValue. Instead, keep the server PID as uint and compare against (uint)process.Id:

var serverProcessId = KernelInterop.GetNamedPipeServerProcessId(pipe.SafePipeHandle.DangerousGetHandle());
if (serverProcessId != (uint)process.Id)
{
    // ...
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Verify the server from the server end instead

When the promoted helper reaches this line, pipe is a NamedPipeClientStream, so its handle was opened as the client end after Connect(). The Win32 GetNamedPipeServerProcessId API expects a named-pipe instance handle created by CreateNamedPipe (the server end), and the wrapper throws on failure; this means every promote launch aborts before Context.Info("已连接,开始通信"), leaving privileged start/start-json operations unusable rather than merely rejecting spoofed servers.

Useful? React with 👍 / 👎.

if (serverProcessId != process.Id)
{
Context.Error("管道服务端验证失败,正在退出");
pipe.Dispose();
return;
}
Context.Info("已连接,开始通信");
var reader = new StreamReader(pipe);
var writer = new StreamWriter(pipe);
Expand Down
15 changes: 15 additions & 0 deletions PCL.Core/Utils/OS/KernelInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public static partial class KernelInterop
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool _GetNamedPipeClientProcessId(IntPtr pipeHandle, out uint clientProcessId);

[LibraryImport("kernel32.dll", EntryPoint = "GetNamedPipeServerProcessId", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool _GetNamedPipeServerProcessId(IntPtr pipeHandle, out uint serverProcessId);

[LibraryImport("kernel32.dll", EntryPoint = "GetLogicalProcessorInformationEx", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool _GetLogicalProcessorInformationEx(
Expand Down Expand Up @@ -98,6 +102,17 @@ public static uint GetNamedPipeClientProcessId(IntPtr pipeHandle)
return clientProcessId;
}

/// <summary>
/// 获取指定命名管道当前连接的服务端进程 ID
/// </summary>
/// <param name="pipeHandle">命名管道句柄</param>
/// <returns>获取到的进程 ID</returns>
public static uint GetNamedPipeServerProcessId(IntPtr pipeHandle)
{
if (!_GetNamedPipeServerProcessId(pipeHandle, out var serverProcessId)) _ThrowLastWin32Error();
return serverProcessId;
}

/// <summary>
/// 获取仅包含性能核(P-core)的逻辑处理器数量。
/// 在不支持 EfficiencyClass(旧 OS 或非混合架构)时,会退回到 Environment.ProcessorCount。
Expand Down
Loading