如何在docker容器内的命名空间内挂载私有的/proc?

如何在docker容器内的命名空间内挂载私有的/proc?

我需要在 Docker 容器内创建命名空间。作为此操作的一部分,我需要将/proc私有资源挂载到内部命名空间。我意识到我必须以某些权限运行容器才能实现这一点,但我更愿意启用最少的权限。

这有效:

$ sudo docker run --privileged --security-opt=seccomp=unconfined \
 -it fedora:rawhide /usr/bin/unshare -Ufmp -r \
 /bin/sh -c 'mount -t proc proc /proc'

这不:

$ sudo docker run --cap-add=sys_admin --security-opt=seccomp=unconfined \
  -it fedora:rawhide /usr/bin/unshare -Ufmp -r \
   /bin/sh -c 'mount -t proc proc /proc'
mount: /proc: cannot mount proc read-only.

因此,仅关闭 seccomp 过滤器并添加CAP_SYS_ADMIN是不够的。足够的?

更新:Selinux 是问题的一部分。如果您全局关闭 selinux 执行,它就可以正常工作。但是,您也可以使用 关闭特定容器的执行--security-opt label:disable,这在在线 Docker 手册的安全配置部分

sudo docker run --cap-add=sys_admin --security-opt label:disable \
 -it fedora:rawhide /usr/bin/unshare -fmp /bin/sh -c \
 'mount --make-private / ; mount -t proc proc /proc'

-U但是如果将和-r标志重新添加到,则会失败unshare。当然,即使使用和标志,添加--privileged到docker run命令也可以正常工作。-U-r

我目前正在尝试使用内核跟踪工具来找出到底是什么导致了 EPERM。这是一个非常无用且不明确的错误。

答案1

该命令有效:

sudo docker run --cap-add=sys_admin --security-opt label:disable -it fedora:rawhide /bin/sh -c 'for dir in $(awk '"'"'/\/proc\// { print $5; }'"'"' /proc/1/mountinfo ); do umount "$dir"; done; /usr/bin/unshare -Ufmp -r /bin/sh -c '"'"'mount --make-private / ; mount -t proc proc /proc ; ls /proc'"'"

/proc我没有将其拆分成多行,因为引用确实很重要。基本上,它会在运行 unshare 并/proc在子用户命名空间中挂载之前卸载一大堆东西。

/procDocker在其自己的目录中装载了一堆目录和文件,这些目录是空的 tmpfs 目录和空文件。 中的各种文件/proc代表适用于整个系统的值。事实上,/proc/kcore如果您是 root,将允许您读取容器内的内核内存,这会让很多人感到惊讶,因为很多人都想相信容器是某种轻量级 VM 之类的东西。

内核(至少从 4.14 版开始)fs/namespace.c:mnt_already_visible会检查您是否正在挂载已挂载的文件系统,如果该文件系统中已将某些内容挂载为子文件系统,并且这些挂载具有 MNT_LOCKED 标志,则挂载失败。每当您创建用户命名空间时,似乎都会将 MNT_LOCKED 标志应用于所有挂载(我没有找到内核中该标志的位置),以防止您卸载该命名空间中的内容(因为您在用户命名空间内获得特权)并再次使隐藏的内容可见。

我发布的命令使用 awk 脚本对 的内容进行处理,以提取Docker 已挂载的 的/proc/1/mountinfo所有子目录和文件,并将它们全部卸载。这使得文件系统再次可在嵌套用户命名空间中挂载。/proc/proc

相关内容