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  })