2016-12-13 205 views
2

我试图实施以下情形:安装文件系统

  1. clone()CLONE_NEWNS标志主要过程(这意味着新坐骑命名空间)
  2. mount()新的文件系统中的子进程
  3. 子进程完成,并在此过程中创建的所有文件系统都卸载

但它不工作,因为我预期和我仍然在主进程中看到已挂载的文件系统。我究竟做错了什么?

来源是这里https://github.com/dmitrievanthony/sprat/blob/master/src/container.c#L47

系统是默认AWS的Ubuntu,

[email protected]:~/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 

回答

2

简短的回答:它看起来像的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(2)上的CLONE_NEWNS标志时,会创建一个新的挂载名称空间,该空间将初始化为调用者的挂载名称空间的副本。 新名称空间的新复制挂载点将与其在调用程序的挂载名称空间中各自的原始挂载点加入同一对等组。

其父传播类型为MS_SHARED的新安装点的传播类型也为MS_SHARED。因此,当您的“包含”进程mount()是循环设备上的文件系统时,安装程​​序默认为MS_SHARED。之后,它下面的所有挂载也会传播到“主”进程的命名空间,这就是“主”进程可以看到它们的原因。

对于你的要求得到满足(为“主”过程中没有看见“载”进程的挂载点),你所寻求的挂载传播类型是MS_SLAVEMS_PRIVATE,这取决于你是否希望你的“载”进程的根挂载点分别接收来自其他对等体的传播事件。 显然,MS_PRIVATE提供比MS_SLAVE更大的隔离度。

因此,在你的情况下,它应该是足以改变“载”进程的根的传播类型,挂载点MS_PRIVATEMS_SLAVE之前挂载文件系统的其余部分,所以坐骑将不会传播到“主”进程的名字空间。


代码

起初,一会尝试来正确设置传播类型当“包含”的过程产生其根挂载点。

不过,我注意到在man 8 mount以下(引用):

注意的是,Linux内核不允许更改多个 传播标志使用单个安装(2)系统调用和标志 不能与其他安装选项混合使用。

由于util-linux 2.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,所有后续坐骑“载”过程/下确实将不会传播,因此在“主”进程的名称空间中不可见,正如您在/proc/mounts/proc/$PID/mountinfo中观察到的那样。


资源

+0

这是一个很好的答案,谢谢! – dmitrievanthony