Linux - 了解mount命名空间并克隆CLONE_NEWNS标志

Jak*_*ake 17 linux mount clone linux-namespaces

我正在阅读mountclone手册页.我想澄清一下CLONE_NEWNS如何影响子进程的文件系统视图.

(文件层次结构)

让我们将此树视为目录层次结构.让我们说5和6是父进程中的挂载点.我在另一个问题中澄清了挂载点.

所以我的理解是:5和6是挂载点意味着该mount命令以前用于在5和6处"挂载"文件系统(目录层次结构)(这意味着必须有5和6下的目录树).

mount手册页:

 A mount namespace is the set of filesystem mounts that are visible to a process. 
Run Code Online (Sandbox Code Playgroud)

clone手册页:

Every process lives in a mount namespace.  The namespace of a process is the data 
(the set of mounts) describing the file hierarchy as seen by that process.  After 
a fork(2) or clone() where the CLONE_NEWNS flag is not set, the child lives in the 
same mount namespace as the parent.
Run Code Online (Sandbox Code Playgroud)

另外:

After a clone() where the CLONE_NEWNS flag is set, the cloned child is started in a 
new mount namespace, initialized with a copy of the namespace of the parent.
Run Code Online (Sandbox Code Playgroud)

现在,如果我用clone()CLONE_NEWNS创建一个子进程,这是不是意味着孩子将在树(5和6)得到的挂载点的精确副本,仍然能够访问原树的其余部分?这是否也意味着孩子可以随意安装5和6,而不影响其父进程的mount命名空间中安装在5或6的内容.

如果是,它是否也意味着孩子可以挂载/卸载5或6之外的其他目录并影响父进程可见的内容?

谢谢.

Emm*_*met 20

进程的"挂载命名空间"只是它看到的挂载文件系统集.一旦从具有一个全局装入命名空间的传统情况转变为具有每个进程装载命名空间,您必须决定在创建子进程时要执行的操作clone().

传统上,安装或卸载文件系统改变了所有进程看到的文件系统:所有进程都看到一个全局安装命名空间,如果进行了任何更改(例如使用mount命令),所有进程都会立即看到该更改,而不管它们是什么与mount命令的关系.

对于每进程挂载命名空间,子进程现在可以具有与其父进程不同的挂载命名空间.现在出现的问题是:

子进程对mount命名空间的更改是否应该传播回父级?

显然,必须至少支持此功能,实际上,必须是默认功能.否则,启动mount命令本身不会产生任何变化(因为父shell看到的文件系统不会受到影响).

同样清楚的是,必须有可能抑制这种必要的传播,否则我们永远不能创建一个子进程,其mount命名空间与其父进程不同,并且我们再次有一个全局mount命名空间(文件系统如图所示init).

因此,我们必须决定何时创建子进程,子进程clone()是否从父进程获取有关已挂载文件系统的数据的副本,它可以在不影响父进程的情况下进行更改,或者获取指向与父进程相同的数据结构的指针.它可以改变(改变传播回来所必需的,就像mount从shell 启动时那样).

如果CLONE_NEWNS传递了标志clone(),则子节点获取其父节点的已挂载文件系统数据的副本,该数据可以在不影响父节点的mount命名空间的情况下进行更改.否则,它会获得指向父级挂载数据结构的指针,其中父级将看到子级所做的更改(因此mount命令本身可以工作).

现在,如果我使用CLONE_NEWNS克隆来创建子进程,这是否意味着子将获得树(5和6)中的挂载点的精确副本,并且仍然能够访问原始树的其余部分?

是.在调用之后,它会看到与其父级完全相同的树clone().

这是否也意味着孩子可以随意安装5和6,而不影响其父进程的mount命名空间中安装在5或6的内容.

是.自从您使用以来CLONE_NEWNS,孩子可以从5卸载一个设备并在那里安装另一个设备,只有它(及其子设备)可以看到更改.在这种情况下,没有其他进程可以看到孩子所做的更改.

如果是,它是否也意味着孩子可以挂载/卸载5或6之外的其他目录并影响父进程可见的内容?

CLONE_NEWNS不可以.如果您已经使用过,那么孩子所做的更改就无法传播回父母.

如果您还没有使用过CLONE_NEWNS,那么子进程将收到一个指向与其父进程相同的mount命名空间数据的指针,并且任何共享这些数据结构的进程(包括父进程)都会看到子进程所做的任何更改.(使用时创建新子项也是如此fork().)


小智 5

我没有足够的声望点来添加评论,所以添加此评论作为答案。这只是 Emmet 答案的补充。

AFAICU,如果创建的进程设置了 CLONE_NEWNS 标志,则它只能挂载那些设置了 FS_USERNS_MOUNT 标志的文件系统。并且几乎所有基于磁盘的文件系统都没有设置这个标志(出于安全原因)。在 do_new_mount 中,有这个检查:

        if (user_ns != &init_user_ns) {
            if (!(type->fs_flags & FS_USERNS_MOUNT)) {
                    put_filesystem(type);
                    return -EPERM;
            }
Run Code Online (Sandbox Code Playgroud)

如果我错了,请纠正我

  • 您错了。FS_USERNS_MOUNT 表示文件系统可以由在用户 (uid) 命名空间中映射为 root 的非 root 用户挂载。也就是说,如果您是(真正的)root,您可以在 CLONE_NEWNS 挂载命名空间中挂载任何文件系统 (3认同)