github.com/cilium/ebpf@v0.10.0/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 var 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 var _ Info = (*BtfInfo)(nil) 75 76 func (i *BtfInfo) info() (unsafe.Pointer, uint32) { 77 return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i)) 78 } 79 80 // ObjInfo retrieves information about a BPF Fd. 81 // 82 // info may be one of MapInfo, ProgInfo, LinkInfo and BtfInfo. 83 func ObjInfo(fd *FD, info Info) error { 84 ptr, len := info.info() 85 err := ObjGetInfoByFd(&ObjGetInfoByFdAttr{ 86 BpfFd: fd.Uint(), 87 InfoLen: len, 88 Info: NewPointer(ptr), 89 }) 90 runtime.KeepAlive(fd) 91 return err 92 } 93 94 // BPFObjName is a null-terminated string made up of 95 // 'A-Za-z0-9_' characters. 96 type ObjName [unix.BPF_OBJ_NAME_LEN]byte 97 98 // NewObjName truncates the result if it is too long. 99 func NewObjName(name string) ObjName { 100 var result ObjName 101 copy(result[:unix.BPF_OBJ_NAME_LEN-1], name) 102 return result 103 } 104 105 // LogLevel controls the verbosity of the kernel's eBPF program verifier. 106 type LogLevel uint32 107 108 const ( 109 BPF_LOG_LEVEL1 LogLevel = 1 << iota 110 BPF_LOG_LEVEL2 111 BPF_LOG_STATS 112 ) 113 114 // LinkID uniquely identifies a bpf_link. 115 type LinkID uint32 116 117 // BTFID uniquely identifies a BTF blob loaded into the kernel. 118 type BTFID uint32 119 120 // MapFlags control map behaviour. 121 type MapFlags uint32 122 123 //go:generate stringer -type MapFlags 124 125 const ( 126 BPF_F_NO_PREALLOC MapFlags = 1 << iota 127 BPF_F_NO_COMMON_LRU 128 BPF_F_NUMA_NODE 129 BPF_F_RDONLY 130 BPF_F_WRONLY 131 BPF_F_STACK_BUILD_ID 132 BPF_F_ZERO_SEED 133 BPF_F_RDONLY_PROG 134 BPF_F_WRONLY_PROG 135 BPF_F_CLONE 136 BPF_F_MMAPABLE 137 BPF_F_PRESERVE_ELEMS 138 BPF_F_INNER_MAP 139 ) 140 141 // wrappedErrno wraps syscall.Errno to prevent direct comparisons with 142 // syscall.E* or unix.E* constants. 143 // 144 // You should never export an error of this type. 145 type wrappedErrno struct { 146 syscall.Errno 147 } 148 149 func (we wrappedErrno) Unwrap() error { 150 return we.Errno 151 } 152 153 func (we wrappedErrno) Error() string { 154 if we.Errno == ENOTSUPP { 155 return "operation not supported" 156 } 157 return we.Errno.Error() 158 } 159 160 type syscallError struct { 161 error 162 errno syscall.Errno 163 } 164 165 func Error(err error, errno syscall.Errno) error { 166 return &syscallError{err, errno} 167 } 168 169 func (se *syscallError) Is(target error) bool { 170 return target == se.error 171 } 172 173 func (se *syscallError) Unwrap() error { 174 return se.errno 175 }