为什么非 root 用户无法取消共享 pid 命名空间?

为什么非 root 用户无法取消共享 pid 命名空间?

unshare -pf bash失败,且不允许操作有效的根。如果我不挂载proc,则不需要挂载ns。是否有任何特殊原因不允许创建 pid ns?

答案1

这确实是不允许的,因为这是一个特权操作:unshare(2)告诉:

CLONE_NEWPID(从 Linux 3.8 开始)

[...]

使用CLONE_NEWPID需要CAP_SYS_ADMIN能力。欲了解更多信息,请参阅pid_命名空间(7)

可以做的是首先取消共享用户命名空间(这不是特权操作)。然后作为在评论中提到,并记录在用户命名空间(7),取消共享用户命名空间足以CAP_SYS_ADMIN至少在下一个 execve() 之前获得其中的内容,因此甚至不需要在这里映射到 root 用户。现在,从这个新的用户命名空间,进程可以取消共享新的 pid 命名空间。

如 pid_namespaces(7) 中所述,只有“使用该标志调用 unshare(2) 后进程创建的第一个子进程CLONE_NEWPID”实际上会位于新的 pid 命名空间中并且“具有 pid 1”。所以 fork 选项在技术上并不是必需的,但是没有它也不是很有用,因为只有第一个子进程实际上会进入/启动新的 pid 命名空间(并且像bash未使用的进程一样bash --norc会 fork 进程并丢失稍后有机会运行自己的选择之一)

$ unshare -U --map-user=$(id -u) --map-group=$(id -g) -f -p
$ echo $$
1

unshare这需要具有相关选项的足够新的版本。使用unshare缺少这些选项的旧版本时,请参阅末尾的注释。

挂载反映新 pid 命名空间的新实例/proc以实际查看新 pid 而不是来自父命名空间的 pid 也是应该做的事情:

$ ls -l /proc/$$/exe
ls: cannot read symbolic link '/proc/1/exe': Permission denied
lrwxrwxrwx 1 nobody nogroup 0 Sep 16 16:13 /proc/1/exe

由于这需要新命名空间中的挂载权限,因此还需要首先取消共享挂载命名空间,以便用户命名空间也获得在此新挂载命名空间中执行新挂载的权限。这仍然不需要是 root 因为(在最终 fork 和 exec 之前),取消共享进程仍然得到CAP_SYS_ADMIN所以最后,这可以完成一些有用的操作:

$ unshare -U --map-user=$(id -u) --map-group=$(id -g) -m --mount-proc -f -p 
$ echo $$
1
$ ls -l /proc/$$/exe
lrwxrwxrwx 1 user user 0 Oct  8 21:49 /proc/1/exe -> /usr/bin/bash

附加说明:取消共享时不映射到 root,而是映射到同一用户,当使用unshare缺少命令的旧版本时--map-user,可以像这样完成:

user@host$ echo $$; id -u; id -g; exec unshare -U -f -p
670034
1000
1000
nobody@host$ echo $$; id -u; id -g
1
65534
65534

然后,这需要其他进程的通常帮助来写入新用户命名空间的用户映射(或者可能是命令的最新版本unshare首先完成此操作)。如果此进程在父名称空间中没有特权(命令newuidmapnewgidmapsetuid root,因此可以根据需要设置为此用户保留的任何映射),则几乎没有选择有用映射(通常是 root 或用户本身)。

其他 shell(仍在父命名空间中):

user@host$ pstree -p 670034
unshare(670034)───bash(670638)
user@host$ echo '1000 1000 1' > /proc/670034/uid_map
user@host$ echo deny > /proc/670034/setgroups
user@host$ echo '1000 1000 1' > /proc/670034/gid_map

再次第一个外壳:

nobody@host$ exec bash #for cosmetic effect
user@host$ echo $$; id -u; id -g
1
1000
1000

相关内容