github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/internal/sys/syscall.go (about) 1 package sys 2 3 import ( 4 "runtime" 5 "syscall" 6 "unsafe" 7 8 "github.com/cilium/ebpf/internal/unix" 9 ) 10 11 // ENOTSUPP is a Linux internal error code that has leaked into UAPI. 12 // 13 // It is not the same as ENOTSUP or EOPNOTSUPP. 14 const ENOTSUPP = syscall.Errno(524) 15 16 // BPF wraps SYS_BPF. 17 // 18 // Any pointers contained in attr must use the Pointer type from this package. 19 func BPF(cmd Cmd, attr unsafe.Pointer, size uintptr) (uintptr, error) { 20 // Prevent the Go profiler from repeatedly interrupting the verifier, 21 // which could otherwise lead to a livelock due to receiving EAGAIN. 22 if cmd == BPF_PROG_LOAD || cmd == BPF_PROG_RUN { 23 maskProfilerSignal() 24 defer unmaskProfilerSignal() 25 } 26 27 for { 28 r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size) 29 runtime.KeepAlive(attr) 30 31 // As of ~4.20 the verifier can be interrupted by a signal, 32 // and returns EAGAIN in that case. 33 if errNo == unix.EAGAIN && cmd == BPF_PROG_LOAD { 34 continue 35 } 36 37 var err error 38 if errNo != 0 { 39 err = wrappedErrno{errNo} 40 } 41 42 return r1, err 43 } 44 } 45 46 // Info is implemented by all structs that can be passed to the ObjInfo syscall. 47 // 48 // MapInfo 49 // ProgInfo 50 // LinkInfo 51 // BtfInfo 52 type Info interface { 53 info() (unsafe.Pointer, uint32) 54 } 55 56 var _ Info = (*MapInfo)(nil) 57 58 func (i *MapInfo) info() (unsafe.Pointer, uint32) { 59 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 60 } 61 62 var _ Info = (*ProgInfo)(nil) 63 64 func (i *ProgInfo) info() (unsafe.Pointer, uint32) { 65 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 66 } 67 68 var _ Info = (*LinkInfo)(nil) 69 70 func (i *LinkInfo) info() (unsafe.Pointer, uint32) { 71 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 72 } 73 74 func (i *TracingLinkInfo) info() (unsafe.Pointer, uint32) { 75 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 76 } 77 78 func (i *CgroupLinkInfo) info() (unsafe.Pointer, uint32) { 79 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 80 } 81 82 func (i *NetNsLinkInfo) info() (unsafe.Pointer, uint32) { 83 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 84 } 85 86 func (i *XDPLinkInfo) info() (unsafe.Pointer, uint32) { 87 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 88 } 89 90 func (i *TcxLinkInfo) info() (unsafe.Pointer, uint32) { 91 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 92 } 93 94 func (i *NetfilterLinkInfo) info() (unsafe.Pointer, uint32) { 95 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 96 } 97 98 func (i *NetkitLinkInfo) info() (unsafe.Pointer, uint32) { 99 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 100 } 101 102 func (i *KprobeMultiLinkInfo) info() (unsafe.Pointer, uint32) { 103 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 104 } 105 106 func (i *KprobeLinkInfo) info() (unsafe.Pointer, uint32) { 107 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 108 } 109 110 var _ Info = (*BtfInfo)(nil) 111 112 func (i *BtfInfo) info() (unsafe.Pointer, uint32) { 113 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 114 } 115 116 func (i *PerfEventLinkInfo) info() (unsafe.Pointer, uint32) { 117 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 118 } 119 120 // ObjInfo retrieves information about a BPF Fd. 121 // 122 // info may be one of MapInfo, ProgInfo, LinkInfo and BtfInfo. 123 func ObjInfo(fd *FD, info Info) error { 124 ptr, len := info.info() 125 err := ObjGetInfoByFd(&ObjGetInfoByFdAttr{ 126 BpfFd: fd.Uint(), 127 InfoLen: len, 128 Info: NewPointer(ptr), 129 }) 130 runtime.KeepAlive(fd) 131 return err 132 } 133 134 // BPFObjName is a null-terminated string made up of 135 // 'A-Za-z0-9_' characters. 136 type ObjName [unix.BPF_OBJ_NAME_LEN]byte 137 138 // NewObjName truncates the result if it is too long. 139 func NewObjName(name string) ObjName { 140 var result ObjName 141 copy(result[:unix.BPF_OBJ_NAME_LEN-1], name) 142 return result 143 } 144 145 // LogLevel controls the verbosity of the kernel's eBPF program verifier. 146 type LogLevel uint32 147 148 const ( 149 BPF_LOG_LEVEL1 LogLevel = 1 << iota 150 BPF_LOG_LEVEL2 151 BPF_LOG_STATS 152 ) 153 154 // LinkID uniquely identifies a bpf_link. 155 type LinkID uint32 156 157 // BTFID uniquely identifies a BTF blob loaded into the kernel. 158 type BTFID uint32 159 160 // TypeID identifies a type in a BTF blob. 161 type TypeID uint32 162 163 // MapFlags control map behaviour. 164 type MapFlags uint32 165 166 //go:generate go run golang.org/x/tools/cmd/stringer@latest -type MapFlags 167 168 const ( 169 BPF_F_NO_PREALLOC MapFlags = 1 << iota 170 BPF_F_NO_COMMON_LRU 171 BPF_F_NUMA_NODE 172 BPF_F_RDONLY 173 BPF_F_WRONLY 174 BPF_F_STACK_BUILD_ID 175 BPF_F_ZERO_SEED 176 BPF_F_RDONLY_PROG 177 BPF_F_WRONLY_PROG 178 BPF_F_CLONE 179 BPF_F_MMAPABLE 180 BPF_F_PRESERVE_ELEMS 181 BPF_F_INNER_MAP 182 BPF_F_LINK 183 BPF_F_PATH_FD 184 ) 185 186 // Flags used by bpf_mprog. 187 const ( 188 BPF_F_REPLACE = 1 << (iota + 2) 189 BPF_F_BEFORE 190 BPF_F_AFTER 191 BPF_F_ID 192 BPF_F_LINK_MPROG = 1 << 13 // aka BPF_F_LINK 193 ) 194 195 // wrappedErrno wraps syscall.Errno to prevent direct comparisons with 196 // syscall.E* or unix.E* constants. 197 // 198 // You should never export an error of this type. 199 type wrappedErrno struct { 200 syscall.Errno 201 } 202 203 func (we wrappedErrno) Unwrap() error { 204 return we.Errno 205 } 206 207 func (we wrappedErrno) Error() string { 208 if we.Errno == ENOTSUPP { 209 return "operation not supported" 210 } 211 return we.Errno.Error() 212 } 213 214 type syscallError struct { 215 error 216 errno syscall.Errno 217 } 218 219 func Error(err error, errno syscall.Errno) error { 220 return &syscallError{err, errno} 221 } 222 223 func (se *syscallError) Is(target error) bool { 224 return target == se.error 225 } 226 227 func (se *syscallError) Unwrap() error { 228 return se.errno 229 }