syscalls.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package link
  2. import (
  3. "errors"
  4. "github.com/cilium/ebpf"
  5. "github.com/cilium/ebpf/asm"
  6. "github.com/cilium/ebpf/internal"
  7. "github.com/cilium/ebpf/internal/sys"
  8. "github.com/cilium/ebpf/internal/unix"
  9. )
  10. // Type is the kind of link.
  11. type Type = sys.LinkType
  12. // Valid link types.
  13. const (
  14. UnspecifiedType = sys.BPF_LINK_TYPE_UNSPEC
  15. RawTracepointType = sys.BPF_LINK_TYPE_RAW_TRACEPOINT
  16. TracingType = sys.BPF_LINK_TYPE_TRACING
  17. CgroupType = sys.BPF_LINK_TYPE_CGROUP
  18. IterType = sys.BPF_LINK_TYPE_ITER
  19. NetNsType = sys.BPF_LINK_TYPE_NETNS
  20. XDPType = sys.BPF_LINK_TYPE_XDP
  21. PerfEventType = sys.BPF_LINK_TYPE_PERF_EVENT
  22. KprobeMultiType = sys.BPF_LINK_TYPE_KPROBE_MULTI
  23. )
  24. var haveProgAttach = internal.NewFeatureTest("BPF_PROG_ATTACH", "4.10", func() error {
  25. prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
  26. Type: ebpf.CGroupSKB,
  27. License: "MIT",
  28. Instructions: asm.Instructions{
  29. asm.Mov.Imm(asm.R0, 0),
  30. asm.Return(),
  31. },
  32. })
  33. if err != nil {
  34. return internal.ErrNotSupported
  35. }
  36. // BPF_PROG_ATTACH was introduced at the same time as CGgroupSKB,
  37. // so being able to load the program is enough to infer that we
  38. // have the syscall.
  39. prog.Close()
  40. return nil
  41. })
  42. var haveProgAttachReplace = internal.NewFeatureTest("BPF_PROG_ATTACH atomic replacement of MULTI progs", "5.5", func() error {
  43. if err := haveProgAttach(); err != nil {
  44. return err
  45. }
  46. prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
  47. Type: ebpf.CGroupSKB,
  48. AttachType: ebpf.AttachCGroupInetIngress,
  49. License: "MIT",
  50. Instructions: asm.Instructions{
  51. asm.Mov.Imm(asm.R0, 0),
  52. asm.Return(),
  53. },
  54. })
  55. if err != nil {
  56. return internal.ErrNotSupported
  57. }
  58. defer prog.Close()
  59. // We know that we have BPF_PROG_ATTACH since we can load CGroupSKB programs.
  60. // If passing BPF_F_REPLACE gives us EINVAL we know that the feature isn't
  61. // present.
  62. attr := sys.ProgAttachAttr{
  63. // We rely on this being checked after attachFlags.
  64. TargetFd: ^uint32(0),
  65. AttachBpfFd: uint32(prog.FD()),
  66. AttachType: uint32(ebpf.AttachCGroupInetIngress),
  67. AttachFlags: uint32(flagReplace),
  68. }
  69. err = sys.ProgAttach(&attr)
  70. if errors.Is(err, unix.EINVAL) {
  71. return internal.ErrNotSupported
  72. }
  73. if errors.Is(err, unix.EBADF) {
  74. return nil
  75. }
  76. return err
  77. })
  78. var haveBPFLink = internal.NewFeatureTest("bpf_link", "5.7", func() error {
  79. attr := sys.LinkCreateAttr{
  80. // This is a hopefully invalid file descriptor, which triggers EBADF.
  81. TargetFd: ^uint32(0),
  82. ProgFd: ^uint32(0),
  83. AttachType: sys.AttachType(ebpf.AttachCGroupInetIngress),
  84. }
  85. _, err := sys.LinkCreate(&attr)
  86. if errors.Is(err, unix.EINVAL) {
  87. return internal.ErrNotSupported
  88. }
  89. if errors.Is(err, unix.EBADF) {
  90. return nil
  91. }
  92. return err
  93. })
  94. var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", "4.15", func() error {
  95. attr := sys.ProgQueryAttr{
  96. // We rely on this being checked during the syscall.
  97. // With an otherwise correct payload we expect EBADF here
  98. // as an indication that the feature is present.
  99. TargetFd: ^uint32(0),
  100. AttachType: sys.AttachType(ebpf.AttachCGroupInetIngress),
  101. }
  102. err := sys.ProgQuery(&attr)
  103. if errors.Is(err, unix.EINVAL) {
  104. return internal.ErrNotSupported
  105. }
  106. if errors.Is(err, unix.EBADF) {
  107. return nil
  108. }
  109. return err
  110. })