github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/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 TCXType = sys.BPF_LINK_TYPE_TCX 28 UprobeMultiType = sys.BPF_LINK_TYPE_UPROBE_MULTI 29 NetfilterType = sys.BPF_LINK_TYPE_NETFILTER 30 NetkitType = sys.BPF_LINK_TYPE_NETKIT 31 ) 32 33 var haveProgAttach = internal.NewFeatureTest("BPF_PROG_ATTACH", "4.10", func() error { 34 prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ 35 Type: ebpf.CGroupSKB, 36 License: "MIT", 37 Instructions: asm.Instructions{ 38 asm.Mov.Imm(asm.R0, 0), 39 asm.Return(), 40 }, 41 }) 42 if err != nil { 43 return internal.ErrNotSupported 44 } 45 46 // BPF_PROG_ATTACH was introduced at the same time as CGgroupSKB, 47 // so being able to load the program is enough to infer that we 48 // have the syscall. 49 prog.Close() 50 return nil 51 }) 52 53 var haveProgAttachReplace = internal.NewFeatureTest("BPF_PROG_ATTACH atomic replacement of MULTI progs", "5.5", func() error { 54 if err := haveProgAttach(); err != nil { 55 return err 56 } 57 58 prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ 59 Type: ebpf.CGroupSKB, 60 AttachType: ebpf.AttachCGroupInetIngress, 61 License: "MIT", 62 Instructions: asm.Instructions{ 63 asm.Mov.Imm(asm.R0, 0), 64 asm.Return(), 65 }, 66 }) 67 68 if err != nil { 69 return internal.ErrNotSupported 70 } 71 72 defer prog.Close() 73 74 // We know that we have BPF_PROG_ATTACH since we can load CGroupSKB programs. 75 // If passing BPF_F_REPLACE gives us EINVAL we know that the feature isn't 76 // present. 77 attr := sys.ProgAttachAttr{ 78 // We rely on this being checked after attachFlags. 79 TargetFdOrIfindex: ^uint32(0), 80 AttachBpfFd: uint32(prog.FD()), 81 AttachType: uint32(ebpf.AttachCGroupInetIngress), 82 AttachFlags: uint32(flagReplace), 83 } 84 85 err = sys.ProgAttach(&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 95 var haveBPFLink = internal.NewFeatureTest("bpf_link", "5.7", func() error { 96 attr := sys.LinkCreateAttr{ 97 // This is a hopefully invalid file descriptor, which triggers EBADF. 98 TargetFd: ^uint32(0), 99 ProgFd: ^uint32(0), 100 AttachType: sys.AttachType(ebpf.AttachCGroupInetIngress), 101 } 102 _, err := sys.LinkCreate(&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 }) 111 112 var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", "4.15", func() error { 113 attr := sys.ProgQueryAttr{ 114 // We rely on this being checked during the syscall. 115 // With an otherwise correct payload we expect EBADF here 116 // as an indication that the feature is present. 117 TargetFdOrIfindex: ^uint32(0), 118 AttachType: sys.AttachType(ebpf.AttachCGroupInetIngress), 119 } 120 121 err := sys.ProgQuery(&attr) 122 123 if errors.Is(err, unix.EBADF) { 124 return nil 125 } 126 if err != nil { 127 return ErrNotSupported 128 } 129 return errors.New("syscall succeeded unexpectedly") 130 }) 131 132 var haveTCX = internal.NewFeatureTest("tcx", "6.6", func() error { 133 prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ 134 Type: ebpf.SchedCLS, 135 License: "MIT", 136 Instructions: asm.Instructions{ 137 asm.Mov.Imm(asm.R0, 0), 138 asm.Return(), 139 }, 140 }) 141 142 if err != nil { 143 return internal.ErrNotSupported 144 } 145 146 defer prog.Close() 147 attr := sys.LinkCreateTcxAttr{ 148 // We rely on this being checked during the syscall. 149 // With an otherwise correct payload we expect ENODEV here 150 // as an indication that the feature is present. 151 TargetIfindex: ^uint32(0), 152 ProgFd: uint32(prog.FD()), 153 AttachType: sys.AttachType(ebpf.AttachTCXIngress), 154 } 155 156 _, err = sys.LinkCreateTcx(&attr) 157 158 if errors.Is(err, unix.ENODEV) { 159 return nil 160 } 161 if err != nil { 162 return ErrNotSupported 163 } 164 return errors.New("syscall succeeded unexpectedly") 165 }) 166 167 var haveNetkit = internal.NewFeatureTest("netkit", "6.7", func() error { 168 prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ 169 Type: ebpf.SchedCLS, 170 License: "MIT", 171 Instructions: asm.Instructions{ 172 asm.Mov.Imm(asm.R0, 0), 173 asm.Return(), 174 }, 175 }) 176 177 if err != nil { 178 return internal.ErrNotSupported 179 } 180 181 defer prog.Close() 182 attr := sys.LinkCreateNetkitAttr{ 183 // We rely on this being checked during the syscall. 184 // With an otherwise correct payload we expect ENODEV here 185 // as an indication that the feature is present. 186 TargetIfindex: ^uint32(0), 187 ProgFd: uint32(prog.FD()), 188 AttachType: sys.AttachType(ebpf.AttachNetkitPrimary), 189 } 190 191 _, err = sys.LinkCreateNetkit(&attr) 192 193 if errors.Is(err, unix.ENODEV) { 194 return nil 195 } 196 if err != nil { 197 return ErrNotSupported 198 } 199 return errors.New("syscall succeeded unexpectedly") 200 })