Is it possible to configure TCP SOCKET descriptors not inherited?

Windows handles can be set as inherited or not, to control whether child processes will receive them (when bInheritHandles in CreateProcess is TRUE). However, using SetHandleInformation to indicate an unsecured SOCKET does not always work. In particular, when certain layered service providers (LSPs) are installed, the child process inherits the handle anyway. This, in particular, can cause bugs with listening sockets. (But due to another problem , if a child tried to use a socket, he will not be able to! Real catch-22!)

Steps to play

  • Create, for example, a listening jack. Mark it non inheritable using SetHandleInformation .
  • Save the child, bInheritHandles true.
  • Close the socket in the parent and try to bind it to the port again.

If LSP (not IFS) is installed, for example. PCTools Internet Security, the listening socket will be open in the child (apparently in netstat ), although SetHandleInformation is called on the socket to disable inheritance before creating the child.

For an alternative scenario, see the (brief) steps in KB2398202 .

What are some workarounds?

+7
source share
1 answer

Short answer

In general, it is not possible to establish that a SOCKET is not inherited. That is, when certain (non-IFS) LSPs are set, even if you mark descriptors in your process that are not inherited, it is not possible to stop the child process with bInheritHandles=TRUE from receiving them.

Description

LSPs are typically used by a firewall or A / V products to filter all TCP connections. LSP is a DLL loaded into your WinSock process that processes all TCP operations, usually by doing some filtering and then passing the call directly to the base WinSock implementation. LSP works by creating a dummy descriptor for each real SOCKET descriptor that created the WinSock implementation: your WSASocket call will give you a dummy descriptor; when you use a dummy handle, the call is sent to the LSP that created it; The LSP then maps the dummy back to the actual descriptor and passes the operation (for example, accept or bind ) to the base descriptor.

So the problem is that calling SetHandleInformation on the created sockets is not enough: the base descriptor that you never see (used internally by the LSP) is still inherited by child processes.

Bypass

  • Never call CreateProcess possible inheritance from an application that uses sockets. This is the most reliable solution. Instead, to associate with the child, create a named pipe with the appropriate permissions, pass its name on the command line for the child, and reconnect to it. Then manually transfer all the pens you want the child to inherit. This is safe, because although the command line can be read by other users, only the user's actual token can connect to the channel if it is configured correctly.
    This is extremely inelegant if all you want to do is something as simple as redirecting a child stdio, since you need to control the analysis of the arguments in the child. To get around this, create a wrapper binary that reads the name of the named pipe from the command line and concatenates, sets the inherited descriptor, and re-calls the remaining arguments with the stdio redirection. It is safe to inherit descriptors from the shell, since there are no sockets in this process.
  • Alternatively, in Vista (with KB2398202 ), Windows 7 (with Service Pack 1), and later the WSA_FLAG_NO_HANDLE_INHERIT flag was added to WSASocket . (This is as much documentation about the problem as I can find with Microsoft. Creating the hotfix has largely confirmed that without it it is impossible to prevent the base service handler from being inherited. It was not well advertised!)
  • Finally, Vista also has ioctls, which let you handle the handlers used by the underlying service provider. They can then be marked as non-inherited. This is a pain, although it still does not fix things for XP.
+8
source

All Articles