我正在尝试实现以下场景:
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发布于 2016-12-14 21:14:00
简短的回答:,看起来https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt的类型没有正确设置。
解释
Linux内核默认所有挂载到MS_PRIVATE,但系统MS_SHARED,以方便nsp结识。这可以通过查看/proc/$PID/mountinfo的可选字段来观察。例如,这样的事情是可以预料到的:
$ cat /proc/self/mountinfo
. . .
25 0 8:6 / / rw,relatime shared:1 - ext4 /dev/sda6 rw,errors=remount-ro,data=ordered
^^^^^^
. . .请注意上面带下划线(By me)的shared:1字段,它指示当前/挂载点的传播类型是MS_SHARED,对等组ID是1 (在本例中,我们根本不关心对等组ID )。
当在CLONE_NEWNS上使用clone(2)标志时,将创建一个新的挂载命名空间,该命名空间被初始化为调用方挂载命名空间的副本。新命名空间的新的、复制的挂载点与调用方挂载名称空间中它们各自的原始挂载点连接相同的对等组。
父传递类型为MS_SHARED的新挂载点的传播类型也是MS_SHARED。因此,当您的“包含”进程mount()对循环设备上的文件系统进行处理时,挂载默认为MS_SHARED。稍后,它下的所有挂载也会传播到"main“进程的命名空间,这就是"main”进程能够看到它们的原因。
为了满足您的请求(对于“主”进程不能看到“包含”进程的挂载点),您所寻求的挂载传播类型是MS_SLAVE或MS_PRIVATE,这取决于您是否希望“包含”进程的根挂载点分别接收来自其他对等点的传播事件。显然,MS_PRIVATE提供了比MS_SLAVE更好的隔离功能。
因此,在您安装其他文件系统之前,将“包含”进程的根挂载点的传播类型更改为MS_PRIVATE或MS_SLAVE 就足够了,这样挂载就不会传播到"main“进程的命名空间。
密码
首先,当“包含”进程创建其根挂载点时,将尝试正确地设置传播类型。
但是,我在man 8 mount (引用)中注意到以下几点:
请注意,Linux内核不允许使用单个挂载(2)系统调用更改多个传播标志,并且这些标志不能与其他挂载选项混合。 由于util-Linux2.23,所以挂载命令允许在一起使用多个传播标志,也可以与其他挂载操作一起使用。这个特性是实验性的。当前面的挂载操作成功时,附加挂载(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,那么在/下“包含”进程所做的所有后续挂载都不会被传播,因此在"main“进程的命名空间中是不可见的,这可以在/proc/mounts或/proc/$PID/mountinfo中观察到。
资源
https://stackoverflow.com/questions/41128296
复制相似问题