web-dev-qa-db-ja.com

Linuxネームスペースでchrootを実行する方法は?

Linux名前空間について読んだ後、他の多くの機能の中で、chrootに代わるものであるという印象を受けました。たとえば、 この記事 の場合:

[名前空間の]その他の用途には、[...] chroot()スタイルの単一ディレクトリ階層の一部へのプロセスの分離が含まれます。

ただし、たとえば次のコマンドを使用してマウント名前空間を複製すると、元のルートツリー全体が表示されます。

unshare --mount -- /bin/bash

新しい名前空間で、元の名前空間と共有されていない追加のマウントを実行できるようになったことを理解しています。これにより分離が提供されますが、それでも同じルートです。 /etcは、両方の名前空間で同じです。ルートを変更するためにchrootが必要ですか、それとも代替手段はありますか?

この質問 で回答が得られると期待していましたが、回答ではchrootのみを使用しています。

編集#1

pivot_rootについてのコメントが削除されました。これは実際には linux/fs/namespace.c の一部であるため、実際には名前空間の実装の一部です。これは、ルートディレクトリをunsharemountだけで変更することは不可能であることを示唆していますが、名前空間はchrootの独自のバージョンを提供します。それでも、ソースコードを読んだ後でも(たとえば、セキュリティやより良い分離の意味で)、このアプローチの基本的な考え方がchrootと根本的に異なることはありません。

編集#2

これは この質問 の複製ではありません。回答からすべてのコマンドを実行した後、別の/tmp/tmp.vyM9IwnKuY(または類似の)がありますが、ルートディレクトリは同じです!

14
koalo

chrootを設定する前にマウント名前空間を入力すると、追加のマウントでホスト名前空間が煩雑になるのを回避できます。 _/proc_の場合。マウントネームスペース内でchrootを使用すると、素晴らしくシンプルなハックができます。

_pivot_root_を理解することには利点があると思いますが、学習曲線が少しあります。ドキュメントはすべてを完全に説明していません... _man 8 pivot_root_の使用例があります(シェルコマンドの場合)。 _man 2 pivot_root_(システムコールの場合)が同じである場合、よりわかりやすくなる可能性があり、サンプルCプログラムが含まれています。

Pivot_rootの使い方

マウント名前空間を入力した直後に、_mount --make-rslave /_または同等のものも必要です。それ以外の場合、すべてのマウントの変更は、_pivot_root_を含め、元の名前空間のマウントに伝達されます。あなたはそれを望まない:)。

_unshare --mount_コマンドを使用した場合は、デフォルトで_mount --make-rprivate_を適用することが記載されていることに注意してください。 AFAICSこれは不適切なデフォルトであり、これを本番コードで使用したくありません。例えば。この時点で、ホストネームスペースにマウントされたDVDまたはUSBでejectが機能しなくなります。 DVDまたはUSBはプライベートマウントツリー内にマウントされたままで、カーネルはDVDを取り出せません。

それが終わったら、マウントすることができます。使用する_/proc_ディレクトリchrootの場合と同じです。

chrootを使用する場合とは異なり、_pivot_root_では、新しいルートファイルシステムがマウントポイントである必要があります。まだバインドされていない場合は、バインドマウントを適用するだけで満足できます:_mount --rbind new_root new_root_。

_pivot_root_を使用し、次に_-l_/_MNT_DETACH_オプションを使用して古いルートファイルシステムをumountします。 ( _umount -R_は必要ありません。時間がかかることがあります。 )。

技術的には、_pivot_root_を使用するには、通常、chrootも使用する必要があります。 「どちらか一方」ではありません。

_man 2 pivot_root_によると、それはマウント名前空間のルートを交換することとしてのみ定義されています。プロセスルートが指している物理ディレクトリを変更することは定義されていません。または、現在の作業ディレクトリ(_/proc/self/cwd_)。たまたま実行しますが、これはカーネルスレッドを処理するためのハックです。マンページには、将来変更される可能性があると記載されています。

通常、このシーケンスが必要です。

_chdir(new_root);            // cd new_root
pivot_root(".", put_old);   // pivot_root . put_old
chroot(".");                // chroot .
_

このシーケンスでのchrootの位置付けは、もう1つの微妙な詳細です 。 _pivot_root_の目的はマウント名前空間を再配置することですが、カーネルコードは、プロセスごとのルートを調べて移動するルートファイルシステムを見つけているようです。これはchrootが設定するものです。

ピボットルートを使用する理由

原則として、セキュリティと分離のために_pivot_root_を使用することは理にかなっています。 機能ベースのセキュリティ の理論について考えたいと思います。必要な特定のリソースのリストを渡し、プロセスは他のリソースにアクセスできません。この場合は、マウント名前空間に渡されるファイルシステムについて話している。この考えは、Linuxの「名前空間」機能に一般的に当てはまりますが、おそらく私はそれをうまく表現していません。

chrootはプロセスのルートのみを設定しますが、プロセスは引き続き完全なマウント名前空間を参照します。プロセスがchrootを実行する特権を保持している場合、ファイルシステム名前空間をさかのぼってバックアップできます。 _man 2 chroot_で詳しく説明されているように、「スーパーユーザーは...によって「chroot刑務所」から脱出できます。」.

chrootを元に戻す別の考えさせる方法は、_nsenter --mount=/proc/self/ns/mnt_です。これはおそらくこの原則に対するより強力な議論です。 nsenter/setns()は、必ず、マウントネームスペースのルートからプロセスルートを再ロードします ...異なる物理ディレクトリ。カーネルのバグと見なされる場合があります。 (テクニカルノート:複数のファイルシステムがルート上で相互にマウントされている可能性があります。setns()は、最も新しくマウントされたものを使用します)。

これは、マウント名前空間を「PID名前空間」と組み合わせる利点の1つを示しています。 PID名前空間内にいると、制限のないプロセスのマウント名前空間に入ることができなくなります。また、制限のないプロセスのルート(_/proc/$PID/root_)に入るのを防ぎます。そしてもちろん、PID名前空間は、その外にあるプロセスを強制終了することも防ぎます:-)。

13
sourcejedi