/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로 실행 중입니다. 두 가지 예를 시작하면 다음과 같습니다.

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

관련 정보