carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package instancectl
2
3import (
4 "os"
5 "path/filepath"
6 "runtime"
7 "strings"
8 "unsafe"
9
10 "golang.org/x/sys/unix"
11)
12
13type claimBPFInsn struct {
14 Code, Registers uint8
15 Offset int16
16 Immediate int32
17}
18
19func claimConnectFilter(ipv6 bool) []claimBPFInsn {
20 // bpf_sock_addr has network-order user_ip4 at 4 and user_ip6 at 8.
21 load := func(offset int16) []claimBPFInsn { return []claimBPFInsn{{0x61, 0x10, offset, 0}, {0xdc, 0, 0, 32}} }
22 var p []claimBPFInsn
23 if !ipv6 {
24 p = append(p, load(4)...)
25 p = append(p, claimBPFInsn{0x54, 0, 0, -16777216}, claimBPFInsn{0x15, 0, 2, 0x7f000000})
26 } else {
27 p = append(p, load(8)...)
28 p = append(p, claimBPFInsn{0x55, 0, 14, 0})
29 p = append(p, load(12)...)
30 p = append(p, claimBPFInsn{0x55, 0, 11, 0})
31 p = append(p, load(16)...)
32 p = append(p, claimBPFInsn{0x15, 0, 4, 0xffff}, claimBPFInsn{0x55, 0, 7, 0})
33 p = append(p, load(20)...)
34 p = append(p, claimBPFInsn{0x15, 0, 6, 1})
35 p = append(p, load(20)...)
36 p = append(p, claimBPFInsn{0x54, 0, 0, -16777216}, claimBPFInsn{0x15, 0, 2, 0x7f000000})
37 }
38 return append(p, claimBPFInsn{0xb7, 0, 0, 1}, claimBPFInsn{0x95, 0, 0, 0}, claimBPFInsn{0xb7, 0, 0, 0}, claimBPFInsn{0x95, 0, 0, 0})
39}
40
41func claimAttachConnectFilter(group int, kind uint32, ipv6 bool) error {
42 p := claimConnectFilter(ipv6)
43 license := []byte("GPL\x00")
44 attr := struct {
45 Type, Count uint32
46 Instructions, License uint64
47 LogLevel, LogSize uint32
48 LogBuffer uint64
49 Version, Flags uint32
50 Name [16]byte
51 IfIndex, Attach uint32
52 }{Type: unix.BPF_PROG_TYPE_CGROUP_SOCK_ADDR, Count: uint32(len(p)), Instructions: uint64(uintptr(unsafe.Pointer(&p[0]))), License: uint64(uintptr(unsafe.Pointer(&license[0]))), Attach: kind}
53 fd, _, errno := unix.Syscall(unix.SYS_BPF, unix.BPF_PROG_LOAD, uintptr(unsafe.Pointer(&attr)), unsafe.Sizeof(attr))
54 runtime.KeepAlive(p)
55 runtime.KeepAlive(license)
56 if errno != 0 {
57 return errno
58 }
59 defer unix.Close(int(fd))
60 attach := struct{ Target, Program, Kind, Flags uint32 }{uint32(group), uint32(fd), kind, unix.BPF_F_ALLOW_MULTI}
61 _, _, errno = unix.Syscall(unix.SYS_BPF, unix.BPF_PROG_ATTACH, uintptr(unsafe.Pointer(&attach)), unsafe.Sizeof(attach))
62 if errno != 0 {
63 return errno
64 }
65 return nil
66}
67
68func (u ClaimUnits) restrictBoundNetwork(s ClaimUnitStarted) error {
69 _, group, err := u.Placement(u.BoundHost)
70 if err != nil || s.ControlGroup != group || s.Unit != u.BoundUnit || u.CgroupRoot != "/sys/fs/cgroup" {
71 return os.ErrPermission
72 }
73 // Pin each directory and check every ancestor before attaching. No program
74 // is pinned on disk; the kernel retains it until this cgroup is destroyed.
75 fd, err := unix.Open("/", unix.O_RDONLY|unix.O_DIRECTORY|unix.O_CLOEXEC, 0)
76 if err != nil {
77 return err
78 }
79 defer func() { unix.Close(fd) }()
80 for _, part := range strings.Split(strings.TrimPrefix(filepath.Join(u.CgroupRoot, group), "/"), "/") {
81 next, e := unix.Openat(fd, part, unix.O_RDONLY|unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
82 if e != nil {
83 return e
84 }
85 unix.Close(fd)
86 fd = next
87 var st unix.Stat_t
88 if e = unix.Fstat(fd, &st); e != nil {
89 return e
90 }
91 if st.Uid != 0 || st.Mode&0022 != 0 {
92 return os.ErrPermission
93 }
94 }
95 var fs unix.Statfs_t
96 if err = unix.Fstatfs(fd, &fs); err != nil {
97 return err
98 }
99 if fs.Type != unix.CGROUP2_SUPER_MAGIC {
100 return os.ErrPermission
101 }
102 for _, hook := range []struct {
103 kind uint32
104 ipv6 bool
105 }{
106 {unix.BPF_CGROUP_INET4_CONNECT, false}, {unix.BPF_CGROUP_INET6_CONNECT, true},
107 {unix.BPF_CGROUP_UDP4_SENDMSG, false}, {unix.BPF_CGROUP_UDP6_SENDMSG, true},
108 } {
109 if err = claimAttachConnectFilter(fd, hook.kind, hook.ipv6); err != nil {
110 return err
111 }
112 }
113 return nil
114}
115