在使用取消共享功能时,我偶然发现了非特权 shell 中的以下行为:
foo@pc $ id foo
uid=1000(foo) gid=1000(foo) groups=1000(foo),27(video),97(input)
foo@pc $ unshare -r -m bash
root@pc # mkdir /tmp/somedir
root@pc # mount -t tmpfs -o size=50M none /tmp/somedir
root@pc # mount | grep somedir
none on /tmp/somedir type tmpfs (rw,relatime,size=51200k,uid=1000,gid=1000)
令我惊讶的是,mount 竟然真的起作用了,因为它已经通过 选项以“伪造的”root 用户身份-r
运行unshare
。
这似乎只发生在 TMPFS 上,尝试安装其他任何东西似乎都会失败。
此外,如果我删除-m
保留父级挂载命名空间的选项,挂载将按预期失败:
mount: /tmp/somedir: permission denied.
mount_namespaces(7)没有描述与 TMPFS 相关的任何具体内容。
为什么我能够挂载该 TMPFS,而我的真实用户 ID 是非特权用户?为什么取消共享挂载命名空间会允许此挂载?
这是在 x86_64 Gentoo 上,带有 4.19.27 Linux 内核。
答案1
那是不是仅安装命名空间 - 该-r
选项还会导致新的用户命名空间也要创建,因为这就是 UID 映射(“伪根”)的真正实现方式。
$ strace unshare -r -m true
unshare(CLONE_NEWNS|CLONE_NEWUSER) = 0
用户命名空间根据设计,它会给你一些“类似 root”的权限,这些权限仅限于特定的命名空间;这就是 Linux 容器的工作方式。(换句话说,你的 uid 0 不是伪造的uid 0;它是真实的 uid 0自己的命名空间在其自己的用户组中拥有完全权限,但在父用户组中没有。)
这包括挂载某些文件系统(在手册页中列出)的能力,例如 overlayfs 或 tmpfs,它们支持命名空间,并且可能是容器运行所必需的。(由于内核 5.12 中引入了“文件系统 ID 映射”功能,未来这甚至可能包括传统的磁盘文件系统。)
请注意,Linux 仅允许在由新 uid 0“拥有”的挂载命名空间内执行此操作。如果您没有使用该-m
选项,但尝试在父挂载命名空间内挂载某些内容,则您仍然没有任何权限来执行此操作。