Linux OCI/runc系统路径约束如何防止重新安装此类路径?

Linux OCI/runc系统路径约束如何防止重新安装此类路径?,linux,docker,mount,procfs,runc,Linux,Docker,Mount,Procfs,Runc,我的问题的背景是我的一组测试用例,其中我在测试容器中创建了一个新的子用户名称空间以及一个新的子PID名称空间。然后我需要重新安装/proc,否则我将看到错误的进程信息,并且无法查找正确的进程相关信息,例如新的子用户+PID命名空间中的测试进程的命名空间(不诉诸游击战术) 测试线束/测试设置基本上就是这样,如果没有--特权(我将简化为所有CAP,并关闭seccomp和apparmor,以便切入真正的肉): 当然,阻力最小且最不美观的方法是使用--privileged,这将完成工作,因为这是一个一次

我的问题的背景是我的一组测试用例,其中我在测试容器中创建了一个新的子用户名称空间以及一个新的子PID名称空间。然后我需要重新安装/proc,否则我将看到错误的进程信息,并且无法查找正确的进程相关信息,例如新的子用户+PID命名空间中的测试进程的命名空间(不诉诸游击战术)

测试线束/测试设置基本上就是这样,如果没有
--特权
(我将简化为所有CAP,并关闭seccomp和apparmor,以便切入真正的肉):

当然,阻力最小且最不美观的方法是使用
--privileged
,这将完成工作,因为这是一个一次性的测试容器(可能完全没有它也有好处)

最近,我注意到Docker的
--security opt systempath=unconfined
,它(afaik)在生成的OCI/runc容器规范中转换为空。以下Docker run命令根据需要成功执行,在示例中它只是静默返回,因此执行正确:

docker run -it --rm --name closedboxx --cap-add ALL --security-opt seccomp=unconfined --security-opt apparmor=unconfined --security-opt systempaths=unconfined busybox unshare -Umpfr mount -t proc /proc proc
如果安装失败,在没有
--privilege
--security opt systempath=unconfined
的情况下运行时,子用户内的装载和容器内的PID命名空间如下所示:

docker run -it --rm --name closedboxx --cap-add ALL --security-opt seccomp=unconfined --security-opt apparmor=unconfined busybox unshare -Umpfr cat /proc/1/mountinfo
693 678 0:46 / / rw,relatime - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/AOY3ZSL2FQEO77CCDBKDOPEK7M:/var/lib/docker/overlay2/l/VNX7PING7ZLTIPXRDFSBMIOKKU,upperdir=/var/lib/docker/overlay2/60e8ad10362e49b621d2f3d603845ee24bda62d6d77de96a37ea0001c8454546/diff,workdir=/var/lib/docker/overlay2/60e8ad10362e49b621d2f3d603845ee24bda62d6d77de96a37ea0001c8454546/work,xino=off
694 693 0:50 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
695 694 0:50 /bus /proc/bus ro,relatime - proc proc rw
696 694 0:50 /fs /proc/fs ro,relatime - proc proc rw
697 694 0:50 /irq /proc/irq ro,relatime - proc proc rw
698 694 0:50 /sys /proc/sys ro,relatime - proc proc rw
699 694 0:50 /sysrq-trigger /proc/sysrq-trigger ro,relatime - proc proc rw
700 694 0:51 /null /proc/kcore rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
701 694 0:51 /null /proc/keys rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
702 694 0:51 /null /proc/latency_stats rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
703 694 0:51 /null /proc/timer_list rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
704 694 0:51 /null /proc/sched_debug rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
705 694 0:56 / /proc/scsi ro,relatime - tmpfs tmpfs ro
706 693 0:51 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
707 706 0:52 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
708 706 0:49 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw
709 706 0:55 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k
710 706 0:52 /0 /dev/console rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
711 693 0:53 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro
712 711 0:54 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,mode=755
713 712 0:28 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/systemd ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,xattr,name=systemd
714 712 0:31 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/cpuset ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuset
715 712 0:32 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/net_cls,net_prio ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,net_cls,net_prio
716 712 0:33 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory
717 712 0:34 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/perf_event ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,perf_event
718 712 0:35 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/devices ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,devices
719 712 0:36 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/blkio ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,blkio
720 712 0:37 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/pids ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,pids
721 712 0:38 / /sys/fs/cgroup/rdma ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,rdma
722 712 0:39 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/freezer ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,freezer
723 712 0:40 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/cpu,cpuacct ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpu,cpuacct
724 711 0:57 / /sys/firmware ro,relatime - tmpfs tmpfs ro
725 693 8:2 /var/lib/docker/containers/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/sda2 rw,stripe=256
944 693 8:2 /var/lib/docker/containers/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0/hostname /etc/hostname rw,relatime - ext4 /dev/sda2 rw,stripe=256
1352 693 8:2 /var/lib/docker/containers/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0/hosts /etc/hosts rw,relatime - ext4 /dev/sda2 rw,stripe=256
  • 到底是什么机制阻止了
    /proc
    上新装载的
    procfs
  • 是什么阻止我卸载
    /proc/kcore

  • 更多的挖掘发现了这一点,指出了正确的方向,但需要更多的解释(尤其是基于一段误导性的段落,该段落关于mount名称空间是从Michael Kerrisk不久前修复的手册页分层的)

    我们的出发点是当
    runc
    设置(测试)容器时,为了屏蔽系统路径,特别是在容器未来的
    /proc
    树中,它创建一组新的装载,以使用
    /dev/null
    屏蔽单个文件或使用
    tmpfs
    屏蔽子目录。这将导致
    procfs
    安装在
    /proc
    上,以及进一步的子安装

    现在,测试容器启动,在某个时刻,一个进程取消共享到一个新的用户名称空间中。请记住,此新用户命名空间(再次)属于UID为0的(真实)根用户,因为默认Docker安装不会在新用户命名空间中启用运行容器

    接下来,测试过程还将取消共享到一个新的装载名称空间中,因此这个新的装载名称空间属于新创建的用户名称空间,但不属于初始用户名称空间。根据中的“装载名称空间的限制”一节:

    如果新名称空间和从中复制装入点列表的名称空间由不同的用户名称空间拥有,则认为新装入名称空间的权限较低

    请注意,这里的标准是:“捐赠者”装载命名空间和新装载命名空间具有不同的用户命名空间;它们是否具有相同的所有者用户(UID)并不重要

    现在的重要线索是:

    作为单个单元来自更具特权的装载命名空间的装载被锁定在一起,并且不能在较低特权的装载命名空间中分离。(unshare(2)CLONE_NEWNS操作将原始装载命名空间中的所有装载作为单个单元进行传递,而在装载命名空间之间传播的递归装载作为单个单元进行传播。)

    由于现在无法再分离
    /proc
    装入点以及掩蔽子装入,因此无法(重新)装入
    /proc
    (问题1)。同样,不可能卸载
    /proc/kcore
    ,因为这将允许取消屏蔽(问题2)

    现在,当使用
    --security opt systempath=unconfined
    部署测试容器时,这只会导致单个
    /proc
    装载,而没有任何掩蔽子装载。因此,根据上面引用的手册页规则,我们只允许(重新)装载一个装载机,这取决于
    CAP\u SYS\u ADMIN
    功能,包括装载(除了大量其他有趣的功能)

    请注意,可以在容器中卸载屏蔽的
    /proc/
    路径,同时仍在原始(=初始)用户命名空间中,并且(毫不奇怪)拥有
    CAP\u SYS\u ADMIN
    。(b)锁只在单独的用户名称空间中起作用,因此一些项目努力在自己的新用户名称空间中部署容器(不幸的是,这不仅对容器网络有影响)

    docker run -it --rm --name closedboxx --cap-add ALL --security-opt seccomp=unconfined --security-opt apparmor=unconfined busybox unshare -Umpfr cat /proc/1/mountinfo
    693 678 0:46 / / rw,relatime - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/AOY3ZSL2FQEO77CCDBKDOPEK7M:/var/lib/docker/overlay2/l/VNX7PING7ZLTIPXRDFSBMIOKKU,upperdir=/var/lib/docker/overlay2/60e8ad10362e49b621d2f3d603845ee24bda62d6d77de96a37ea0001c8454546/diff,workdir=/var/lib/docker/overlay2/60e8ad10362e49b621d2f3d603845ee24bda62d6d77de96a37ea0001c8454546/work,xino=off
    694 693 0:50 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
    695 694 0:50 /bus /proc/bus ro,relatime - proc proc rw
    696 694 0:50 /fs /proc/fs ro,relatime - proc proc rw
    697 694 0:50 /irq /proc/irq ro,relatime - proc proc rw
    698 694 0:50 /sys /proc/sys ro,relatime - proc proc rw
    699 694 0:50 /sysrq-trigger /proc/sysrq-trigger ro,relatime - proc proc rw
    700 694 0:51 /null /proc/kcore rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
    701 694 0:51 /null /proc/keys rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
    702 694 0:51 /null /proc/latency_stats rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
    703 694 0:51 /null /proc/timer_list rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
    704 694 0:51 /null /proc/sched_debug rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
    705 694 0:56 / /proc/scsi ro,relatime - tmpfs tmpfs ro
    706 693 0:51 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755
    707 706 0:52 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
    708 706 0:49 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw
    709 706 0:55 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k
    710 706 0:52 /0 /dev/console rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
    711 693 0:53 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro
    712 711 0:54 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,mode=755
    713 712 0:28 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/systemd ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,xattr,name=systemd
    714 712 0:31 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/cpuset ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuset
    715 712 0:32 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/net_cls,net_prio ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,net_cls,net_prio
    716 712 0:33 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory
    717 712 0:34 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/perf_event ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,perf_event
    718 712 0:35 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/devices ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,devices
    719 712 0:36 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/blkio ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,blkio
    720 712 0:37 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/pids ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,pids
    721 712 0:38 / /sys/fs/cgroup/rdma ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,rdma
    722 712 0:39 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/freezer ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,freezer
    723 712 0:40 /docker/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0 /sys/fs/cgroup/cpu,cpuacct ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpu,cpuacct
    724 711 0:57 / /sys/firmware ro,relatime - tmpfs tmpfs ro
    725 693 8:2 /var/lib/docker/containers/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/sda2 rw,stripe=256
    944 693 8:2 /var/lib/docker/containers/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0/hostname /etc/hostname rw,relatime - ext4 /dev/sda2 rw,stripe=256
    1352 693 8:2 /var/lib/docker/containers/eebfacfdc6e0e34c4e62d9f162bdd7c04b232ba2d1f5327eaf7e00011d0235c0/hosts /etc/hosts rw,relatime - ext4 /dev/sda2 rw,stripe=256