为什么创建大小为 1 的用户命名空间可以工作,但大小 >1 会失败

为什么创建大小为 1 的用户命名空间可以工作,但大小 >1 会失败

我正在尝试非特权 Linux 容器,并且正在编写一个创建极简容器的 Go 程序。程序分叉自身并在进程中创建名称空间。但是,由于某种原因,如果我将用户命名空间大小设置为大于 1,则以普通用户身份运行时会失败。

    cmd := exec.Command("/proc/self/exe", "run-container")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags:   syscall.CLONE_NEWUSER | syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
        Unshareflags: syscall.CLONE_NEWNS,
        UidMappings: []syscall.SysProcIDMap{
            {
                ContainerID: 0,
                HostID:      os.Getuid(),
                Size:        1,   // set this to 2 or more and it fails
            },
        },
        GidMappings: []syscall.SysProcIDMap{
            {
                ContainerID: 0,
                HostID:      os.Getgid(),
                Size:        1,
            },
        },
    }
    // other flags: CLONE_NEWNET, CLONE_NEWIPC, CLONE_NEWCGROUP, CLONE_NEWUSER,
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    err := cmd.Run()
    if err != nil {
        fmt.Println("ERROR: parent cmd.Run", err)
        os.Exit(1)
    }

上面的代码(以及所有其他东西,如pivot_root等)工作正常。但当我将 Size 设置为 2 时,它就崩溃了:

ERROR: parent cmd.Run fork/exec /proc/self/exe: operation not permitted

这似乎是一个功能问题,因为当我以 root 身份运行时它可以工作。

这是我的/etc/subuid

lxd:1000:1
root:1000:1
lxd:100000:65536
root:100000:65536
developer:165536:65536
mounter:231072:65536

更新:

我发现您需要 CAP_SETUID 将当前的内容映射euid到另一个(请参阅用户命名空间手册页)。

但即使sudo setcap cap_setuid=eip /my/binary失败了。错误消息已更改为:

ERROR: parent cmd.Run fork/exec /proc/self/exe: permission denied

如果我运行它,当尝试写入时strace会失败。EPERM/proc/xx/uid_map

openat(AT_FDCWD, "/proc/25233/uid_map", O_RDWR) = 5
write(5, "0 1000 100\n\0", 12)          = -1 EPERM (Operation not permitted)

相关内容