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