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  }