进程如何拥有另一个命名空间中的能力?

进程如何拥有另一个命名空间中的能力?

我正在思考命名空间和功能之间的相互作用。有时,我会绊倒user_namespaces(7)中的以下措辞:

Holding CAP_SYS_ADMIN within the user namespace that owns a
process's mount namespace allows that process to ...

我确实了解以下内容:

  • 每个非用户命名空间N都属于一个用户命名空间U,这是由当时在U中创建N的进程决定的。

  • 能力是进程(更准确地说:线程)或文件的属性。对于这次讨论,我认为现在考虑流程就足够了。

  • 对于每种类型的命名空间,每个进程都位于该类型的一个命名空间中。

  • 正是 PID 命名空间和用户命名空间形成了层次结构。我对文档中措辞的理解是,即使进程 P 位于命名空间 A 中,而命名空间 A 又是命名空间 B 的子级,人们仍然不会说 P 位于 B 中,因为 P 位于 A 中,并且它仅位于该类型的一个命名空间中。换句话说:命名空间的父关系一定不能与集合包含相混淆。

现在,措辞

Holding a capability within the user namespace U that owns a
process's mount namespace M allows that process P to ...

告诉我从进程 P 转到其挂载命名空间 M (/proc/P/ns/mnt),找出其所属的用户命名空间 U ( ioctl_ns(2)),然后验证该进程是否拥有 U 中的功能。

这是我不明白的最后一部分:P 不一定在 U 中,那么它如何在那里拥有能力呢?是否存在进程 × 用户命名空间 ↦ 功能映射?此外,U 与 UID 相关联,但功能不是用户 ID 的属性。

答案1

事实上,答案就在我眼皮子底下,在user_namespaces(7)中,我似乎已经翻过了相关部分,我将在下面引用它:

       1. A process has a capability inside a user namespace if it is a member
          of that namespace and it has the capability in its  effective  capa‐
          bility  set.  A process can gain capabilities in its effective capa‐
          bility set in various ways.  For example, it may execute a set-user-
          ID  program  or an executable with associated file capabilities.  In
          addition,  a  process  may  gain  capabilities  via  the  effect  of
          clone(2), unshare(2), or setns(2), as already described.

       2. If  a process has a capability in a user namespace, then it has that
          capability in all child (and further removed descendant)  namespaces
          as well.

       3. When  a  user namespace is created, the kernel records the effective
          user ID of the creating process as being the "owner"  of  the  name‐
          space.   A  process that resides in the parent of the user namespace
          and whose effective user ID matches the owner of the  namespace  has
          all  capabilities in the namespace.  By virtue of the previous rule,
          this means that the process has all capabilities in all further  re‐
          moved  descendant  user  namespaces  as  well.  The NS_GET_OWNER_UID
          ioctl(2) operation can be used to discover the user ID of the  owner
          of the namespace; see ioctl_ns(2).

所以实际上存在进程×命名空间×能力的三元关系。我的理解如下:

  1. 进程显然在其所属的用户命名空间中具有这些功能,这些功能位于其有效功能集中。这里并不奇怪。

  2. 拥有某种能力可以抑制用户命名空间的层次结构。也不足为奇。

  3. 如果进程 P 是用户命名空间 U 的成员,并且 U 具有子用户命名空间 U',并且 P 的 eUID 是 U' 的 UID,则 P 具有 U' 中的所有能力。

不幸的是,我不确定我是否正确理解了3,但我未能通过以下实验观察到它:

$ id -u
1000
$ echo $$
4083
$ readlink /proc/4083/ns/user
user:[4026531837]
$ sleep 10001 &
[1] 4101
$ readlink /proc/4101/ns/user
user:[4026531837]
$ ps -p 4101 -o pid,euid,comm
    PID  EUID COMMAND
   4101  1000 sleep

现在sleep驻留在用户命名空间 4026531837 中,并且 eUID 为 1000。

$ unshare -r
# echo $$
4111
# readlink /proc/4111/ns/user
user:[4026532574]

从外部看,这个 ID 为 4026532574 的用户命名空间的父用户命名空间为 4026531837,UID 为 1000(见下文)。所以它应该满足上述标准。但是,我仍然没有看到睡眠过程的扩展功能:

# grep Cap /proc/4101/status
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000

也许我必须安装一个 neww /proc,但我不知道如何在不影响进程的情况下做到这一点sleep......

边注

从各种代码片段和手册页中,我整理了相当特别的内容恩斯雷尔研究命名空间层次结构。对于上面的示例,当在初始命名空间中运行时,它会产生

$ nsrel 4111 user
ID          TYPE      PARENT      USERNS      UID
4026532574  User      4026531837  4026531837  1000
4026531837  User      <oos>       <oos>       0

其中显示进程 4111 位于用户命名空间 4026532574 中,该用户命名空间的父命名空间为 4026531837,属于 UID 1000。

相关内容