前回までに引き続き、
Linuxでは、
非特権ユーザに対する権限委譲
デフォルトではcgroupを操作する権限は特権ユーザにしかありません。一般ユーザ権限で起動する非特権コンテナを起動する場合などでは、
たとえば、
- cgroup B以下にcgroupを作れる権限
- cgroup B以下でプロセスを自由に登録できる権限
を与えれば良いでしょう
cgroup B上のコントローラを制御するファイルについては、
もちろん、
cgroup v1の場合
cgroup v1の場合、
| 権限 | 実際の書き込み権 | |
|---|---|---|
| 1 | cgroup B以下にcgroupを作れる権限 | ディレクトリBへの書き込み権 |
| 2 | cgroup B以下でプロセスを自由に登録できる権限 | 登録先cgroup内のcgroup., tasksファイルへの書き込み権 |
実際に試してみましょう。図1に対応させるためにcgroup_というcgroupを作成し、ubuntuユーザにします。
$ whoami ubuntu $ sudo mkdir /sys/fs/cgroup/cpu/cgroup_B (cgroup_B を作成) $ sudo chown ubuntu /sys/fs/cgroup/cpu/cgroup_B/ (cgroup_Bの所有権をubuntuに) $ ls -ld /sys/fs/cgroup/cpu/cgroup_B/ (ubuntuユーザ所有になっている) drwxr-xr-x 2 ubuntu root 0 Feb 27 20:04 /sys/fs/cgroup/cpu/cgroup_B/
これで子cgroupを作る準備はできましたので、cgroup_とcgroup_を作ってみましょう。
$ mkdir /sys/fs/cgroup/cpu/cgroup_B/cgroup_C $ mkdir /sys/fs/cgroup/cpu/cgroup_B/cgroup_D $ $ ls -ld /sys/fs/cgroup/cpu/cgroup_B/cgroup_* drwxrwxr-x 2 ubuntu ubuntu 0 Feb 27 20:07 /sys/fs/cgroup/cpu/cgroup_B/cgroup_C drwxrwxr-x 2 ubuntu ubuntu 0 Feb 27 20:07 /sys/fs/cgroup/cpu/cgroup_B/cgroup_D
通常のディレクトリを作成する際と同じで、cgroup_ディレクトリはubuntuユーザ所有ですので、
$ ls -l /sys/fs/cgroup/cpu/cgroup_B/cgroup_C total 0 -rw-r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cgroup.clone_children -rw-r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cgroup.procs -r--r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cpuacct.stat -rw-r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cpuacct.usage -r--r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cpuacct.usage_percpu -rw-r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cpu.cfs_period_us -rw-r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cpu.cfs_quota_us -rw-r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cpu.shares -r--r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 cpu.stat -rw-r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 notify_on_release -rw-r--r-- 1 ubuntu ubuntu 0 Feb 27 20:07 tasks
上の実行例のようにcgroup_、cgroup_以下にファイルは、ubuntuユーザ所有ですので自由にcgroup操作ができます。
次にプロセスの登録について見てみましょう。cgroup_のtasks、cgroup.ファイルの所有権をubuntuに変更し、
$ sudo chown ubuntu /sys/fs/cgroup/cpu/cgroup_B/tasks (cgroup_Bのtasksファイルの所有権をubuntuに) $ sudo chown ubuntu /sys/fs/cgroup/cpu/cgroup_B/cgroup.procs (cgroup_Bのcgroup.procsファイルの所有権をubuntuに) $ echo $$ 1690 $ echo $$ > /sys/fs/cgroup/cpu/cgroup_B/tasks (プロセスをcgroup_Bに登録) $ cat /sys/fs/cgroup/cpu/cgroup_B/tasks (登録できている) 1690 2285
cgroup_にプロセスが登録できました。cgroup_やcgroup_以下のファイルの所有者はubuntuですから、
$ echo $$ > /sys/fs/cgroup/cpu/cgroup_B/cgroup_C/tasks (上でcgroup_Bに登録したプロセスをcgroup_Cに移動) $ cat /sys/fs/cgroup/cpu/cgroup_B/tasks (cgroup_Bにはプロセスはない) $ cat /sys/fs/cgroup/cpu/cgroup_B/cgroup_C/tasks (cgroup_Cに移動した) 1690 2316 $ echo $$ > /sys/fs/cgroup/cpu/cgroup_B/cgroup_D/tasks $ cat /sys/fs/cgroup/cpu/cgroup_B/cgroup_D/tasks (cgroup_Dに移動した) 1690 2328 $ cat /sys/fs/cgroup/cpu/cgroup_B/tasks (再度cgroup_Bに移動した) 1690 2343
cgroup v1でプロセスをcgroup間で移動させる場合は、
- 移動先の
tasks、cgroup.ファイルへの書き込み権があるproc - 移動
(書き込み) しようとするプロセスの実効UIDが、 ターゲットとなるプロセスの実UIDもしくは保存set-user-idと一致する
上のような条件ですので、
試してみましょう。
$ sudo mkdir /sys/fs/cgroup/cpu/cgroup_{A,B} (cgroup_A, B作成)
$ sudo chown ubuntu /sys/fs/cgroup/cpu/cgroup_{A,B} (A, Bの所有権の変更)
$ mkdir /sys/fs/cgroup/cpu/cgroup_A/cgroup_C (cgroup_C作成)
$ mkdir /sys/fs/cgroup/cpu/cgroup_B/cgroup_D (cgroup_D作成)
$ echo $$ > /sys/fs/cgroup/cpu/cgroup_A/cgroup_C/tasks (Cにプロセスを登録)
$ cat /sys/fs/cgroup/cpu/cgroup_A/cgroup_C/tasks | grep $$
1622 (登録されている)
$ echo $$ > /sys/fs/cgroup/cpu/cgroup_B/cgroup_D/tasks (Dにプロセスを移動)
$ cat /sys/fs/cgroup/cpu/cgroup_B/cgroup_D/tasks | grep $$
1622 (移動している)
図3の通りのcgroupを作成して、cgroup_に登録したプロセスをcgroup_に移動できました。
cgroup v2の場合
cgroup v2の場合、
| 権限 | 実際の書き込み権 | |
|---|---|---|
| 1 | cgroup B以下にcgroupを作れる権限 | ディレクトリBへの書き込み権 |
| 2 | cgroup B以下でプロセスを自由に登録できる権限 | 登録先cgroup内のcgroup.ファイルへの書き込み権 |
プロセスがもともと所属しているcgroupと登録先cgroupの共通の祖先となるcgroup内のcgroup.ファイルへの書き込み権 |
実効UIDの制限がなくなった理由は、
文字で書くと条件が少しわかりづらいですね。実際に、
図4のような構成のツリーがあるとします。まずはcgroup_を作成し、cgroup.ファイルの所有権を変更します。
$ sudo chown ubuntu /sys/fs/cgroup/cgroup_B (cgroup Bをubuntuユーザ所有に) $ sudo chown ubuntu /sys/fs/cgroup/cgroup_B/cgroup.procs (cgroup Bのcgroup.procsファイルをubuntuユーザ権限に) $ ls -al /sys/fs/cgroup/cgroup_B total 0 drwxr-xr-x 4 ubuntu root 0 Mar 7 20:27 ./ dr-xr-xr-x 4 root root 0 Mar 7 20:14 ../ -r--r--r-- 1 root root 0 Mar 7 20:38 cgroup.controllers -r--r--r-- 1 root root 0 Mar 7 20:38 cgroup.events -rw-r--r-- 1 ubuntu root 0 Mar 7 20:25 cgroup.procs -rw-r--r-- 1 root root 0 Mar 7 20:38 cgroup.subtree_control (cgroup Bディレクトリとcgroup.procsファイルのみubuntuの所有となっている)
root cgroupからcgroup Bへのプロセスの移動
図4のubuntuユーザでcgroup_のcgroup.に登録を試みます。cgroup v1の場合はcgroup B内のcgroup.に書き込み権があれば、
$ whoami
ubuntu
$ echo $$ > /sys/fs/cgroup/cgroup_B/cgroup.procs
-bash: echo: write error: Permission denied
(ユーザ自身の権限で実行されているプロセスを登録しようとしたが失敗した)
しかしcgroup v2では、cgroup.ファイルはubuntuユーザの所有であり、
これは表2で示した条件の2番目に引っかかったためです。この場合、ubuntuユーザはroot cgroupのcgroup.ファイルに対する権限を持っていませんので、
これは、
この考え方に従い、cgroup_に登録しましょう。
$ echo $$ | sudo tee /sys/fs/cgroup/cgroup_B/cgroup.procs 3126 (root権限でubuntuユーザ権限で動いているプロセスをcgroup_Bに登録) $ grep $$ /sys/fs/cgroup/cgroup_B/cgroup.procs 3126 (登録できた)
この操作はroot権限で行っていますので登録できます。
権限があるcgroup間でのプロセスの移動(共通のcgroup配下のcgroup間)
それではcgroup_配下にcgroup_とcgroup_を作成し、
$ whoami
ubuntu
$ mkdir /sys/fs/cgroup/cgroup_B/cgroup_{D,E}
(ubuntuユーザ権限でcgroup D,Eを作成)
$ ls -d /sys/fs/cgroup/cgroup_B/cgroup_*
/sys/fs/cgroup/cgroup_B/cgroup_D/ /sys/fs/cgroup/cgroup_B/cgroup_E/
(問題なく作成できた)
cgroup_はubuntuユーザ所有ですので、cgroup_とcgroup_は問題なく作成できました。
それでは、cgroup_へ移動させたプロセスをcgroup_に移動させましょう。図4の
$ whoami
ubuntu
$ echo $$ > /sys/fs/cgroup/cgroup_B/cgroup_D/cgroup.procs
(自身の所有であるcgroup_Bのcgroup.procsに登録されたプロセスを自身の所有であるcgroup Dに移動)
$ grep $$ /sys/fs/cgroup/cgroup_B/cgroup_D/cgroup.procs
3126
今度はエラーなく作成できました。これはcgroup_がcgroup_とcgroup_の共通の祖先」
cgroup_のD cgroup.はprocs ubuntuユーザが所有cgroup_とD cgroup_の共通の祖先であるB cgroup_のB cgroup.ファイルはprocs ubuntuユーザが所有
となり、
次に、cgroup_からcgroup_へのプロセスの移動を見てみましょう。図4の
cgroup_のE cgroup.はprocs ubuntuユーザが所有cgroup_とD cgroup_の共通の祖先であるE cgroup_のB cgroup.ファイルはprocs ubuntuユーザが所有
ですので、
$ whoami ubuntu $ ls -l /sys/fs/cgroup/cgroup_B/cgroup.procs -rw-r--r-- 1 ubuntu root 0 Mar 7 20:25 /sys/fs/cgroup/cgroup_B/cgroup.procs $ ls -l /sys/fs/cgroup/cgroup_B/cgroup_E/cgroup.procs -rw-r--r-- 1 ubuntu ubuntu 0 Mar 7 20:57 /sys/fs/cgroup/cgroup_B/cgroup_E/cgroup.procs (共通の祖先と移動先のcgroup.procsファイルに権限があることの確認) $ grep $$ /sys/fs/cgroup/cgroup_B/cgroup_D/cgroup.procs 3126 (cgroup Dにプロセスが登録されていることの確認) $ echo $$ > /sys/fs/cgroup/cgroup_B/cgroup_E/cgroup.procs (プロセスをcgroup Eに移動) $ grep $$ /sys/fs/cgroup/cgroup_B/cgroup_E/cgroup.procs 3126 (移動できた)
移動できました。
権限があるcgroup間でのプロセスの移動(共通のcgroup配下でないcgroup間)
別の例を紹介しましょう。
図5のようにroot cgroup直下にcgroup_とcgroup_を作成し、cgroup_、cgroup_を作成します。
$ ls -ld /sys/fs/cgroup/cgroup_? (cgroup_A,Bはubuntuユーザ所有) drwxr-xr-x 3 ubuntu root 0 3月 14日 19:38 /sys/fs/cgroup/cgroup_A/ drwxr-xr-x 3 ubuntu root 0 3月 14日 19:38 /sys/fs/cgroup/cgroup_B/ $ ls -l /sys/fs/cgroup/cgroup_?/cgroup.procs (ubuntuユーザはcgroup_A,Bのcgroup.procsに書き込み権あり) -rw-r--r-- 1 ubuntu root 0 3月 14日 19:33 /sys/fs/cgroup/cgroup_A/cgroup.procs -rw-r--r-- 1 ubuntu root 0 3月 14日 19:33 /sys/fs/cgroup/cgroup_B/cgroup.procs $ ls -ld /sys/fs/cgroup/cgroup_?/cgroup_? (cgroup_C,Dはubuntuユーザ所有) drwxr-xr-x 2 ubuntu users 0 3月 14日 19:38 /sys/fs/cgroup/cgroup_A/cgroup_C/ drwxr-xr-x 2 ubuntu users 0 3月 14日 19:38 /sys/fs/cgroup/cgroup_B/cgroup_D/ $ ls -l /sys/fs/cgroup/cgroup_?/cgroup_?/cgroup.procs (ubuntuユーザはcgroup_C,Dのcgroup.procsに書き込み権あり) -rw-r--r-- 1 ubuntu users 0 3月 14日 19:38 /sys/fs/cgroup/cgroup_A/cgroup_C/cgroup.procs -rw-r--r-- 1 ubuntu users 0 3月 14日 19:38 /sys/fs/cgroup/cgroup_B/cgroup_D/cgroup.procs
以上のようにcgroup_ubuntuユーザ所有のグループで、cgroup.ファイルの所有権もubuntuユーザになっており、
ここでcgroup_からcgroup_へプロセスが移動できるでしょうか? 試してみましょう。
まずはcgroup_にプロセスを登録します。root cgroupからの移動になりますのでroot権限で移動させます。
$ echo $$ | sudo tee /sys/fs/cgroup/cgroup_A/cgroup_C/cgroup.procs 3058 (root権限でcgroup_Cにプロセスを登録) $ grep $$ /sys/fs/cgroup/cgroup_A/cgroup_C/cgroup.procs 3058 (登録されている)
これでcgroup_にプロセスが登録された状態になりました。つぎに、cgroup_からcgroup_に移動させてみましょう。
$ echo $$ > /sys/fs/cgroup/cgroup_B/cgroup_D/cgroup.procs -bash: echo: write error: Permission denied
cgroup_のcgroup.はubuntuユーザ所有であり、cgroup_とcgroup_の共通の祖先をたどるとroot cgroupになります。root cgroupのcgroup.ファイルに対してubuntuユーザは書き込み権限を持っていませんので、
このような移動ができない理由を考えてみましょう。
図5の構造を見ると、cgroup_以下とcgroup_以下はそれぞれ独立したコンテナとみなせます。いくら同じユーザ権限で動いているコンテナとはいえ、
このようにcgroup v2では、
まとめ
今回を含めて4回でcgroup v2コアの機能を紹介してきました。
今回は特権を持たないユーザに対して、
cgroup v2には、
次回以降はしばらく私ではなく、
udzura さんは、
お楽しみに。
