github.com/cilium/cilium@v1.16.2/pkg/datapath/linux/probes/attach_cgroup.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package probes
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"sync"
    10  
    11  	"github.com/cilium/ebpf"
    12  	"github.com/cilium/ebpf/asm"
    13  	"github.com/cilium/ebpf/link"
    14  	"golang.org/x/sys/unix"
    15  )
    16  
    17  // HaveAttachCgroup returns nil if the kernel is compiled with
    18  // CONFIG_CGROUP_BPF.
    19  //
    20  // It's only an approximation and doesn't execute a successful cgroup attachment
    21  // under the hood. If any unexpected errors are encountered, the original error
    22  // is returned.
    23  func HaveAttachCgroup() error {
    24  	attachCgroupOnce.Do(func() {
    25  		attachCgroupResult = haveAttachCgroup()
    26  	})
    27  
    28  	return attachCgroupResult
    29  }
    30  
    31  func haveAttachCgroup() error {
    32  	// Load known-good program supported by the earliest kernels with cgroup
    33  	// support.
    34  	spec := &ebpf.ProgramSpec{
    35  		Type:       ebpf.CGroupSKB,
    36  		AttachType: ebpf.AttachCGroupInetIngress,
    37  		Instructions: asm.Instructions{
    38  			asm.LoadImm(asm.R0, 0, asm.DWord),
    39  			asm.Return(),
    40  		},
    41  	}
    42  
    43  	p, err := ebpf.NewProgramWithOptions(spec, ebpf.ProgramOptions{
    44  		LogDisabled: true,
    45  	})
    46  	if err != nil {
    47  		return fmt.Errorf("create cgroup program: %w: %w", err, ebpf.ErrNotSupported)
    48  	}
    49  	defer p.Close()
    50  
    51  	// Attaching to a non-cgroup node should result in EBADF when creating the
    52  	// link, compared to EINVAL if the kernel does not support or was compiled
    53  	// without CONFIG_CGROUP_BPF.
    54  	_, err = link.AttachCgroup(link.CgroupOptions{Path: "/dev/null", Program: p, Attach: spec.AttachType})
    55  	if errors.Is(err, unix.EBADF) {
    56  		// The kernel checked the given file descriptor from within the cgroup prog
    57  		// attach handler. Assume it supports attaching cgroup progs.
    58  		return nil
    59  	}
    60  	if err != nil {
    61  		// Preserve the original error in the error string. Needs Go 1.20.
    62  		return fmt.Errorf("link cgroup program to /dev/null: %w: %w", err, ebpf.ErrNotSupported)
    63  	}
    64  
    65  	return errors.New("attaching prog to /dev/null did not result in error")
    66  }
    67  
    68  var attachCgroupOnce sync.Once
    69  var attachCgroupResult error