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