我正在尝试实施以下方案:
clone()
带有CLONE_NEWNS
标志的主进程(表示新的安装命名空间)mount()
子进程中的新文件系统但是它没有按照我的预期工作,我仍然在主进程中看到挂载的文件系统。我做错了什么?
来源是https://github.com/dmitrievanthony/sprat/blob/master/src/container.c#L47
系统是默认的AWS Ubuntu,
ubuntu@ip-172-31-31-112:~/sprat$ uname -a
Linux ip-172-31-31-112 4.4.0-53-generic #74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
答案 0 :(得分:4)
简答:看起来mount propagation的类型设置不正确。
首先,您的根安装点的传播类型应为MS_SHARED
,由systemd在启动时设置。
通过查看/proc/$PID/mountinfo
的可选字段可以观察到这一点。
例如,可能会出现类似的情况:
$ cat /proc/self/mountinfo
. . .
25 0 8:6 / / rw,relatime shared:1 - ext4 /dev/sda6 rw,errors=remount-ro,data=ordered
^^^^^^
. . .
注意上面的下划线(由我)shared:1
字段,表示/
挂载点的当前传播类型为MS_SHARED
,对等组 ID为1
(在我们的案例中,我们根本不关心对等组ID)。
在CLONE_NEWNS
上使用clone(2)
标志时,会创建一个新的mount命名空间,该命名空间被初始化为调用者的mount命名空间的副本。
新命名空间的新复制挂载点与调用方挂载命名空间中的相应原始挂载点连接相同的对等组。
父级传播类型为MS_SHARED
的新装载点的传播类型也是MS_SHARED
。因此,当“包含”进程mount()
是循环设备上的文件系统时,默认情况下挂载MS_SHARED
。之后,它下面的所有坐载也会传播到“主”进程的命名空间,这就是“主要”进程可以看到它们的原因。
为了满足您的要求(对于“主要”流程不要查看“包含”进程的挂载点),您寻找的挂载传播类型可以是MS_SLAVE
或MS_PRIVATE
,具体取决于是否您希望“包含”进程的根安装点分别从其他对等方接收传播事件。
显然,MS_PRIVATE
提供的隔离度高于MS_SLAVE
。
因此,在您的情况下,将“包含”进程的根安装点的传播类型更改为MS_PRIVATE
或MS_SLAVE
,然后再安装其他就足够了文件系统,因此安装不会传播到“主”进程的命名空间。
首先,当“包含”进程创建其根安装点时,会尝试正确设置传播类型。
但是,我注意到man 8 mount
(引用)中的以下内容:
请注意,Linux内核不允许更改多个 带有单个mount(2)系统调用的传播标志和标志 不能与其他挂载选项混合使用。
由于util-linux 2.23,mount命令允许使用几个 传播标志在一起,也与其他安装一起 操作。此功能是实验性的。传播标志是 在前面的安装时通过附加的mount(2)系统调用应用 运作成功。
查看代码,“包含”进程,在mount()
循环设备上的文件系统之后,它会向其发出chroot()
。此时,您可以通过注入此mount(2)
调用来设置其传播类型:
if (chroot(".") < 0) {
// handle error
}
if (mount("/", "/", c->fstype, MS_PRIVATE, "") < 0) {
// handle error
}
if (mkdir(...)) {
// handle error
}
现在传播类型设置为MS_PRIVATE
,“{包含”进程在/
下执行的所有后续安装都不会传播,因此在“主”进程中不会显示您可以在/proc/mounts
或/proc/$PID/mountinfo
。
Linux内核Shared Subtrees documentation,了解有关安装传播的更多信息。
Michael Kerrisk出色的LWN article解释mount命名空间比我更好。