我想隔离一个潜在危险的进程,而不需要 root 权限。但是,系统调用pivot_root
失败并显示EINVAL
.
struct clone_args ca = {
.flags = CLONE_NEWUSER | CLONE_NEWNS,
};
pid = syscall(SYS_clone3, &ca, sizeof ca);
if (pid == 0) {
mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL);
mount(".", ".", NULL, MS_BIND | MS_REC, NULL);
mkdir("./oldroot", 0777);
syscall(SYS_pivot_root, ".", "./oldroot"); // Fails with EINVAL
}
我printk
在内核中添加了调用并重新编译了它,我知道它在这次检查中失败:if (new_mnt->mnt.mnt_flags & MNT_LOCKED)
。
这是什么MNT_LOCKED
意思?我该怎么做才能new_mnt
没有这个标志?作为普通用户,是否可以在用户命名空间中执行此操作?
答案1
我对 Linux 内核源代码的解释是 a 的目标pivot_root
必须是从它所在的用户命名空间中安装的。
MNT_LOCKED
似乎主要由 来设置lock_mnt_tree
,它在挂载命名空间发生更改的几个地方被调用,并由诸如if (child->mnt_parent->mnt_ns->user_ns != user_ns)
.
评论中lock_mnt_tree
说这样做是为了防止用户命名空间中的进程卸载挂载并查看被遮挡的内容,因为绑定挂载在敏感目录顶部的空目录是防止容器访问它的常见方法。
我相信这可以通过等到转向后取消共享用户命名空间来破坏。只是不要忘记在取消共享用户命名空间时/之后再次取消共享挂载命名空间,以便用户命名空间成为挂载命名空间的“所有者”。