为什么我不能将挂载命名空间绑定到文件

ste*_*fan 5 linux namespace bind-mount unshare

我观察到以下几点:

作为 1 号 shell 中的非特权用户:

user@box:~$ sysctl kernel.unprivileged_userns_clone
kernel.unprivileged_userns_clone = 1
user@box:~$ unshare --mount --user
nobody@box:~$ echo $$
18655
Run Code Online (Sandbox Code Playgroud)

并作为 2 号 shell 中的 root:

root@box:~# mkdir -p /tmp/myns
root@box:~# touch /tmp/myns/{user,mnt}
root@box:~# mount --bind /proc/18655/ns/user /tmp/myns/user 
root@box:~# mount --bind /proc/18655/ns/mnt /tmp/myns/mnt
mount: /tmp/myns/mnt: wrong fs type, bad option, bad superblock on /proc/18655/ns/mnt, missing codepage or helper program, or other error.
Run Code Online (Sandbox Code Playgroud)

该错误令人惊讶:我无法将挂载命名空间绑定挂载到文件,但我可以将用户命名空间绑定挂载到文件?为什么会这样,我怎样才能使这个挂载命名空间可供非特权用户使用user

为什么我想要这个:为了测试一个程序,我想~user用一个临时文件系统覆盖,最初共享原始内容。可以按照以下方式由 root 设置

tmp='/tmp/GAtcNNeSfM8b'
mkdir -p "$tmp"
mount -t tmpfs -o size=100m tmpfs "$tmp"
mkdir -p "${tmp}/"{upper,work,lower}
mount --bind -o ro /home/user "${tmp}/lower"

unshare -m
mount -t overlay -o"lowerdir=${tmp}/lower,upperdir=${tmp}/upper,workdir=${tmp}/work" overlay /home/user
touch /tmp/namespace
mount --bind /proc/self/ns/mnt /tmp/namespace
Run Code Online (Sandbox Code Playgroud)

但最后一行失败了。

目的是非特权用户可以nsenter --mount=/tmp/namespace看到与以前相同的系统,只是对 的更改/home/user不是持久的。实际上,我什至不想取消共享用户命名空间。

我有意识地试图避免 LXC、Docker 甚至 VirtualBox 的开销。我认为使用 Linux 标准工具应该是可能的。

更新:我正在运行一个最新的 ArchLinux,

$ uname -r
5.0.10-arch1-1-ARCH
Run Code Online (Sandbox Code Playgroud)

sou*_*edi 1

鉴于它只影响挂载命名空间,我非常怀疑这是由于挂载命名空间的循环预防检查之一造成的。我不认为这与链接中讨论的情况完全相同,因为unshare --mount默认将安装传播设置为private,即禁用它。

但是,为了防止某些竞争条件,我认为完全正确可能需要您将挂载命名空间挂载到具有private挂载传播的挂载内。我还认为如果您使用unbindable. (我认为unbindable已经包括了所有的影响private)。

即,将挂载命名空间挂载到使用以下命令准备的目录中:

mount --bind /var/local/lib/myns/ /var/local/lib/myns/
mount --make-unbindable /var/local/lib/myns/
Run Code Online (Sandbox Code Playgroud)

总的来说,我认为这是最安全的方法,可以避免触发此类问题。

我的比赛条件是假设的。我不希望你大部分时间都能击中它。所以我不知道你的实际问题是什么。