/proc/を読み取らないようにするメカニズムは何ですか?/ environは、ホストと共有PID名前空間を持つコンテナにありますか?

/proc/を読み取らないようにするメカニズムは何ですか?/ environは、ホストと共有PID名前空間を持つコンテナにありますか?

コンテナとPID名前空間を共有する方法を研究しながら、私が理解していない興味深い事実を見つけました。コンテナがホストとPID名前空間を共有すると、一部のプロセスの環境変数は保護されますが、他のプロセスは保護されません。

mysqlを例に挙げましょう。環境変数セットを使用してコンテナを起動します。

ubuntu@sandbox:~$ docker container run -it -d --env MYSQL_ROOT_PASSWORD=SuperSecret mysql
551b309513926caa9d5eab5748dbee2f562311241f72c4ed5d193c81148729a6

ホストPID名前空間を共有する別のコンテナを起動し、ファイルにアクセスしましょうenviron

ubuntu@sandbox:~$ docker container run -it --rm --pid host ubuntu /bin/bash

root@1c670d9d7138:/# ps aux | grep mysql
999        18212  5.0  9.6 2006556 386428 pts/0  Ssl+ 17:55   0:00 mysqld
root       18573  0.0  0.0   2884  1288 pts/0    R+   17:55   0:00 grep --color=auto mysql

root@1c670d9d7138:/# cat /proc/18212/environ
cat: /proc/18212/environ: Permission denied

環境変数の読み取りへのアクセスをブロックすることがあります。CAP_SYS_PTRACEコンテナから読む必要があることがわかりました。

ubuntu@sandbox:~$ docker container run -it --rm --pid host --cap-add SYS_PTRACE  ubuntu /bin/bash

root@079d4c1d66d8:/# cat /proc/18212/environ
MYSQL_PASSWORD=HOSTNAME=551b30951392MYSQL_DATABASE=MYSQL_ROOT_PASSWORD=SuperSecretPWD=/HOME=/var/lib/mysqlMYSQL_MAJOR=8.0GOSU_VERSION=1.14MYSQL_USER=MYSQL_VERSION=8.0.30-1.el8TERM=xtermSHLVL=0MYSQL_ROOT_HOST=%PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binMYSQL_SHELL_VERSION=8.0.30-1.el8

しかし、すべてのプロセスがこのように保護されるわけではありません。

たとえば、別のコンテナubuntuコンテナを起動し、env変数を設定してコマンドを実行しますtail

ubuntu@sandbox:~$ docker container run --rm --env SUPERSECRET=helloworld -d ubuntu tail -f /dev/null
42023615a4415cd4064392e890622530adee1f42a8a2c9027f4921a522d5e1f2

共有pid名前空間を使用してコンテナを実行すると、環境変数にアクセスできるようになりました。

ubuntu@sandbox:~$ docker container run -it --rm --pid host ubuntu /bin/bash

root@3a774156a364:/# ps aux | grep tail
root       19056  0.0  0.0   2236   804 ?        Ss   17:57   0:00 tail -f /dev/null
root       19176  0.0  0.0   2884  1284 pts/0    S+   17:58   0:00 grep --color=auto tail

root@3a774156a364:/# cat /proc/19056/environ
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=42023615a441SUPERSECRET=helloworldHOME=/root

プロセスの代わりにmysqld環境変数を読み取らないようにするメカニズムは何ですかtail -f

ベストアンサー1

tail -fプロセスの代わりにmysqld環境変数を読み取らないようにするメカニズムは何ですか?

実際、最初のケースでは、別のユーザーIDで実行されています。 2つの例を開始すると、次のようになります。

docker run --name mysql -it -d --env MYSQL_ROOT_PASSWORD=SuperSecret mysql:latest
docker run --name tail -it -d --env MYSQL_ROOT_PASSWORD=SuperSecret ubuntu:latest tail -f /dev/null

次に、生成プロセスを見てください。

$ ps -fe n |grep -E 'tail|mysqld' | grep -v grep
     999  422026  422005  2 22:50 pts/0    Ssl+   0:00 mysqld
       0  422170  422144  0 22:50 pts/0    Ss+    0:00 tail -f /dev/null

mysqldUID 999で実行され、コマンドはtailUID 0で実行されていることがわかります。ホストpidネームスペースで新しいコンテナを起動すると、environ同じUIDとGIDが所有するプロセスのみを読み取ることができます。コンテナはデフォルトでUID 0で実行されるため、これは機能します。

$ docker run  --rm --pid host ubuntu:latest cat /proc/422170/environ | tr '\0' '\n'
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=e89c069d4674
TERM=xterm
MYSQL_ROOT_PASSWORD=SuperSecret
HOME=/root

失敗します。

$ docker run  --rm --pid host ubuntu:latest cat /proc/422026/environ | tr '\0' '\n'
cat: /proc/422026/environ: Permission denied

能力がある場合は、environ他のUIDまたはGIDで実行されているプロセスでのみファイルを読み取ることができますCAP_SYS_PTRACE。このチェックのロジックは次の場所にあります。ptrace_may_access機能カーネルから:

    if (uid_eq(caller_uid, tcred->euid) &&
        uid_eq(caller_uid, tcred->suid) &&
        uid_eq(caller_uid, tcred->uid)  &&
        gid_eq(caller_gid, tcred->egid) &&
        gid_eq(caller_gid, tcred->sgid) &&
        gid_eq(caller_gid, tcred->gid))
        goto ok;
    if (ptrace_has_cap(tcred->user_ns, mode))
        goto ok;

mysqlプロセスと同じUIDとGIDを使用してコンテナを実行すると、この失敗した例が機能するようにすることができます。

$ docker run -u 999:999 --rm --pid host ubuntu:latest cat /proc/422026/environ | tr '\0' '\n'
MYSQL_PASSWORD=
HOSTNAME=bde980104dcd
MYSQL_DATABASE=
MYSQL_ROOT_PASSWORD=SuperSecret
PWD=/
HOME=/var/lib/mysql
MYSQL_MAJOR=8.0
GOSU_VERSION=1.14
MYSQL_USER=
MYSQL_VERSION=8.0.31-1.el8
TERM=xterm
SHLVL=0
MYSQL_ROOT_HOST=%
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYSQL_SHELL_VERSION=8.0.31-1.el8

おすすめ記事