用户命名空间中的 hub_root() 失败并显示 EINVAL

用户命名空间中的 hub_root() 失败并显示 EINVAL

我想隔离一个潜在危险的进程,而不需要 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说这样做是为了防止用户命名空间中的进程卸载挂载并查看被遮挡的内容,因为绑定挂载在敏感目录顶部的空目录是防止容器访问它的常见方法。

我相信这可以通过等到转向后取消共享用户命名空间来破坏。只是不要忘记在取消共享用户命名空间时/之后再次取消共享挂载命名空间,以便用户命名空间成为挂载命名空间的“所有者”。

相关内容