可以将Windows句柄设置为可继承或不可继承,以控制子进程是否会接收它们(bInheritHandles
中的CreateProcess
为TRUE时)。但是,使用SetHandleInformation
标记SOCKET不可继承并不总是有效。特别是,当安装某些分层服务提供程序(LSP)时,子进程无论如何都会继承句柄。这特别容易导致监听套接字的错误。 (但是,由于another issue,如果孩子尝试使用套接字,它将无法使用!真正的捕获22!)
SetHandleInformation
将其标记为不可继承。bInheritHandles
为真。安装(非IFS)LSP时,例如。 PCTools Internet Security,监听套接字将在子进程中打开(在netstat
中可见),尽管在创建子进程之前在套接字上调用SetHandleInformation
来禁用继承。
有关替代方案,请参阅KB2398202中的(简要)步骤。
答案 0 :(得分:10)
通常不可能将SOCKET句柄设置为不可继承。也就是说,当安装了某些(非IFS)LSP时,即使您将流程中的句柄标记为具有不可继承性,也无法阻止bInheritHandles=TRUE
的子流程接收它们。
防火墙或A / V产品通常使用LSP来过滤所有TCP连接。 LSP是由WinSock加载到您的进程中的DLL,它通常通过执行一些过滤然后将调用直接传递给底层的WinSock实现来处理所有TCP操作。 LSP通过为生成WinSock实现的每个实际SOCKET句柄创建一个虚拟句柄来工作:您对WSASocket的调用将为您提供虚拟句柄;当你使用虚拟句柄时,调用被发送到创建它的LSP; LSP然后将虚拟映射回实际句柄,并将操作(例如accept
或bind
)传递给底层句柄。
因此,问题是在您创建的套接字上调用SetHandleInformation
是不够的:您从未看到的底层句柄(由LSP内部使用)仍然由子进程继承。
CreateProcess
允许来自使用套接字的应用程序的任何继承。这是最可靠的解决方案。相反,要设置与子进程的通信,请创建具有适当权限的命名管道,将其在命令行上的名称传递给子进程,然后在子进程中重新连接。然后手动传递您希望孩子继承的任何句柄。这是安全的,因为虽然命令行可能是其他用户可读的,但只有正确设置的孩子的实际用户令牌才能连接到管道。WSA_FLAG_NO_HANDLE_INHERIT
标记中添加WSASocket
标记。 (这是我从Microsoft可以找到的问题的文档。尽管如此,创建此修补程序几乎可以肯定,如果没有它可以阻止基本服务提供程序句柄被继承。虽然它没有得到很好的宣传!)