syscalls.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package link
  2. import (
  3. "errors"
  4. "unsafe"
  5. "github.com/cilium/ebpf"
  6. "github.com/cilium/ebpf/asm"
  7. "github.com/cilium/ebpf/internal"
  8. "github.com/cilium/ebpf/internal/unix"
  9. )
  10. // Type is the kind of link.
  11. type Type uint32
  12. // Valid link types.
  13. //
  14. // Equivalent to enum bpf_link_type.
  15. const (
  16. UnspecifiedType Type = iota
  17. RawTracepointType
  18. TracingType
  19. CgroupType
  20. IterType
  21. NetNsType
  22. XDPType
  23. )
  24. var haveProgAttach = internal.FeatureTest("BPF_PROG_ATTACH", "4.10", func() error {
  25. prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
  26. Type: ebpf.CGroupSKB,
  27. AttachType: ebpf.AttachCGroupInetIngress,
  28. License: "MIT",
  29. Instructions: asm.Instructions{
  30. asm.Mov.Imm(asm.R0, 0),
  31. asm.Return(),
  32. },
  33. })
  34. if err != nil {
  35. return internal.ErrNotSupported
  36. }
  37. // BPF_PROG_ATTACH was introduced at the same time as CGgroupSKB,
  38. // so being able to load the program is enough to infer that we
  39. // have the syscall.
  40. prog.Close()
  41. return nil
  42. })
  43. var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replacement", "5.5", func() error {
  44. if err := haveProgAttach(); err != nil {
  45. return err
  46. }
  47. prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
  48. Type: ebpf.CGroupSKB,
  49. AttachType: ebpf.AttachCGroupInetIngress,
  50. License: "MIT",
  51. Instructions: asm.Instructions{
  52. asm.Mov.Imm(asm.R0, 0),
  53. asm.Return(),
  54. },
  55. })
  56. if err != nil {
  57. return internal.ErrNotSupported
  58. }
  59. defer prog.Close()
  60. // We know that we have BPF_PROG_ATTACH since we can load CGroupSKB programs.
  61. // If passing BPF_F_REPLACE gives us EINVAL we know that the feature isn't
  62. // present.
  63. attr := internal.BPFProgAttachAttr{
  64. // We rely on this being checked after attachFlags.
  65. TargetFd: ^uint32(0),
  66. AttachBpfFd: uint32(prog.FD()),
  67. AttachType: uint32(ebpf.AttachCGroupInetIngress),
  68. AttachFlags: uint32(flagReplace),
  69. }
  70. err = internal.BPFProgAttach(&attr)
  71. if errors.Is(err, unix.EINVAL) {
  72. return internal.ErrNotSupported
  73. }
  74. if errors.Is(err, unix.EBADF) {
  75. return nil
  76. }
  77. return err
  78. })
  79. type bpfLinkCreateAttr struct {
  80. progFd uint32
  81. targetFd uint32
  82. attachType ebpf.AttachType
  83. flags uint32
  84. targetBTFID uint32
  85. }
  86. func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {
  87. ptr, err := internal.BPF(internal.BPF_LINK_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  88. if err != nil {
  89. return nil, err
  90. }
  91. return internal.NewFD(uint32(ptr)), nil
  92. }
  93. type bpfLinkCreateIterAttr struct {
  94. prog_fd uint32
  95. target_fd uint32
  96. attach_type ebpf.AttachType
  97. flags uint32
  98. iter_info internal.Pointer
  99. iter_info_len uint32
  100. }
  101. func bpfLinkCreateIter(attr *bpfLinkCreateIterAttr) (*internal.FD, error) {
  102. ptr, err := internal.BPF(internal.BPF_LINK_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  103. if err != nil {
  104. return nil, err
  105. }
  106. return internal.NewFD(uint32(ptr)), nil
  107. }
  108. type bpfLinkUpdateAttr struct {
  109. linkFd uint32
  110. newProgFd uint32
  111. flags uint32
  112. oldProgFd uint32
  113. }
  114. func bpfLinkUpdate(attr *bpfLinkUpdateAttr) error {
  115. _, err := internal.BPF(internal.BPF_LINK_UPDATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  116. return err
  117. }
  118. var haveBPFLink = internal.FeatureTest("bpf_link", "5.7", func() error {
  119. prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
  120. Type: ebpf.CGroupSKB,
  121. AttachType: ebpf.AttachCGroupInetIngress,
  122. License: "MIT",
  123. Instructions: asm.Instructions{
  124. asm.Mov.Imm(asm.R0, 0),
  125. asm.Return(),
  126. },
  127. })
  128. if err != nil {
  129. return internal.ErrNotSupported
  130. }
  131. defer prog.Close()
  132. attr := bpfLinkCreateAttr{
  133. // This is a hopefully invalid file descriptor, which triggers EBADF.
  134. targetFd: ^uint32(0),
  135. progFd: uint32(prog.FD()),
  136. attachType: ebpf.AttachCGroupInetIngress,
  137. }
  138. _, err = bpfLinkCreate(&attr)
  139. if errors.Is(err, unix.EINVAL) {
  140. return internal.ErrNotSupported
  141. }
  142. if errors.Is(err, unix.EBADF) {
  143. return nil
  144. }
  145. return err
  146. })
  147. type bpfIterCreateAttr struct {
  148. linkFd uint32
  149. flags uint32
  150. }
  151. func bpfIterCreate(attr *bpfIterCreateAttr) (*internal.FD, error) {
  152. ptr, err := internal.BPF(internal.BPF_ITER_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  153. if err == nil {
  154. return internal.NewFD(uint32(ptr)), nil
  155. }
  156. return nil, err
  157. }
  158. type bpfRawTracepointOpenAttr struct {
  159. name internal.Pointer
  160. fd uint32
  161. _ uint32
  162. }
  163. func bpfRawTracepointOpen(attr *bpfRawTracepointOpenAttr) (*internal.FD, error) {
  164. ptr, err := internal.BPF(internal.BPF_RAW_TRACEPOINT_OPEN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  165. if err == nil {
  166. return internal.NewFD(uint32(ptr)), nil
  167. }
  168. return nil, err
  169. }