.Net Core子进程不会从父进程(Windows)继承(套接字)句柄。

3
我们在C#中实现了一个Windows程序集。该程序监听套接字以接收传入的连接,并启动子进程(非托管的c代码),这些子进程应该使用此套接字。子进程由包含套接字句柄的参数的命令行启动。整个机制在.Net 4.8 Framework下运行良好,但在.Net 6下失败。以下是我们正在使用的代码摘录:
        GetUserNameAndDomain(user, out var userName, out var domain);
        var process = new Process{StartInfo = new ProcessStartInfo(command, arguments){UseShellExecute = false}};
        WrapperImpersonationContext wrapperImpersonationContext  = new WrapperImpersonationContext(domain, userName, password.ToUnsecureString(), false, false);
        using (wrapperImpersonationContext) {
            Action impersonationAction = () =>
            {
                    process.Start();
            };
            wrapperImpersonationContext.Enter(impersonationAction);
        }

这里的模拟身份主要是做类似于以下操作:

     public WrapperImpersonationContext(string domain, string username, string password, bool automaticallyEnter = true, bool logonAsService = false) {
        mDomain = domain;
        mUsername = username;
        mPassword = password;
        mLogonType = logonAsService ? LOGON32_LOGON_SERVICE : LOGON32_LOGON_INTERACTIVE;
        if (automaticallyEnter)
            Enter();
    }

    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    public void Enter(Action impersonationAction = null) {
        //if (IsInContext)
        //    return;
        mToken = new IntPtr(0);
        try {
            LogFactory.WriteVerbose("Logon to user '{0}' in domain '{1}'", mUsername, mDomain);
            mToken = IntPtr.Zero;
            bool logonSuccessfull = LogonUser(mUsername, mDomain, mPassword, mLogonType, LOGON32_PROVIDER_DEFAULT, ref mToken);
            if (logonSuccessfull == false) {
                int error = Marshal.GetLastWin32Error();
                throw new Win32Exception(error);
            }
            WindowsIdentity identity = new WindowsIdentity(mToken);
            WindowsIdentity.RunImpersonated(new Microsoft.Win32.SafeHandles.SafeAccessTokenHandle(mToken), impersonationAction);
            LogFactory.WriteVerbose("Impersonation was successfully");
        } catch (Exception exception) {
           LogFactory.WriteWarning(exception);
            throw;
        }
    }

我们使用Sysinternals Process Explorer查看父进程和子进程的句柄。使用.Net 4.8,我们清楚地看到,在命令行中传递的套接字句柄在子进程的句柄列表中可用。然而,在.Net 6中传递的句柄却不可用。与.Net 4.8相比,.Net 6似乎继承的句柄较少。
为什么.Net 6在这个领域的行为不同?我们所做的所有研究/阅读都表明,“句柄继承”在.Net 6中仍应保持不变。
1个回答

1
我们使用GetHandleInformation()函数来查找在子进程中要访问的套接字在.NET 6中未被标记为“可继承”(而在使用.Net 4.8时是这样的)。现在,我们使用SetHandleInformation()函数将标志设置为1,然后就可以传递句柄了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接