Bra*_*gle 7 c linux filesystems linux-containers linux-namespaces
如何将在子命名空间中创建的装载传播到父级?
我正在尝试创建一个利用overlayfs
允许写入只读目录的工具.棘手的是,我希望任何用户都能够在没有root权限的情况下使用它.因此我希望这可以通过mount命名空间来实现,前提是管理员已经挂载了一个共享目录,然后任何用户都应该能够在该父树命名空间可见的树下创建一个覆盖(因此任何用户都可以登录) shell可以看到覆盖挂载).
这是我尝试过的,但不起作用:
# admin creates a shared tree for users to mount under
sudo mkdir /overlays
# bind mount over itself with MS_REC | MS_SHARED
sudo mount --bind --rshared /overlays /overlays
Run Code Online (Sandbox Code Playgroud)
假设用户想要创建覆盖/some/readonly/dir
,他们应该创建/overlays/user/{upper,work,mnt}
.我希望他们能够在/overlays
使用以下代码传播的目录下安装叠加层.
// user_overlay.c
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <linux/capability.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int child(void *args)
{
pid_t p;
p = mount("overlay", "/overlays/user/mnt", "overlay", 0, "lowerdir=/some/readonly/dir,upperdir=/overlays/user/upper,workdir=/overlays/user/work");
if (p == -1){
perror("Failed to mount overlay");
exit(1);
}
// Expose the mount to the parent namespace
p = mount("none", "/overlays/user/mnt", NULL, MS_SHARED, NULL);
if (p == -1){
perror("Failed to mark mount as shared");
exit(1);
}
// Exec bash so I can ensure that the mnt was created
// though in practice I would just daemonize this proc
// such that the mount is visible in the parent
// until this proc is killed
char *newargv[] = { "/bin/bash", NULL };
execv("/bin/bash", newargv);
perror("exec");
exit(EXIT_FAILURE);
return 0;
}
int main()
{
pid_t p = clone(child, malloc(4096) + 4096, CLONE_NEWNS | CLONE_NEWUSER | SIGCHLD, NULL);
if (p == -1) {
perror("clone");
exit(1);
}
// Wait until the bash proc in the child finishes
waitpid(p, NULL, 0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
执行gcc user_overlay.c -o user_overlay && ./user_overlay
确实在该子进程中挂载叠加层,但/overlays/user/mnt
不会传播到父进程.但是,/overlays/user/upper
父母和孩子都可以看到修改.
您想要实现的目标似乎是不可能的,至少不使用上述方法。您希望通过创建新的用户命名空间来向非特权用户授予安装权限CLONE_NEWUSER
。然而,引用mount_namespaces(7)
(强调我的):
挂载命名空间的限制
对于挂载命名空间,请注意以下几点:
* 挂载命名空间有一个所有者用户命名空间。其所有者用户命名空间与其父挂载命名空间的所有者用户命名空间不同的挂载命名空间被视为特权较低的挂载命名空间。* 创建权限较低的挂载命名空间时,共享挂载将减少为从属挂载。 (共享挂载和从属挂载将在下面讨论。)这可确保在特权较低的挂载命名空间中执行的映射不会传播到特权较高的挂载命名空间。
这意味着您正在创建的安装实际上具有slave
传播类型,而不是shared
您所期望的那样。这会导致挂载事件不会传播到父挂载命名空间。