TenForward

技術ブログ。はてなダイアリーから移転しました

cgroup v2 の nsdelegate オプション(2)〜 cgroup namespace 作成後の cgroup root を権限委譲の境界として扱う

cgroup v2 の nsdelegate オプション第 2 弾です。

前回紹介したのは、cgroup namespace を作ると cgroup root を超えたプロセスの移動が禁止されるという機能でした。

これはユーザに関わらず関係するお話でしたが、今回は一般ユーザで namespace(つまりコンテナ)を作ったときのお話です。

私の連載の第 40 回 で紹介したとおり、cgroup v1 に比べて cgroup v2 は一般ユーザでプロセスを移動できる条件が厳しくなりました。ただ、これは実際のユースケースに合っている、というのは連載で書いたとおりです。

一般ユーザに cgroup ツリーを権限委譲する際には、権限委譲する root cgroup に当たる cgroup には、

という権限を与えました。

cgroup 内でコントローラを使えるようにしていても、権限委譲の root cgroup 内のコントローラ関連のファイルには権限は与えません。コンテナに与えるリソースを定義するのはあくまでホストの管理者であって、コンテナの管理者が自身に与えられたリソースを変更できるとマズいから、というのは納得の行くところだと思います。

これを実現するために、前述のようにホスト側の管理者がパーミッションの調整を行っていたわけですが、nsdelegate オプションをつけると、これが自動的に行われます。

nsdelegate の有無で処理がどう変わるか見てみましょう。処理は

  1. cgroup v2 をマウントする(オプション有無)
  2. cgroup.subtree_control にコントローラを登録
  3. cgroup 作成
  4. cgroup ディレクトリとそれ以下のファイルに所有権を与える
  5. cgroup にシェルの PID 登録
  6. cgroup namespace 作成
  7. 作成した cgroup のコントローラを制御するファイル(ここでは pids.max)に制限値を書き込む

という処理をやってみました。

nsdelegate を付けない場合

では、まず普通に cgroup v2 をマウントして処理をすすめましょう。

# mount -t cgroup2 cgroup2 /sys/fs/cgroup/ (1)
# echo "+io +pids +memory" > /sys/fs/cgroup/cgroup.subtree_control (2)
# mkdir /sys/fs/cgroup/test01 (3)
# chown karma /sys/fs/cgroup/test01   (4)
# chown karma /sys/fs/cgroup/test01/* (4)
$ echo $$ | sudo tee /sys/fs/cgroup/test01/cgroup.procs (5)
4013
$ unshare --user --cgroup --map-root-user (6)
root@plamo70b2:~# ls -l /sys/fs/cgroup/test01 (権限を確認)
  : (snip)
-rw-r--r-- 1 root nogroup 0  9701:03 pids.max

このように pids.max には書き込み権がありますね。

一応 cgroup root にいるか確認します。

# cat /proc/$$/cgroup 
0::/

ここで pids.max に制限値として 50 を書き込みます。

# echo 50 > /sys/fs/cgroup/test01/pids.max (7)
# cat /sys/fs/cgroup/test01/pids.max 
50

登録できました。普通の cgroup v2 のコントローラ操作ですね。

nsdelegate を付けた場合

nsdelegate をオプションで与える以外は同じ操作をしてみます。

# mount -t cgroup2 -o nsdelegate cgroup2 /sys/fs/cgroup/ (1)
# echo "+io +pids +memory" > /sys/fs/cgroup/cgroup.subtree_control  (2)
# mkdir /sys/fs/cgroup/test01 (3)
# chown karma /sys/fs/cgroup/test01   (4)
# chown karma /sys/fs/cgroup/test01/* (4)
$ echo $$ | sudo tee /sys/fs/cgroup/test01/cgroup.procs (5)
4013
$ unshare --user --cgroup --map-root-user (6)
# ls -l /sys/fs/cgroup/test01/
  : (snip)
-rw-r--r-- 1 root nogroup 0  9701:25 pids.max

先ほどと同様に書き込み権はあります。

cgroup root にいることも確認しておきます。

# cat /proc/$$/cgroup 
0::/

先ほどと同様に制限値を書き込みます。

# echo 50 > /sys/fs/cgroup/test01/pids.max (7)
-bash: echo: 書き込みエラー: 許可されていない操作です

今回は先ほどと違ってエラーになりました。

このように権限委譲した場合、その root cgroup には限定的な権限のみを与えるのが nsdelegate のもうひとつの機能です。

つまり cgroup namespace (つまりコンテナ)を権限委譲の境界とし、その root cgroup (コンテナの root cgroup)には限定的な権限を与え、それ以下の cgroup のみ権限委譲対象のユーザ管理とするわけです。