carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package instanceexec
4
5import (
6 "runtime"
7 "unsafe"
8
9 "github.com/carlosframework/platform/internal/instancectl"
10 "golang.org/x/sys/unix"
11)
12
13// ScopeClaimGeneration closes descriptor-import routes before the claim
14// handshake. Mount isolation alone cannot stop SCM_RIGHTS from a pathname
15// socket in the shared instance directory. The locked launching thread and
16// every tenant descendant retain this filter across fork and exec.
17func ScopeClaimGeneration() error {
18 var arch uint32
19 switch runtime.GOARCH {
20 case "amd64":
21 arch = unix.AUDIT_ARCH_X86_64
22 case "arm64":
23 arch = unix.AUDIT_ARCH_AARCH64
24 default:
25 return instancectl.ErrClaimUnit
26 }
27 filter := []unix.SockFilter{
28 {Code: unix.BPF_LD | unix.BPF_W | unix.BPF_ABS, K: 4},
29 {Code: unix.BPF_JMP | unix.BPF_JEQ | unix.BPF_K, Jt: 1, K: arch},
30 {Code: unix.BPF_RET | unix.BPF_K, K: unix.SECCOMP_RET_KILL_PROCESS},
31 {Code: unix.BPF_LD | unix.BPF_W | unix.BPF_ABS, K: 0},
32 // Reject x32 as well as nonnative audit architectures.
33 {Code: unix.BPF_JMP | unix.BPF_JSET | unix.BPF_K, Jf: 1, K: 0x40000000},
34 {Code: unix.BPF_RET | unix.BPF_K, K: unix.SECCOMP_RET_ERRNO | uint32(unix.EPERM)},
35 }
36 for _, call := range []uint32{unix.SYS_RECVMSG, unix.SYS_RECVMMSG, unix.SYS_PTRACE, unix.SYS_PROCESS_VM_READV, unix.SYS_PROCESS_VM_WRITEV, unix.SYS_PIDFD_GETFD, unix.SYS_OPEN_BY_HANDLE_AT, unix.SYS_IO_URING_SETUP, unix.SYS_IO_URING_ENTER, unix.SYS_IO_URING_REGISTER, unix.SYS_SETNS, unix.SYS_UNSHARE} {
37 filter = append(filter,
38 unix.SockFilter{Code: unix.BPF_JMP | unix.BPF_JEQ | unix.BPF_K, Jf: 1, K: call},
39 unix.SockFilter{Code: unix.BPF_RET | unix.BPF_K, K: unix.SECCOMP_RET_ERRNO | uint32(unix.EPERM)})
40 }
41 filter = append(filter,
42 unix.SockFilter{Code: unix.BPF_JMP | unix.BPF_JEQ | unix.BPF_K, Jf: 1, K: unix.SYS_CLONE3},
43 unix.SockFilter{Code: unix.BPF_RET | unix.BPF_K, K: unix.SECCOMP_RET_ERRNO | uint32(unix.ENOSYS)},
44 unix.SockFilter{Code: unix.BPF_JMP | unix.BPF_JEQ | unix.BPF_K, Jf: 3, K: unix.SYS_CLONE},
45 unix.SockFilter{Code: unix.BPF_LD | unix.BPF_W | unix.BPF_ABS, K: 16},
46 unix.SockFilter{Code: unix.BPF_JMP | unix.BPF_JSET | unix.BPF_K, Jf: 1, K: unix.CLONE_NEWCGROUP | unix.CLONE_NEWIPC | unix.CLONE_NEWNET | unix.CLONE_NEWNS | unix.CLONE_NEWPID | unix.CLONE_NEWUSER | unix.CLONE_NEWUTS},
47 unix.SockFilter{Code: unix.BPF_RET | unix.BPF_K, K: unix.SECCOMP_RET_ERRNO | uint32(unix.EPERM)})
48 filter = append(filter, unix.SockFilter{Code: unix.BPF_RET | unix.BPF_K, K: unix.SECCOMP_RET_ALLOW})
49 if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil {
50 return err
51 }
52 program := unix.SockFprog{Len: uint16(len(filter)), Filter: &filter[0]}
53 unsynced, _, errno := unix.Syscall(unix.SYS_SECCOMP, unix.SECCOMP_SET_MODE_FILTER, unix.SECCOMP_FILTER_FLAG_TSYNC, uintptr(unsafe.Pointer(&program)))
54 runtime.KeepAlive(filter)
55 if errno != 0 {
56 return errno
57 }
58 if unsynced != 0 {
59 return instancectl.ErrClaimUnit
60 }
61 return nil
62}
63