进程和用户命名空间之间的关系

进程和用户命名空间之间的关系

我正在研究容器化机制。 手册页对于用户命名空间状态: “每个进程都是一个用户命名空间的成员。”

我也在努力追随本文作者指出: “用户命名空间允许用户命名空间 1 中进程的 UID 与用户命名空间 1 中的 UID 不同对于相同的过程在用户命名空间 2"

上述2种说法看似矛盾。同一进程可以是多个用户命名空间的一部分吗?进程、UID 和用户命名空间之间有什么关系?一些图形解释将不胜感激。

答案1

明显的矛盾来自于文章中对用户命名空间层次结构的遗漏。引用联机帮助页:

用户命名空间可以嵌套;也就是说,每个用户命名空间(初始(“根”)命名空间除外)都有一个父用户命名空间,并且可以有零个或多个子用户命名空间。父用户命名空间是通过调用创建用户命名空间的进程的用户命名空间unshare(2)或者clone(2)CLONE_NEWUSER旗帜。

在本文中,进程 D 是用户命名空间 2 的一部分,该命名空间嵌套在用户命名空间 1 内。单个进程属于单个用户命名空间,但该用户命名空间嵌套在其连续的父命名空间内,一直到根命名空间。

进程可以从多个用户命名空间可见;特别是,所有进程从最顶层的用户命名空间(或者如果您愿意,从所有用户命名空间外部)都是可见的。附加到进程的用户 id 会根据从中查询它们的用户命名空间以及每个用户命名空间中使用的 uid/gid 映射来更改值,这就是本文试图阐述的要点。

例如,您可以通过启动运行的无根容器来看到这一点bashps然后容器内会显示

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.3  0.0  12024  3196 pts/0    Ss   13:49   0:00 /bin/bash

但是相同的 bash过程将显示为

skitt    23345  0.0  0.0  12024  3208 pts/0    Ss+  15:49   0:00 /bin/bash

容器外。/proc/.../uid_map显示正在使用的 uid 映射:

$ cat /proc/23345/uid_map
         0       1000          1
         1     624288      65536

这意味着uid的“范围”从0到0里面相应的用户命名空间映射到我查询的用户命名空间中的1000,并且从1到65536的范围映射到624288–689823。

答案2

经过一番头痛之后,我想我已经有了一些答案。每个过程确实是一部分正好一个用户命名空间(如此处确认的),文章中的图片准确地描绘了它。除了init之外,进程也是由其他进程创建的。当进程创建子进程时,它可以选择将子进程分配给新的用户命名空间,该命名空间也称为父进程用户命名空间的“子命名空间”。

所谓UID(用户ID)和GID(组ID)映射使进程的 UID 和 GID 成为可能出现从另一个命名空间检查时会有所不同。映射很重要,因为进程可能会修改系统上其他命名空间的进程想要访问的文件,并且它们还希望从命名空间外部查看这些文件上有意义的 UID 或 GID。

映射 UID(与 GID 相同)的工作原理是获取创建新命名空间的进程的 UID,将其与/proc/<Process_ID>/uid_map新命名空间中的新进程进行匹配并分配映射的 UID。如果在创建新用户命名空间时未指定映射,则新命名空间中的进程 UID 将采用值。有关/proc/sys/kernel/overflowuid 如何定义此类映射的更多详细信息,请参阅这篇 LWN 文章

相关内容