我想以我的 (非 root) 用户身份运行一个具有非共享绑定挂载的进程。我可以这样做。
$ unshare --mount --map-root-user mount --bind foo bar
虽然这有效,但我在此上下文中伪造了 root 权限。我想以自己的身份运行后续进程。我可以保留我的身份,--map-current-user
但显然 mount 会失败。
$ unshare --mount --map-current-user mount --bind foo bar
mount: bar: must be superuser to use mount.
然后,我想到user
为这个挂载添加一个条目/etc/fstab
。它在命名空间之外工作,但仍然顽固地拒绝在命名空间内工作。在我所有的尝试中,这次失败是最让我惊讶的。
$ unshare --mount --map-current-user mount bar
mount: bar: must be superuser to use mount.
好吧,这有点不愉快,但是如何通过 sudo 进行安装呢?不行。
$ unshare --mount --map-current-user sudo mount --bind foo bar
sudo: /etc/sudo.conf is owned by uid 65534, should be 0
sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set
好吧,性能可能很糟糕,但基于 FUSE 的 bindfs 肯定会起作用吗?不会。
$ unshare --mount --map-current-user bindfs -o nonempty foo bar
fusermount: mount failed: Operation not permitted
这很尴尬,但如果我先假冒 root 然后再切换用户怎么办?有很多方法可以做到这一点,但都行不通。
$ unshare --mount --map-root-user runuser -u ${USER} someprocess
runuser: cannot set groups: Operation not permitted
然后我发现了nsenter
,它允许你在命名空间外部运行命名空间上下文中的命令。无论我怎么使用它,它都不会让我进入挂载命名空间。
nsenter --mount --target 1234 mount bar
nsenter: reassociate to namespace 'ns/mnt' failed: Operation not permitted
我以为命名空间应该可以减少对 sudo 的需求。真的没有办法做到这一点吗?
自从最初发布这篇文章以来,我记得普罗特,它实际上可以做到这一点。我曾经是它的忠实粉丝,但遇到了各种问题,上游开发也放缓了。我看到最近有一个新的 alpha 版本,这令人鼓舞,但它仍然没有修复 seccomp,我认为我需要它,因为我想要运行的进程是 Steam。它还有一些相当高的 CPU 开销,我想避免这种情况。我觉得我要求的不应该产生太多开销。proot 至少证明内核确实允许这样做,可能只是缺少用户空间工具。
答案1
答案2
您还可以使用假树. 它用于 CI/CD 管道和EDA 环境,无需 root 即可为特定构建步骤创建文件系统视图,同时保留 UID/GID、合理的信号处理、传播错误状态并保证清理。它可以重新映射文件和目录而不必处理/dev
或/
类似的事情。
例如:
$ echo "127.0.0.1 builder" > ./fake_etc_hosts
$ mkdir -p opt_build
$ touch opt_build/testfile
$ faketree --mount fake_etc_hosts:/etc/hosts \
--mount opt_build:/opt/build -- "$SHELL"
$ ls
testfile
$ cat /etc/hosts
127.0.0.1 builder
它具有用于覆盖主机名(--hostname
)、更改工作目录(--chdir
)以及使用标志调整行为的标志。
来自项目文档:
- 不需要root,只要系统上启用了 pid 和用户命名空间,任何用户都可以运行它(它们在大多数现代 Linux 发行版中都是默认启用的,您可以使用附带的测试进行验证)。
- 使用与用户相同的 UID/GID 运行命令,不会创建以 root 身份运行的 shell(可以通过标志覆盖)
- 不需要
LD_PRELOAD
、ptrace 或类似的技巧。它适用于静态二进制文件以及需要修改LD_LIBRARY_PATH
或LD_PRELOAD
具有保护措施以防止跟踪的二进制文件。- 仅影响在 faketree 中运行的命令,这意味着你可以在同一个系统上由同一个用户使用不同的参数并行运行多个 faketree 实例。
- 正确传播环境变量和权限,甚至允许图形工具在 faketree 中正确运行。
- 不依赖 FUSE,磁盘性能和性能不受影响。
- 可以覆盖单个文件,包括
/proc
和/sys
文件。- 尝试正确处理信号,因此在 CI/CD 管道中的集成应该很简单。向 faketree 发送 SIGTERM 将传播到子节点,并且 faketree 将正确等待所有子节点和后代节点终止后再退出。faketree
kill -9
的 A 也将确保所有后代节点都被终止。- 如果包装的命令调用 realpath 或检查文件系统,该命令将只看到一个带有挂载的普通文件系统。
还有一个此处发布博客文章描述其用途。
答案3
这个答案有一些工作示例,使用 unshare(不是 root)和 nsenter(作为容器内的 root)来引发绑定挂载,并以同步方式调用它们来执行您想要的操作。不需要真正的 root 访问权限
遗憾的是,它需要 util-linux 2.39.1,这可能意味着 ubuntu 23.04 或更高版本。
请注意,取消共享调用具有以前互斥的选项。
我仍在尝试让它在较早的 ubuntu 上运行,例如 22.04(最新的 LTS)。一旦 24.04 推出,我就会停止尝试。
但是由于目前 brwap 在比 util-linux > 2.39.1 更多的地方可用,我认为您的 bwrap 解决方案更好。