저는 권한이 없는 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)
}
위의 코드(및 피봇루트 등과 같은 다른 모든 항목)는 정상적으로 작동합니다. 하지만 Size를 2로 설정하면 충돌이 발생합니다.
ERROR: parent cmd.Run fork/exec /proc/self/exe: operation not permitted
루트로 실행할 때 작동하는 기능 문제인 것 같습니다.
이 내 꺼야 /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)