6

我试图通过试验unshareandnewuidmap命令来更好地理解用户命名空间。

这些是我运行的命令:

[root@host ~]$ ls -l /usr/bin/newuidmap
-rwsr-xr-x 1 root root 32944 May 16 19:37 /usr/bin/newuidmap
[root@host ~]$  unshare -U bash namespace
[nobody@host ~]$ echo $$
7134
[nobody@host ~]$ newuidmap 7134 65534 5000 1
newuidmap: write to uid_map failed: Operation not permitted

/etc/subuid:

nobody:5000:1
root:5000:1

知道为什么这会失败吗?

然后我尝试newuidmap在父命名空间的同一个 PID 上运行该命令,它似乎可以工作:

[root@host ~]$ newuidmap 7134 65534 5000 1
[root@host ~]$ cat /proc/7134/uid_map 
 65534       5000          1

但是当我从新命名空间中运行一个进程时,它似乎仍然以 root 而不是 UID 5000 运行:

[nobody@host ~]$ exec sleep 20

从另一个外壳:

[root@host ~]$ ps aux | grep 7134
root      7134  0.0  0.0   7292   708 pts/2    S+   02:07   0:00 sleep 20

我错过了什么?

4

1 回答 1

16

卡坦曼

1)

[nobody@host ~]$ newuidmap 7134 65534 5000 1
newuidmap: write to uid_map failed: Operation not permitted

知道为什么这会失败吗?

文档(http://man7.org/linux/man-pages/man7/user_namespaces.7.html)说明如下:

由 clone(2) 创建的带有 CLONE_NEWUSER 标志的子进程以新用户命名空间中的一组完整功能开始。<...> 请注意,对 execve(2) 的调用将导致以通常的方式重新计算进程的功能(请参阅功能(7))。

发生这种情况是因为 unshare 在将控制权归还给用户之前调用了“exec bash”,并且您失去了必要的功能,因此您无法从用户命名空间中更改 uid_map/gid_map。

不过,如果您编译一些应用程序(例如,您可以在 user_namespaces(7) 的示例中进行小修复)在“exec”之前更新 uid_map/gid_map,则更新将成功。

2)

但是当我从新命名空间中运行一个进程时,它似乎仍然以 root 而不是 UID 5000 运行:

我错过了什么?

  • 映射不会更改用户。映射将子命名空间中的 id 链接到其父命名空间中的 id,而不是相反的方式。
  • 您可以在子命名空间中调用setuid(2)seteuid(2)从同一用户命名空间中将凭据更改为其他一些凭据。它们当然应该映射到父命名空间中的值,否则 geteuid() 函数将失败。

这里有两个例子:

示例 1.假设我们创建了一个子用户命名空间。

arksnote linux-namespaces   # unshare -U bash
nobody@arksnote ~  $ id
uid=65534(nobody) gid=65534(nobody) группы=65534(nobody)
nobody@arksnote ~  $ echo $$
18526

现在让我们将父命名空间中的根与子命名空间中的某个 id(在本例中为 0)链接起来:

arksnote linux-namespaces   # newuidmap 18526 0 0 1
arksnote linux-namespaces   # cat /proc/18526/uid_map
         0          0          1

以下是子命名空间发生的情况:

nobody@arksnote ~  $ id
uid=0(root) gid=65534(nobody) группы=65534(nobody)

您可以尝试一些其他映射,例如newuidmap 18526 1 0 1并查看它是否应用于子用户名称空间,而不是父用户名称空间。

示例 2:现在我们不设置映射root

arksnote linux-namespaces   # newuidmap 18868 0  1000 1
arksnote linux-namespaces   # cat /proc/18868/uid_map
         0       1000          1

在这种情况下,用户root对于子用户命名空间是未知的:

nobody@arksnote ~  $ id
uid=65534(nobody) gid=65534(nobody) группы=65534(nobody)

您所做的[root@host ~]$ newuidmap 7134 65534 5000 1是将父命名空间中的 userid 5000 与子命名空间中的 uid 65534 关联,但该进程仍以root. 它显示为 65534 只是因为此值用于任何未知 id:

函数 getuid()、getgid() 从/proc/sys/kernel/overflowgid没有映射的 uids/gids 返回值。该值对应于没有任何系统权限的特殊用户:nobody,正如您在上面输出中的 uid/gid 中看到的那样。

参见Unmapped user and group IDsuser_namespaces(7)。

于 2017-11-14T21:31:56.753 回答