10

Windows ハンドルを継承可能にするかどうかを設定して、子プロセスがそれらを受け取るかどうかを制御できます ( bInheritHandlesinCreateProcessが TRUE の場合)。ただし、SetHandleInformation継承不可能な SOCKET をマークするために使用しても、常に機能するとは限りません。特に、特定のレイヤード サービス プロバイダー (LSP) がインストールされている場合、子プロセスはハンドルを継承します。これは特に、リッスン ソケットでバグを引き起こす可能性があります。(しかし、別の問題のため、子供がソケットを使用しようとしても、それはできません! 本当のキャッチ 22!)

再現する手順

  1. たとえば、リッスン ソケットを作成します。を使用して継承不可とマークしSetHandleInformationます。
  2. trueで子を生成しbInheritHandlesます。
  3. 親のソケットを閉じ、ポートへの再バインドを試みます。

(非 IFS) LSP がインストールされている場合。PCTools Internet Security では、子を作成する前に継承を無効にするためにソケットで呼び出されたnetstatにもかかわらず、リッスン ソケットが子で開かれます ( で表示) 。SetHandleInformation

別のシナリオについては、KB2398202の (簡単な) 手順を参照してください。

どのような回避策がありますか?

4

1 に答える 1

10

簡潔な答え

通常、SOCKET ハンドルを継承不可に設定することはできません。つまり、特定の (非 IFS) LSP がインストールされている場合、プロセス内のハンドルを特に継承不可としてマークしても、子プロセスがハンドルをbInheritHandles=TRUE受け取るのを停止することはできません。

説明

LSP は一般に、すべての TCP 接続をフィルタリングするために、ファイアウォールまたは A/V 製品で使用されます。LSP は、WinSock によってプロセスにロードされる DLL であり、すべての TCP 操作を処理します。通常は、何らかのフィルタリングを実行してから、基になる WinSock 実装に直接呼び出しを渡します。LSP は、WinSock 実装を生成した実際の SOCKET ハンドルごとにダミー ハンドルを作成することによって機能します。WSASocket を呼び出すと、ダミー ハンドルが得られます。ダミー ハンドルを使用すると、コールはそれを作成した LSP に送信されます。次に、LSP はダミーを実際のハンドルにマップし直し、操作 (acceptまたは などbind) を基になるハンドルに渡します。

したがって、問題は、SetHandleInformation作成したソケットを呼び出すだけでは十分ではないということです。(LSP によって内部的に使用される) 表示されることのない基になるハンドルは、子プロセスによって引き続き継承されます。

回避策

  1. CreateProcessソケットを使用するアプリケーションからの継承を許可する呼び出しは絶対に行わないでください。これが最も信頼できるソリューションです。代わりに、子との通信を設定するには、適切な権限を持つ名前付きパイプを作成し、コマンドラインでその名前を子に渡し、子に接続し直します。次に、子に継承させたいハンドルを手動で渡します。コマンドラインは他のユーザーが読み取ることができますが、パイプが正しく設定されていれば、子の実際のユーザー トークンのみがパイプに接続できるため、これは安全です。
    子での引数の解析を制御する必要があるため、子の stdio をリダイレクトするなどの単純なことだけを行いたい場合、これは非常に洗練されていません。これを回避するには、コマンドラインから名前付きパイプ名を読み取って接続し、ハンドルを継承可能に設定し、stdio をリダイレクトして残りの引数を再度呼び出すラッパー バイナリを作成します。プロセスにはソケットがないため、ラッパーからハンドルを継承しても安全です。
  2. または、Vista ( KB2398202 )、Windows 7 (SP1) 以降では、WSA_FLAG_NO_HANDLE_INHERITフラグが に追加されましたWSASocket(これは、Microsoft から入手できる問題のドキュメントと同じです。修正プログラムを作成することは、ベース サービス プロバイダー ハンドルの継承を防止するためには、それなしでは不可能であることをほぼ認めています。しかし、それは十分に宣伝されていません!)
  3. 最後に、Vista では、ベース サービス プロバイダが使用するハンドルを照会できるようにする ioctl もあります。これらは継承不可とマークすることができます。これは面倒ですが、XP の問題はまだ修正されていません。
于 2012-08-21T16:07:52.770 に答える