syscall.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package sys
  2. import (
  3. "runtime"
  4. "syscall"
  5. "unsafe"
  6. "github.com/cilium/ebpf/internal/unix"
  7. )
  8. // ENOTSUPP is a Linux internal error code that has leaked into UAPI.
  9. //
  10. // It is not the same as ENOTSUP or EOPNOTSUPP.
  11. var ENOTSUPP = syscall.Errno(524)
  12. // BPF wraps SYS_BPF.
  13. //
  14. // Any pointers contained in attr must use the Pointer type from this package.
  15. func BPF(cmd Cmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
  16. // Prevent the Go profiler from repeatedly interrupting the verifier,
  17. // which could otherwise lead to a livelock due to receiving EAGAIN.
  18. if cmd == BPF_PROG_LOAD || cmd == BPF_PROG_RUN {
  19. maskProfilerSignal()
  20. defer unmaskProfilerSignal()
  21. }
  22. for {
  23. r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
  24. runtime.KeepAlive(attr)
  25. // As of ~4.20 the verifier can be interrupted by a signal,
  26. // and returns EAGAIN in that case.
  27. if errNo == unix.EAGAIN && cmd == BPF_PROG_LOAD {
  28. continue
  29. }
  30. var err error
  31. if errNo != 0 {
  32. err = wrappedErrno{errNo}
  33. }
  34. return r1, err
  35. }
  36. }
  37. // Info is implemented by all structs that can be passed to the ObjInfo syscall.
  38. //
  39. // MapInfo
  40. // ProgInfo
  41. // LinkInfo
  42. // BtfInfo
  43. type Info interface {
  44. info() (unsafe.Pointer, uint32)
  45. }
  46. var _ Info = (*MapInfo)(nil)
  47. func (i *MapInfo) info() (unsafe.Pointer, uint32) {
  48. return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i))
  49. }
  50. var _ Info = (*ProgInfo)(nil)
  51. func (i *ProgInfo) info() (unsafe.Pointer, uint32) {
  52. return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i))
  53. }
  54. var _ Info = (*LinkInfo)(nil)
  55. func (i *LinkInfo) info() (unsafe.Pointer, uint32) {
  56. return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i))
  57. }
  58. var _ Info = (*BtfInfo)(nil)
  59. func (i *BtfInfo) info() (unsafe.Pointer, uint32) {
  60. return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i))
  61. }
  62. // ObjInfo retrieves information about a BPF Fd.
  63. //
  64. // info may be one of MapInfo, ProgInfo, LinkInfo and BtfInfo.
  65. func ObjInfo(fd *FD, info Info) error {
  66. ptr, len := info.info()
  67. err := ObjGetInfoByFd(&ObjGetInfoByFdAttr{
  68. BpfFd: fd.Uint(),
  69. InfoLen: len,
  70. Info: NewPointer(ptr),
  71. })
  72. runtime.KeepAlive(fd)
  73. return err
  74. }
  75. // BPFObjName is a null-terminated string made up of
  76. // 'A-Za-z0-9_' characters.
  77. type ObjName [unix.BPF_OBJ_NAME_LEN]byte
  78. // NewObjName truncates the result if it is too long.
  79. func NewObjName(name string) ObjName {
  80. var result ObjName
  81. copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
  82. return result
  83. }
  84. // LogLevel controls the verbosity of the kernel's eBPF program verifier.
  85. type LogLevel uint32
  86. const (
  87. BPF_LOG_LEVEL1 LogLevel = 1 << iota
  88. BPF_LOG_LEVEL2
  89. BPF_LOG_STATS
  90. )
  91. // LinkID uniquely identifies a bpf_link.
  92. type LinkID uint32
  93. // BTFID uniquely identifies a BTF blob loaded into the kernel.
  94. type BTFID uint32
  95. // TypeID identifies a type in a BTF blob.
  96. type TypeID uint32
  97. // MapFlags control map behaviour.
  98. type MapFlags uint32
  99. //go:generate stringer -type MapFlags
  100. const (
  101. BPF_F_NO_PREALLOC MapFlags = 1 << iota
  102. BPF_F_NO_COMMON_LRU
  103. BPF_F_NUMA_NODE
  104. BPF_F_RDONLY
  105. BPF_F_WRONLY
  106. BPF_F_STACK_BUILD_ID
  107. BPF_F_ZERO_SEED
  108. BPF_F_RDONLY_PROG
  109. BPF_F_WRONLY_PROG
  110. BPF_F_CLONE
  111. BPF_F_MMAPABLE
  112. BPF_F_PRESERVE_ELEMS
  113. BPF_F_INNER_MAP
  114. )
  115. // wrappedErrno wraps syscall.Errno to prevent direct comparisons with
  116. // syscall.E* or unix.E* constants.
  117. //
  118. // You should never export an error of this type.
  119. type wrappedErrno struct {
  120. syscall.Errno
  121. }
  122. func (we wrappedErrno) Unwrap() error {
  123. return we.Errno
  124. }
  125. func (we wrappedErrno) Error() string {
  126. if we.Errno == ENOTSUPP {
  127. return "operation not supported"
  128. }
  129. return we.Errno.Error()
  130. }
  131. type syscallError struct {
  132. error
  133. errno syscall.Errno
  134. }
  135. func Error(err error, errno syscall.Errno) error {
  136. return &syscallError{err, errno}
  137. }
  138. func (se *syscallError) Is(target error) bool {
  139. return target == se.error
  140. }
  141. func (se *syscallError) Unwrap() error {
  142. return se.errno
  143. }