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  }