为什么用`unshare -m`启动的进程会影响主机中的挂载?

时间:2019-05-22 10:36:38

标签: linux namespaces mount

这是我所做的:

$ sudo unshare -m --propagation unchanged sh    # Run a shell with `unshare` in a separate mount namespace
# cd /tmp
# mkdir foo bar
# mount --bind foo bar  # This mount is supposed to be only visible in this separate mount namespace, right?
# exit                  # Back to the original shell
$ cat /proc/self/mountinfo | grep foo     # Why can I see it here???
272 26 8:1 /tmp/foo /tmp/bar rw,relatime shared:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=ordered

我知道它在运行sudo unshare -m sh时会按预期工作,但这是因为默认情况下unshare会将所有装载的递归设置为私有(请参见代码here和{{3 }})。当我使用--propagation unchanged运行它时,unshare完全不会设置装载的传播,它只会使用unshare()调用CLONE_NEWNS syscall,在这种情况下,由如上例所示,启动的外壳将在主机安装名称空间中可见。

所以我的问题是,由于隔离安装/ umount操作是通过挂载传播,那么为什么我们根本需要CLONE_NEWNS?还是CLONE_NEWNS仅用于隔离不同安装名称空间的设置安装传播(而不是安装/ umount操作)?

1 个答案:

答案 0 :(得分:0)

Mount传播类型确定是否将新的安装点和安装点下的安装点的卸载传播回父命名空间。默认情况下,所有安装点都标记为共享安装。如果您创建一个新的名称空间并保留传播类型不变,则这些安装下的新安装将被传播回父对象。但是,如果父名称空间中有一个专用的挂载点,则该挂载点本身会被复制到新的命名空间中,但是新的挂载不会传播回父对象。

举个例子:

# mkdir -p /tmp/shared-mount
# mount --bind --make-shared /tmp/shared-mount /tmp/shared-mount

# mkdir -p /tmp/private-mount
# mount --bind --make-private /tmp/private-mount /tmp/private-mount

# grep "/tmp" /proc/self/mountinfo
406 29 8:5 /tmp/shared-mount /tmp/shared-mount rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
420 29 8:5 /tmp/private-mount /tmp/private-mount rw,relatime - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered

请注意“ shared:1”,表示共享的安装点。现在:

# unshare -m --propagation unchanged /bin/bash
# grep "/tmp" /proc/self/mountinfo
551 432 8:5 /tmp/shared-mount /tmp/shared-mount rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
552 432 8:5 /tmp/private-mount /tmp/private-mount rw,relatime - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered

一切都很好。现在,让我们在新名称空间的以下安装点下创建子安装:

# mkdir -p /tmp/shared-mount/submount
# mount --bind /tmp/shared-mount/submount /tmp/shared-mount/submount

# mkdir -p /tmp/private-mount/submount
# mount --bind /tmp/private-mount/submount /tmp/private-mount/submount

# grep "/tmp" /proc/self/mountinfo
551 432 8:5 /tmp/shared-mount /tmp/shared-mount rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
552 432 8:5 /tmp/private-mount /tmp/private-mount rw,relatime - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
553 551 8:5 /tmp/shared-mount/submount /tmp/shared-mount/submount rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
555 432 8:5 /tmp/shared-mount/submount /tmp/shared-mount/submount rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
577 552 8:5 /tmp/private-mount/submount /tmp/private-mount/submount rw,relatime - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered

现在,您可以从父命名空间下的另一个外壳观察/proc/self/mountinfo,并看到专用安装点下的新子安装尚未传播。或像您一样退出新的名称空间:

# exit
# grep "/tmp" /proc/self/mountinfo
406 29 8:5 /tmp/shared-mount /tmp/shared-mount rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
420 29 8:5 /tmp/private-mount /tmp/private-mount rw,relatime - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
556 406 8:5 /tmp/shared-mount/submount /tmp/shared-mount/submount rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered
554 29 8:5 /tmp/shared-mount/submount /tmp/shared-mount/submount rw,relatime shared:1 - ext4 /dev/sda5 rw,errors=remount-ro,data=ordered

在新名称空间下,您还可以将共享安装点设为私有:

# mount --make-private /tmp/shared-mount

在现实生活中,它甚至更复杂。很好的补充读物: