syscall.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. package internal
  2. import (
  3. "errors"
  4. "fmt"
  5. "path/filepath"
  6. "runtime"
  7. "syscall"
  8. "unsafe"
  9. "github.com/cilium/ebpf/internal/unix"
  10. )
  11. //go:generate stringer -output syscall_string.go -type=BPFCmd
  12. // BPFCmd identifies a subcommand of the bpf syscall.
  13. type BPFCmd int
  14. // Well known BPF commands.
  15. const (
  16. BPF_MAP_CREATE BPFCmd = iota
  17. BPF_MAP_LOOKUP_ELEM
  18. BPF_MAP_UPDATE_ELEM
  19. BPF_MAP_DELETE_ELEM
  20. BPF_MAP_GET_NEXT_KEY
  21. BPF_PROG_LOAD
  22. BPF_OBJ_PIN
  23. BPF_OBJ_GET
  24. BPF_PROG_ATTACH
  25. BPF_PROG_DETACH
  26. BPF_PROG_TEST_RUN
  27. BPF_PROG_GET_NEXT_ID
  28. BPF_MAP_GET_NEXT_ID
  29. BPF_PROG_GET_FD_BY_ID
  30. BPF_MAP_GET_FD_BY_ID
  31. BPF_OBJ_GET_INFO_BY_FD
  32. BPF_PROG_QUERY
  33. BPF_RAW_TRACEPOINT_OPEN
  34. BPF_BTF_LOAD
  35. BPF_BTF_GET_FD_BY_ID
  36. BPF_TASK_FD_QUERY
  37. BPF_MAP_LOOKUP_AND_DELETE_ELEM
  38. BPF_MAP_FREEZE
  39. BPF_BTF_GET_NEXT_ID
  40. BPF_MAP_LOOKUP_BATCH
  41. BPF_MAP_LOOKUP_AND_DELETE_BATCH
  42. BPF_MAP_UPDATE_BATCH
  43. BPF_MAP_DELETE_BATCH
  44. BPF_LINK_CREATE
  45. BPF_LINK_UPDATE
  46. BPF_LINK_GET_FD_BY_ID
  47. BPF_LINK_GET_NEXT_ID
  48. BPF_ENABLE_STATS
  49. BPF_ITER_CREATE
  50. )
  51. // BPF wraps SYS_BPF.
  52. //
  53. // Any pointers contained in attr must use the Pointer type from this package.
  54. func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
  55. r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
  56. runtime.KeepAlive(attr)
  57. var err error
  58. if errNo != 0 {
  59. err = wrappedErrno{errNo}
  60. }
  61. return r1, err
  62. }
  63. type BPFProgLoadAttr struct {
  64. ProgType uint32
  65. InsCount uint32
  66. Instructions Pointer
  67. License Pointer
  68. LogLevel uint32
  69. LogSize uint32
  70. LogBuf Pointer
  71. KernelVersion uint32 // since 4.1 2541517c32be
  72. ProgFlags uint32 // since 4.11 e07b98d9bffe
  73. ProgName BPFObjName // since 4.15 067cae47771c
  74. ProgIfIndex uint32 // since 4.15 1f6f4cb7ba21
  75. ExpectedAttachType uint32 // since 4.17 5e43f899b03a
  76. ProgBTFFd uint32
  77. FuncInfoRecSize uint32
  78. FuncInfo Pointer
  79. FuncInfoCnt uint32
  80. LineInfoRecSize uint32
  81. LineInfo Pointer
  82. LineInfoCnt uint32
  83. AttachBTFID uint32
  84. AttachProgFd uint32
  85. }
  86. // BPFProgLoad wraps BPF_PROG_LOAD.
  87. func BPFProgLoad(attr *BPFProgLoadAttr) (*FD, error) {
  88. for {
  89. fd, err := BPF(BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  90. // As of ~4.20 the verifier can be interrupted by a signal,
  91. // and returns EAGAIN in that case.
  92. if errors.Is(err, unix.EAGAIN) {
  93. continue
  94. }
  95. if err != nil {
  96. return nil, err
  97. }
  98. return NewFD(uint32(fd)), nil
  99. }
  100. }
  101. type BPFProgAttachAttr struct {
  102. TargetFd uint32
  103. AttachBpfFd uint32
  104. AttachType uint32
  105. AttachFlags uint32
  106. ReplaceBpfFd uint32
  107. }
  108. func BPFProgAttach(attr *BPFProgAttachAttr) error {
  109. _, err := BPF(BPF_PROG_ATTACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  110. return err
  111. }
  112. type BPFProgDetachAttr struct {
  113. TargetFd uint32
  114. AttachBpfFd uint32
  115. AttachType uint32
  116. }
  117. func BPFProgDetach(attr *BPFProgDetachAttr) error {
  118. _, err := BPF(BPF_PROG_DETACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  119. return err
  120. }
  121. type BPFEnableStatsAttr struct {
  122. StatsType uint32
  123. }
  124. func BPFEnableStats(attr *BPFEnableStatsAttr) (*FD, error) {
  125. ptr, err := BPF(BPF_ENABLE_STATS, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  126. if err != nil {
  127. return nil, fmt.Errorf("enable stats: %w", err)
  128. }
  129. return NewFD(uint32(ptr)), nil
  130. }
  131. type bpfObjAttr struct {
  132. fileName Pointer
  133. fd uint32
  134. fileFlags uint32
  135. }
  136. const bpfFSType = 0xcafe4a11
  137. // BPFObjPin wraps BPF_OBJ_PIN.
  138. func BPFObjPin(fileName string, fd *FD) error {
  139. dirName := filepath.Dir(fileName)
  140. var statfs unix.Statfs_t
  141. if err := unix.Statfs(dirName, &statfs); err != nil {
  142. return err
  143. }
  144. if uint64(statfs.Type) != bpfFSType {
  145. return fmt.Errorf("%s is not on a bpf filesystem", fileName)
  146. }
  147. value, err := fd.Value()
  148. if err != nil {
  149. return err
  150. }
  151. attr := bpfObjAttr{
  152. fileName: NewStringPointer(fileName),
  153. fd: value,
  154. }
  155. _, err = BPF(BPF_OBJ_PIN, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
  156. if err != nil {
  157. return fmt.Errorf("pin object %s: %w", fileName, err)
  158. }
  159. return nil
  160. }
  161. // BPFObjGet wraps BPF_OBJ_GET.
  162. func BPFObjGet(fileName string, flags uint32) (*FD, error) {
  163. attr := bpfObjAttr{
  164. fileName: NewStringPointer(fileName),
  165. fileFlags: flags,
  166. }
  167. ptr, err := BPF(BPF_OBJ_GET, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
  168. if err != nil {
  169. return nil, fmt.Errorf("get object %s: %w", fileName, err)
  170. }
  171. return NewFD(uint32(ptr)), nil
  172. }
  173. type bpfObjGetInfoByFDAttr struct {
  174. fd uint32
  175. infoLen uint32
  176. info Pointer
  177. }
  178. // BPFObjGetInfoByFD wraps BPF_OBJ_GET_INFO_BY_FD.
  179. //
  180. // Available from 4.13.
  181. func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error {
  182. value, err := fd.Value()
  183. if err != nil {
  184. return err
  185. }
  186. attr := bpfObjGetInfoByFDAttr{
  187. fd: value,
  188. infoLen: uint32(size),
  189. info: NewPointer(info),
  190. }
  191. _, err = BPF(BPF_OBJ_GET_INFO_BY_FD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
  192. if err != nil {
  193. return fmt.Errorf("fd %v: %w", fd, err)
  194. }
  195. return nil
  196. }
  197. type bpfGetFDByIDAttr struct {
  198. id uint32
  199. next uint32
  200. }
  201. // BPFObjGetInfoByFD wraps BPF_*_GET_FD_BY_ID.
  202. //
  203. // Available from 4.13.
  204. func BPFObjGetFDByID(cmd BPFCmd, id uint32) (*FD, error) {
  205. attr := bpfGetFDByIDAttr{
  206. id: id,
  207. }
  208. ptr, err := BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
  209. return NewFD(uint32(ptr)), err
  210. }
  211. // BPFObjName is a null-terminated string made up of
  212. // 'A-Za-z0-9_' characters.
  213. type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte
  214. // NewBPFObjName truncates the result if it is too long.
  215. func NewBPFObjName(name string) BPFObjName {
  216. var result BPFObjName
  217. copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
  218. return result
  219. }
  220. type BPFMapCreateAttr struct {
  221. MapType uint32
  222. KeySize uint32
  223. ValueSize uint32
  224. MaxEntries uint32
  225. Flags uint32
  226. InnerMapFd uint32 // since 4.12 56f668dfe00d
  227. NumaNode uint32 // since 4.14 96eabe7a40aa
  228. MapName BPFObjName // since 4.15 ad5b177bd73f
  229. MapIfIndex uint32
  230. BTFFd uint32
  231. BTFKeyTypeID uint32
  232. BTFValueTypeID uint32
  233. }
  234. func BPFMapCreate(attr *BPFMapCreateAttr) (*FD, error) {
  235. fd, err := BPF(BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  236. if err != nil {
  237. return nil, err
  238. }
  239. return NewFD(uint32(fd)), nil
  240. }
  241. // wrappedErrno wraps syscall.Errno to prevent direct comparisons with
  242. // syscall.E* or unix.E* constants.
  243. //
  244. // You should never export an error of this type.
  245. type wrappedErrno struct {
  246. syscall.Errno
  247. }
  248. func (we wrappedErrno) Unwrap() error {
  249. return we.Errno
  250. }
  251. type syscallError struct {
  252. error
  253. errno syscall.Errno
  254. }
  255. func SyscallError(err error, errno syscall.Errno) error {
  256. return &syscallError{err, errno}
  257. }
  258. func (se *syscallError) Is(target error) bool {
  259. return target == se.error
  260. }
  261. func (se *syscallError) Unwrap() error {
  262. return se.errno
  263. }