web-dev-qa-db-ja.com

`nsenter:`を使用して子プロセスを投獄する信頼できる方法

Linuxの名前空間は、とりわけ、子プロセスをゾンビ化したり、initにダンプしたりすることなく、制限して子プロセスを安全に処理するために活用できることを知っています。しかし、私は実装の詳細について曖昧です。 mountnsenterなどのutil-linuxが提供するツールを使用して、監視、監視し、起動したすべてのプロセスが別のプロセスの直接の名前空間の子孫であることを確認するにはどうすればよいですか?

15
mikeserv

PID名前空間を作成する

ここで使用する正しいコマンドはunshareです。これを行うために必要なオプションはutil-linux 2.23からのみ利用できることに注意してください。アイデアは、実行中のプログラムに新しい PID名前空間 を作成し、そのすべての子もこの名前空間に作成されるようにすることです。次のようにするだけで、新しいPID名前空間でコマンドを実行できます。

Sudo unshare -fp some_command

シェルを実行するには、コマンドを省略します。これにより、その子と一緒に、親(システム)名前空間内で通常どおりPIDを持つプロセスが作成されます。ただし、新しい名前空間内では、initプロセスのいくつかの特別な特性とともに、PIDが1になります。おそらく、監視の観点から最も関連する特性は、その子孫のいずれかが孤立している場合、実際のinitプロセスではなく、このプロセスに対して親が親になることです。

ほとんどの場合、これを行うだけで十分です。前述のように、名前空間内のプロセスはすべて親名前空間内にPIDを持っているため、通常のコマンドを使用してアクティビティを監視できます。名前空間内のプロセスが孤立した場合でも、トップレベルプログラムのPIDの下にあるプロセスツリーのブランチから外れることがないので、簡単に追跡できます。

マウント名前空間と組み合わせる

しかし、私たちができないことは、それが持っているが考えるPIDに関してプロセスを監視することです。これを行うには、特に新しいネームスペース内でpsコマンドを使用できるようにするには、ネームスペース用に別のprocfsファイルシステムをマウントする必要があります。 psprocfsを受け入れる唯一の場所は/procであるため、これは別の問題を引き起こします。 1つの解決策は、chroot刑務所を作成し、そこに新しいprocfsをマウントすることです。しかし、これは扱いにくいアプローチです。少なくとも、使用する予定のバイナリを、それらが依存するライブラリと一緒に新しいルートにコピー(または少なくともハードリンク)する必要があるからです。

解決策は、新しいmount名前空間も使用することです。この中で、真のルート/procディレクトリを使用する方法で新しいprocfsをマウントし、PID名前空間内で使用でき、他のものに干渉しません。このプロセスを非常に単純にするために、unshareコマンドは--mount-procオプションを提供します。

Sudo unshare -fp --mount-proc some_command

結合された名前空間内でpsを実行すると、PIDネームスペースを持つプロセスのみが表示され、PIDが1である最上位プロセスが表示されます。

nsenterはどうですか?

名前が示すように、nsenterを使用して、unshareですでに作成されている名前空間を入力できます。これは、名前空間内からのみ利用可能な情報を、他の関係のないスクリプトから取得する場合に役立ちます。最も簡単な方法は、名前空間内で実行されているプログラムのPIDにアクセスすることです。明確にするために、これはnsenterが実行されているネームスペース内のターゲットプログラムのPIDである必要があります(ネームスペースはネストできるため、単一のプロセスで多数のPIDを持つことが可能です)。ターゲットPID /マウント名前空間でシェルを実行するには、次のようにします。

Sudo nsenter -t $PID -m -p

この名前空間が上記のように設定されている場合、psはその名前空間内のプロセスのみを一覧表示します。

19
Graeme