差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン | ||
linux:kernel:namespace:more_on_user_namespaces [2013/11/13 11:16] – [ユーザ名前空間とケーパビリティ] tenforward | linux:kernel:namespace:more_on_user_namespaces [2013/11/20 05:46] (現在) – [ケーパビリティふたたび] tenforward | ||
---|---|---|---|
行 54: | 行 54: | ||
一方で,userns_setns_test が作った子プロセスは異なる名前空間 (4026532319) にいる.実際は ksh プロセスが実行されている名前空間の兄弟名前空間にいる.このように,先に説明したルールの 2 番目は適用されない.なぜならその名前空間は 4026532318 の祖先ではないからである.なので,子プロセスは CAP_SYS_ADMIN ケーパビリティをその名前空間内では持たないため,setns() の呼び出しは失敗する. | 一方で,userns_setns_test が作った子プロセスは異なる名前空間 (4026532319) にいる.実際は ksh プロセスが実行されている名前空間の兄弟名前空間にいる.このように,先に説明したルールの 2 番目は適用されない.なぜならその名前空間は 4026532318 の祖先ではないからである.なので,子プロセスは CAP_SYS_ADMIN ケーパビリティをその名前空間内では持たないため,setns() の呼び出しは失敗する. | ||
- | ==== ユーザ名前空間と他の名前空間の同時使用 ==== | + | ===== ユーザ名前空間と他の名前空間の同時使用 |
+ | ユーザ名前空間以外の名前空間を作成するには CAP_SYS_ADMIN ケーパビリティが必要である.一方で,ユーザ名前空間を作成するには (Linux 3.8 以降は) ケーパビリティは不要である.名前空間の最初のプロセスは (その新しいユーザ名前空間内では) フルセットのケーパビリティを得る.これは,プロセスは 2 度目の clone() の呼び出しでどんなタイプの名前空間も作ることが可能であるということを意味する. | ||
+ | |||
+ | しかし,この 2 ステップのプロセスは必要ではない.新しいユーザ名前空間を作るための CLONE_NEWUSER を指定する同じ clone() (or unshare()) に追加の CLONE_NEW* を含める事も可能である.この場合,カーネルは CLONE_NEWUSER フラグを先に実行し,新しいユーザ名前空間を作成して,その中に作られる子供が全てのケーパビリティを持つことを保証する.それから,カーネルは残りの CLONE_NEW* を実行し,指定の新しい名前空間を作成し,その全ての名前空間のメンバーである子プロセスを作成する. | ||
+ | |||
+ | それゆえ,例えば,非特権プロセスが以下のような形の呼び出しで,新しいユーザ名前空間と新しい UTS 名前空間の両方のメンバーである子プロセスを作成することが可能である. | ||
+ | |||
+ | < | ||
+ | |||
+ | userns_child_exec プログラムを使うと,上記と同等の clone() 呼び出しを実行し,子プロセス内でシェルを実行することが可能である.以下のコマンドは新しい UTS 名前空間と新しいユーザ名前空間の作成を指定している.このユーザ名前空間内では,ユーザ ID とグループ ID の両方ともの 1000 が 0 にマッピングされる. | ||
+ | |||
+ | < | ||
+ | $ uname -n # Display hostname for later reference | ||
+ | antero | ||
+ | $ ./ | ||
+ | </ | ||
+ | |||
+ | 予想通り,シェルプロセスはフルセットの permitted と effective ケーパビリティを持っている. | ||
+ | |||
+ | < | ||
+ | $ id -u # Show effective user and group ID of shell | ||
+ | 0 | ||
+ | $ id -g | ||
+ | 0 | ||
+ | $ cat / | ||
+ | CapInh: 0000000000000000 | ||
+ | CapPrm: 0000001fffffffff | ||
+ | CapEff: 0000001fffffffff | ||
+ | </ | ||
+ | |||
+ | 上記の出力で,Hex 値 1fffffffff は,現時点での Linux の全ての 37 のケーパビリティセットが有効であることを表している. | ||
+ | |||
+ | ここで,UTS 名前空間で隔離されているグローバルリソースの一つであるホスト名を hostname コマンドを使って変更することができる.この操作には CAP_SYS_ADMIN が必要である.最初に,ホスト名を新しい値に変更する.それから uname コマンドでその辺りを表示する. | ||
+ | |||
+ | < | ||
+ | $ hostname bizarro | ||
+ | $ uname -n # Verify the change | ||
+ | bizarro | ||
+ | </ | ||
+ | |||
+ | 初期の UTS 名前空間内で実行されている,他のターミナルウィンドウに移動し,その UTS 名前空間でホスト名をチェックする. | ||
+ | |||
+ | < | ||
+ | $ uname -n # Hostname in original UTS namespace is unchanged | ||
+ | antero | ||
+ | </ | ||
+ | |||
+ | 以上の出力から,親の UTS 名前空間では見えない子供の UTS 名前空間内でホスト名を変更することをみることができた. | ||
+ | |||
+ | ===== ケーパビリティふたたび ===== | ||
+ | |||
+ | カーネルはユーザ名前空間内の初期プロセスに全てのケーパビリティを与えるが,これは,その後でプロセスがシステムワイドでスーパーユーザの特権を持つことは意味しない.(しかし,従来は root だけがアクセスできたカーネルコード内の弱点にアクセスできるようになったことは意味するかもしれない.[[http:// | ||
+ | |||
+ | 例えば,clone(NEW_USER) を使ってユーザ名前空間を作成すると仮定しよう.生成される子プロセスは新しいユーザ名前空間内ではフルセットのケーパビリティを持つ.これは,例えば,他のタイプの名前空間を作成することが可能になることと,自身のユーザ,グループ ID と名前空間内でマッピングされる他の ID を変えることが可能になることを意味する.(このシリーズの前の記事にあるように,我々は親の名前空間内の特権プロセスのみが,名前空間を作成するプロセスの実効ユーザ,グループ ID 以外の ID へのマッピングを作成することができることを見ているので,ここにはセキュリティ的な抜け道は存在しない.) | ||
+ | |||
+ | 一方で,子プロセスはファイルシステムをマウントできない.子プロセスはまだ初期のマウント名前空間に留まっており,その名前空間内でファイルシステムをマウントするためには,マウント名前空間と関連付いたユーザ名前空間内でケーパビリティを持つ必要がある (すなわち,初期のユーザ名前空間内でのケーパビリティが必要ということである).このケーパビリティは子プロセスは持っていない.同様のことが IPC, ネットワーク,PID,UTS 名前空間で隔離されたグローバルリソースに対しても言える. | ||
+ | |||
+ | その上,子プロセスは名前空間が (現時点では) 持っていないケーパビリティが必要な特権操作を行うことはできない.それゆえ,例えば,子プロセスは自身のリソースのハードリミットを上げたり,システム時間を設定したり,プロセスの優先度を設定したり,カーネルモジュールをロードしたり,< | ||
+ | |||
+ | 名前空間に対するケーパビリティの効果を隔離することによって,ユーザ名前空間は以上のように,特権のないユーザが,従来は root に限定されていた機能へのアクセスを,安全性を保証しながら実行することを可能にした.これにより,新しい種類のユーザ空間アプリケーションに対する面白そうな可能性が創りだされた.例えば,今後は非特権ユーザが root 特権なしで Linux コンテナを実行できるようになったり,[[http:// | ||
+ | |||
+ | 著者は,このシリーズを書く過程の名前空間に関する実験で生じた多数の質問への回答に対して,Eric Biederman に感謝を述べたい. | ||