Akh*_*han 3 linux selinux mount docker bind-mount
我需要连接到 docker 容器内主机的所有磁盘的挂载点。安装信息在/proc/1/mounts文件中可用,但我无法在所有操作系统上访问该文件。
当我在 Ubuntu 上运行以下命令时,它工作正常。
docker run -it -v /proc/1/mounts:/tmp/mounts ubuntu:16.04
但是在启用了 SELinux 的 CentOS 上,我无法挂载/proc/1/mounts文件。它会给出permission denied错误。
我也尝试过/etc/mtab,但由于它是到 的符号链接/proc/self/mounts,因此 docker 容器内的内容会发生变化。
除了 ,还有其他方法可以获取主机的挂载信息/proc/1/mounts,还是应该使用特定的 SELinux 标签?
我试过docker run -it --privileged -v /proc/1/mounts:/tmp/mounts ubuntu:16.04,它仍然给出同样的错误。
我假设您并不严格要求 init 进程(pid 1)可见的挂载,并且 docker 守护程序可见的挂载就足够了。通常,它们都应该具有相同的挂载命名空间。
(使用来自 CentOS 存储库的 docker 1.13.1)
我可以用/proc/1/mounts. 但是,使用 docker 守护进程的 mounts 文件可以工作:
$ docker run -it -v /proc/$(pidof dockerd-current)/mounts:/tmp/mounts ubuntu:16.04
Run Code Online (Sandbox Code Playgroud)
在 docker 容器中,/tmp/mounts然后列出主机的挂载。
(使用这里描述的外部 docker-ce 18.09.5 包)
除了上面解释的问题外,该docker-ce包还有一个containerd服务的 SE Linux 上下文的问题:
# ps xZ | grep containerd
system_u:system_r:unconfined_service_t:s0 5695 ? Ssl 0:00 /usr/bin/containerd
...
Run Code Online (Sandbox Code Playgroud)
我们希望containerd 用类型container_runtime_t而不是unconfined_service_t. 为此,/usr/bin/containerd必须更新的标签(一般参考):
# ls -Z /usr/bin/dockerd-ce
-rwxr-xr-x. root root system_u:object_r:container_runtime_exec_t:s0 /usr/bin/dockerd-ce
# ls -Z /usr/bin/containerd
-rwxr-xr-x. root root system_u:object_r:bin_t:s0 /usr/bin/containerd
# semanage fcontext -a -t container_runtime_exec_t /usr/bin/containerd
# restorecon /usr/bin/containerd
# ls -Z /usr/bin/containerd
-rwxr-xr-x. root root system_u:object_r:container_runtime_exec_t:s0 /usr/bin/containerd
Run Code Online (Sandbox Code Playgroud)
接下来,重新启动containerd守护进程:
# systemctl daemon-reload
# systemctl restart containerd
# ps xZ | grep containerd
system_u:system_r:container_runtime_t:s0 6557 ? Ssl 0:00 /usr/bin/containerd
Run Code Online (Sandbox Code Playgroud)
现在,可以使用与上述相同的技术(用dockerd代替dockerd-current)启动 docker 容器:
$ docker run -it -v /proc/$(pidof dockerd)/mounts:/tmp/mounts ubuntu:16.04
Run Code Online (Sandbox Code Playgroud)
我在 CentOS Linux 7.6.1810 版上对此进行了测试。
您可以验证 init 和 docker 守护进程是否具有相同的挂载命名空间(即它们的 /proc/[pid]/mounts 将显示相同的挂载):
# readlink /proc/1/ns/mnt /proc/$(pidof dockerd-current)/ns/mnt
mnt:[4026531840]
mnt:[4026531840]
Run Code Online (Sandbox Code Playgroud)
我还验证了 SE Linux 已启用:
# getenforce
Enforcing
Run Code Online (Sandbox Code Playgroud)
使用 CentOSdocker软件包运行您的命令时,我收到此错误消息:
$ docker run -it -v /proc/1/mounts:/tmp/mounts ubuntu:16.04
/usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "container init exited prematurely".
Run Code Online (Sandbox Code Playgroud)
此外,在 中/var/log/audit/audit.log,我看到以下 AVC 违规:
type=AVC msg=audit(1555530383.707:214): avc: denied { mounton } for pid=5691 comm="runc:[2:INIT]" path="/var/lib/docker/overlay2/8944062749f8ad19c3ff600e1d5286315227378174b95a952e7b0530927f4dcd/merged/tmp/mounts" dev="proc" ino=45422 scontext=system_u:system_r:container_runtime_t:s0 tcontext=system_u:system_r:init_t:s0 tclass=file permissive=0
Run Code Online (Sandbox Code Playgroud)
这告诉我们 SE Linux 规则不允许 container_runtime_t 类型的源上下文对“init_t”类型的目标上下文执行“mounton”操作。您可以验证这是 的上下文/proc/1/mounts,而/proc/$(pidof dockerd-current)/mounts匹配的上下文:
# ls -Z /proc/1/mounts /proc/$(pidof dockerd-current)/mounts
-r--r--r--. root root system_u:system_r:init_t:s0 /proc/1/mounts
-r--r--r--. root root system_u:system_r:container_runtime_t:s0 /proc/5476/mounts
Run Code Online (Sandbox Code Playgroud)