使用CLONE_NEWNS标志克隆后挂载文件系统

时间:2016-12-13 18:41:20

标签: c linux containers mount linux-namespaces

我正在尝试实施以下方案:

  1. clone()带有CLONE_NEWNS标志的主进程(表示新的安装命名空间)
  2. mount()子进程中的新文件系统
  3. 子进程已完成,并且在此进程中创建的所有文件系统都已卸载
  4. 但是它没有按照我的预期工作,我仍然在主进程中看到挂载的文件系统。我做错了什么?

    来源是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
    

1 个答案:

答案 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_SLAVEMS_PRIVATE,具体取决于是否您希望“包含”进程的根安装点分别从其他对等方接收传播事件。 显然,MS_PRIVATE提供的隔离度高于MS_SLAVE

因此,在您的情况下,将“包含”进程的根安装点的传播类型更改为MS_PRIVATEMS_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

中观察到名称空间

资源