Ver código fonte

vendor: github.com/containerd/cgroups v1.0.1

full diff: https://github.com/containerd/cgroups/compare/0b889c03f102012f1d93a97ddd3ef71cd6f4f510...v1.0.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 4 anos atrás
pai
commit
0691addf6a

+ 1 - 1
vendor.conf

@@ -135,7 +135,7 @@ google.golang.org/genproto                          3f1135a288c9a07e340ae8ba4cc6
 github.com/containerd/containerd                    19ee068f93c91f7b9b2a858457f1af2cabc7bc06 # master (v1.5.0-dev)
 github.com/containerd/fifo                          650e8a8a179d040123db61f016cb133143e7a581 # v1.0.0
 github.com/containerd/continuity                    bce1c3f9669b6f3e7f6656ee715b0b4d75fa64a6 # v0.1.0
-github.com/containerd/cgroups                       0b889c03f102012f1d93a97ddd3ef71cd6f4f510
+github.com/containerd/cgroups                       b9de8a2212026c07cec67baf3323f1fc0121e048 # v1.0.1
 github.com/containerd/console                       2f1e3d2b6afd18e8b2077816c711205a0b4d8769 # v1.0.2
 github.com/containerd/go-runc                       16b287bc67d069a60fa48db15f330b790b74365b
 github.com/containerd/typeurl                       cd3ce7159eae562a4f60ceff37dada11a939d247 # v1.0.1

+ 171 - 0
vendor/github.com/cilium/ebpf/link/cgroup.go

@@ -0,0 +1,171 @@
+package link
+
+import (
+	"errors"
+	"fmt"
+	"os"
+
+	"github.com/cilium/ebpf"
+)
+
+type cgroupAttachFlags uint32
+
+// cgroup attach flags
+const (
+	flagAllowOverride cgroupAttachFlags = 1 << iota
+	flagAllowMulti
+	flagReplace
+)
+
+type CgroupOptions struct {
+	// Path to a cgroupv2 folder.
+	Path string
+	// One of the AttachCgroup* constants
+	Attach ebpf.AttachType
+	// Program must be of type CGroup*, and the attach type must match Attach.
+	Program *ebpf.Program
+}
+
+// AttachCgroup links a BPF program to a cgroup.
+func AttachCgroup(opts CgroupOptions) (Link, error) {
+	cgroup, err := os.Open(opts.Path)
+	if err != nil {
+		return nil, fmt.Errorf("can't open cgroup: %s", err)
+	}
+
+	clone, err := opts.Program.Clone()
+	if err != nil {
+		cgroup.Close()
+		return nil, err
+	}
+
+	var cg Link
+	cg, err = newLinkCgroup(cgroup, opts.Attach, clone)
+	if errors.Is(err, ErrNotSupported) {
+		cg, err = newProgAttachCgroup(cgroup, opts.Attach, clone, flagAllowMulti)
+	}
+	if errors.Is(err, ErrNotSupported) {
+		cg, err = newProgAttachCgroup(cgroup, opts.Attach, clone, flagAllowOverride)
+	}
+	if err != nil {
+		cgroup.Close()
+		clone.Close()
+		return nil, err
+	}
+
+	return cg, nil
+}
+
+// LoadPinnedCgroup loads a pinned cgroup from a bpffs.
+func LoadPinnedCgroup(fileName string, opts *ebpf.LoadPinOptions) (Link, error) {
+	link, err := LoadPinnedRawLink(fileName, CgroupType, opts)
+	if err != nil {
+		return nil, err
+	}
+
+	return &linkCgroup{*link}, nil
+}
+
+type progAttachCgroup struct {
+	cgroup     *os.File
+	current    *ebpf.Program
+	attachType ebpf.AttachType
+	flags      cgroupAttachFlags
+}
+
+var _ Link = (*progAttachCgroup)(nil)
+
+func (cg *progAttachCgroup) isLink() {}
+
+func newProgAttachCgroup(cgroup *os.File, attach ebpf.AttachType, prog *ebpf.Program, flags cgroupAttachFlags) (*progAttachCgroup, error) {
+	if flags&flagAllowMulti > 0 {
+		if err := haveProgAttachReplace(); err != nil {
+			return nil, fmt.Errorf("can't support multiple programs: %w", err)
+		}
+	}
+
+	err := RawAttachProgram(RawAttachProgramOptions{
+		Target:  int(cgroup.Fd()),
+		Program: prog,
+		Flags:   uint32(flags),
+		Attach:  attach,
+	})
+	if err != nil {
+		return nil, fmt.Errorf("cgroup: %w", err)
+	}
+
+	return &progAttachCgroup{cgroup, prog, attach, flags}, nil
+}
+
+func (cg *progAttachCgroup) Close() error {
+	defer cg.cgroup.Close()
+	defer cg.current.Close()
+
+	err := RawDetachProgram(RawDetachProgramOptions{
+		Target:  int(cg.cgroup.Fd()),
+		Program: cg.current,
+		Attach:  cg.attachType,
+	})
+	if err != nil {
+		return fmt.Errorf("close cgroup: %s", err)
+	}
+	return nil
+}
+
+func (cg *progAttachCgroup) Update(prog *ebpf.Program) error {
+	new, err := prog.Clone()
+	if err != nil {
+		return err
+	}
+
+	args := RawAttachProgramOptions{
+		Target:  int(cg.cgroup.Fd()),
+		Program: prog,
+		Attach:  cg.attachType,
+		Flags:   uint32(cg.flags),
+	}
+
+	if cg.flags&flagAllowMulti > 0 {
+		// Atomically replacing multiple programs requires at least
+		// 5.5 (commit 7dd68b3279f17921 "bpf: Support replacing cgroup-bpf
+		// program in MULTI mode")
+		args.Flags |= uint32(flagReplace)
+		args.Replace = cg.current
+	}
+
+	if err := RawAttachProgram(args); err != nil {
+		new.Close()
+		return fmt.Errorf("can't update cgroup: %s", err)
+	}
+
+	cg.current.Close()
+	cg.current = new
+	return nil
+}
+
+func (cg *progAttachCgroup) Pin(string) error {
+	return fmt.Errorf("can't pin cgroup: %w", ErrNotSupported)
+}
+
+func (cg *progAttachCgroup) Unpin() error {
+	return fmt.Errorf("can't pin cgroup: %w", ErrNotSupported)
+}
+
+type linkCgroup struct {
+	RawLink
+}
+
+var _ Link = (*linkCgroup)(nil)
+
+func newLinkCgroup(cgroup *os.File, attach ebpf.AttachType, prog *ebpf.Program) (*linkCgroup, error) {
+	link, err := AttachRawLink(RawLinkOptions{
+		Target:  int(cgroup.Fd()),
+		Program: prog,
+		Attach:  attach,
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return &linkCgroup{*link}, err
+}

+ 2 - 0
vendor/github.com/cilium/ebpf/link/doc.go

@@ -0,0 +1,2 @@
+// Package link allows attaching eBPF programs to various kernel hooks.
+package link

+ 67 - 0
vendor/github.com/cilium/ebpf/link/iter.go

@@ -0,0 +1,67 @@
+package link
+
+import (
+	"fmt"
+	"io"
+
+	"github.com/cilium/ebpf"
+)
+
+type IterOptions struct {
+	// Program must be of type Tracing with attach type
+	// AttachTraceIter. The kind of iterator to attach to is
+	// determined at load time via the AttachTo field.
+	//
+	// AttachTo requires the kernel to include BTF of itself,
+	// and it to be compiled with a recent pahole (>= 1.16).
+	Program *ebpf.Program
+}
+
+// AttachIter attaches a BPF seq_file iterator.
+func AttachIter(opts IterOptions) (*Iter, error) {
+	link, err := AttachRawLink(RawLinkOptions{
+		Program: opts.Program,
+		Attach:  ebpf.AttachTraceIter,
+	})
+	if err != nil {
+		return nil, fmt.Errorf("can't link iterator: %w", err)
+	}
+
+	return &Iter{*link}, err
+}
+
+// LoadPinnedIter loads a pinned iterator from a bpffs.
+func LoadPinnedIter(fileName string, opts *ebpf.LoadPinOptions) (*Iter, error) {
+	link, err := LoadPinnedRawLink(fileName, IterType, opts)
+	if err != nil {
+		return nil, err
+	}
+
+	return &Iter{*link}, err
+}
+
+// Iter represents an attached bpf_iter.
+type Iter struct {
+	RawLink
+}
+
+// Open creates a new instance of the iterator.
+//
+// Reading from the returned reader triggers the BPF program.
+func (it *Iter) Open() (io.ReadCloser, error) {
+	linkFd, err := it.fd.Value()
+	if err != nil {
+		return nil, err
+	}
+
+	attr := &bpfIterCreateAttr{
+		linkFd: linkFd,
+	}
+
+	fd, err := bpfIterCreate(attr)
+	if err != nil {
+		return nil, fmt.Errorf("can't create iterator: %w", err)
+	}
+
+	return fd.File("bpf_iter"), nil
+}

+ 296 - 0
vendor/github.com/cilium/ebpf/link/kprobe.go

@@ -0,0 +1,296 @@
+package link
+
+import (
+	"crypto/rand"
+	"errors"
+	"fmt"
+	"os"
+	"path/filepath"
+	"runtime"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/internal"
+	"github.com/cilium/ebpf/internal/unix"
+)
+
+var (
+	kprobeEventsPath = filepath.Join(tracefsPath, "kprobe_events")
+)
+
+// Kprobe attaches the given eBPF program to a perf event that fires when the
+// given kernel symbol starts executing. See /proc/kallsyms for available
+// symbols. For example, printk():
+//
+//	Kprobe("printk")
+//
+// The resulting Link must be Closed during program shutdown to avoid leaking
+// system resources.
+func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
+	k, err := kprobe(symbol, prog, false)
+	if err != nil {
+		return nil, err
+	}
+
+	err = k.attach(prog)
+	if err != nil {
+		k.Close()
+		return nil, err
+	}
+
+	return k, nil
+}
+
+// Kretprobe attaches the given eBPF program to a perf event that fires right
+// before the given kernel symbol exits, with the function stack left intact.
+// See /proc/kallsyms for available symbols. For example, printk():
+//
+//	Kretprobe("printk")
+//
+// The resulting Link must be Closed during program shutdown to avoid leaking
+// system resources.
+func Kretprobe(symbol string, prog *ebpf.Program) (Link, error) {
+	k, err := kprobe(symbol, prog, true)
+	if err != nil {
+		return nil, err
+	}
+
+	err = k.attach(prog)
+	if err != nil {
+		k.Close()
+		return nil, err
+	}
+
+	return k, nil
+}
+
+// kprobe opens a perf event on the given symbol and attaches prog to it.
+// If ret is true, create a kretprobe.
+func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) {
+	if symbol == "" {
+		return nil, fmt.Errorf("symbol name cannot be empty: %w", errInvalidInput)
+	}
+	if prog == nil {
+		return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
+	}
+	if !rgxTraceEvent.MatchString(symbol) {
+		return nil, fmt.Errorf("symbol '%s' must be alphanumeric or underscore: %w", symbol, errInvalidInput)
+	}
+	if prog.Type() != ebpf.Kprobe {
+		return nil, fmt.Errorf("eBPF program type %s is not a Kprobe: %w", prog.Type(), errInvalidInput)
+	}
+
+	// Use kprobe PMU if the kernel has it available.
+	tp, err := pmuKprobe(symbol, ret)
+	if err == nil {
+		return tp, nil
+	}
+	if err != nil && !errors.Is(err, ErrNotSupported) {
+		return nil, fmt.Errorf("creating perf_kprobe PMU: %w", err)
+	}
+
+	// Use tracefs if kprobe PMU is missing.
+	tp, err = tracefsKprobe(symbol, ret)
+	if err != nil {
+		return nil, fmt.Errorf("creating trace event '%s' in tracefs: %w", symbol, err)
+	}
+
+	return tp, nil
+}
+
+// pmuKprobe opens a perf event based on a Performance Monitoring Unit.
+// Requires at least 4.17 (e12f03d7031a "perf/core: Implement the
+// 'perf_kprobe' PMU").
+// Returns ErrNotSupported if the kernel doesn't support perf_kprobe PMU,
+// or os.ErrNotExist if the given symbol does not exist in the kernel.
+func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
+
+	// Getting the PMU type will fail if the kernel doesn't support
+	// the perf_kprobe PMU.
+	et, err := getPMUEventType("kprobe")
+	if err != nil {
+		return nil, err
+	}
+
+	// Create a pointer to a NUL-terminated string for the kernel.
+	sp, err := unsafeStringPtr(symbol)
+	if err != nil {
+		return nil, err
+	}
+
+	// TODO: Parse the position of the bit from /sys/bus/event_source/devices/%s/format/retprobe.
+	config := 0
+	if ret {
+		config = 1
+	}
+
+	attr := unix.PerfEventAttr{
+		Type:   uint32(et),          // PMU event type read from sysfs
+		Ext1:   uint64(uintptr(sp)), // Kernel symbol to trace
+		Config: uint64(config),      // perf_kprobe PMU treats config as flags
+	}
+
+	fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
+
+	// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
+	// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
+	// is returned to the caller.
+	if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
+		return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, os.ErrNotExist)
+	}
+	if err != nil {
+		return nil, fmt.Errorf("opening perf event: %w", err)
+	}
+
+	// Ensure the string pointer is not collected before PerfEventOpen returns.
+	runtime.KeepAlive(sp)
+
+	// Kernel has perf_kprobe PMU available, initialize perf event.
+	return &perfEvent{
+		fd:       internal.NewFD(uint32(fd)),
+		pmuID:    et,
+		name:     symbol,
+		ret:      ret,
+		progType: ebpf.Kprobe,
+	}, nil
+}
+
+// tracefsKprobe creates a trace event by writing an entry to <tracefs>/kprobe_events.
+// A new trace event group name is generated on every call to support creating
+// multiple trace events for the same kernel symbol. A perf event is then opened
+// on the newly-created trace event and returned to the caller.
+func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
+
+	// Generate a random string for each trace event we attempt to create.
+	// This value is used as the 'group' token in tracefs to allow creating
+	// multiple kprobe trace events with the same name.
+	group, err := randomGroup("ebpf")
+	if err != nil {
+		return nil, fmt.Errorf("randomizing group name: %w", err)
+	}
+
+	// Before attempting to create a trace event through tracefs,
+	// check if an event with the same group and name already exists.
+	// Kernels 4.x and earlier don't return os.ErrExist on writing a duplicate
+	// entry, so we need to rely on reads for detecting uniqueness.
+	_, err = getTraceEventID(group, symbol)
+	if err == nil {
+		return nil, fmt.Errorf("trace event already exists: %s/%s", group, symbol)
+	}
+	// The read is expected to fail with ErrNotSupported due to a non-existing event.
+	if err != nil && !errors.Is(err, ErrNotSupported) {
+		return nil, fmt.Errorf("checking trace event %s/%s: %w", group, symbol, err)
+	}
+
+	// Create the kprobe trace event using tracefs.
+	if err := createTraceFSKprobeEvent(group, symbol, ret); err != nil {
+		return nil, fmt.Errorf("creating kprobe event on tracefs: %w", err)
+	}
+
+	// Get the newly-created trace event's id.
+	tid, err := getTraceEventID(group, symbol)
+	if err != nil {
+		return nil, fmt.Errorf("getting trace event id: %w", err)
+	}
+
+	// Kprobes are ephemeral tracepoints and share the same perf event type.
+	fd, err := openTracepointPerfEvent(tid)
+	if err != nil {
+		return nil, err
+	}
+
+	return &perfEvent{
+		fd:        fd,
+		group:     group,
+		name:      symbol,
+		ret:       ret,
+		tracefsID: tid,
+		progType:  ebpf.Kprobe, // kernel only allows attaching kprobe programs to kprobe events
+	}, nil
+}
+
+// createTraceFSKprobeEvent creates a new ephemeral trace event by writing to
+// <tracefs>/kprobe_events. Returns ErrNotSupported if symbol is not a valid
+// kernel symbol, or if it is not traceable with kprobes.
+func createTraceFSKprobeEvent(group, symbol string, ret bool) error {
+	// Open the kprobe_events file in tracefs.
+	f, err := os.OpenFile(kprobeEventsPath, os.O_APPEND|os.O_WRONLY, 0666)
+	if err != nil {
+		return fmt.Errorf("error opening kprobe_events: %w", err)
+	}
+	defer f.Close()
+
+	// The kprobe_events syntax is as follows (see Documentation/trace/kprobetrace.txt):
+	// p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe
+	// r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe
+	// -:[GRP/]EVENT                                        : Clear a probe
+	//
+	// Some examples:
+	// r:ebpf_1234/r_my_kretprobe nf_conntrack_destroy
+	// p:ebpf_5678/p_my_kprobe __x64_sys_execve
+	//
+	// Leaving the kretprobe's MAXACTIVE set to 0 (or absent) will make the
+	// kernel default to NR_CPUS. This is desired in most eBPF cases since
+	// subsampling or rate limiting logic can be more accurately implemented in
+	// the eBPF program itself. See Documentation/kprobes.txt for more details.
+	pe := fmt.Sprintf("%s:%s/%s %s", kprobePrefix(ret), group, symbol, symbol)
+	_, err = f.WriteString(pe)
+	// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
+	// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
+	// is returned to the caller.
+	if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
+		return fmt.Errorf("kernel symbol %s not found: %w", symbol, os.ErrNotExist)
+	}
+	if err != nil {
+		return fmt.Errorf("writing '%s' to kprobe_events: %w", pe, err)
+	}
+
+	return nil
+}
+
+// closeTraceFSKprobeEvent removes the kprobe with the given group, symbol and kind
+// from <tracefs>/kprobe_events.
+func closeTraceFSKprobeEvent(group, symbol string) error {
+	f, err := os.OpenFile(kprobeEventsPath, os.O_APPEND|os.O_WRONLY, 0666)
+	if err != nil {
+		return fmt.Errorf("error opening kprobe_events: %w", err)
+	}
+	defer f.Close()
+
+	// See kprobe_events syntax above. Kprobe type does not need to be specified
+	// for removals.
+	pe := fmt.Sprintf("-:%s/%s", group, symbol)
+	if _, err = f.WriteString(pe); err != nil {
+		return fmt.Errorf("writing '%s' to kprobe_events: %w", pe, err)
+	}
+
+	return nil
+}
+
+// randomGroup generates a pseudorandom string for use as a tracefs group name.
+// Returns an error when the output string would exceed 63 characters (kernel
+// limitation), when rand.Read() fails or when prefix contains characters not
+// allowed by rgxTraceEvent.
+func randomGroup(prefix string) (string, error) {
+	if !rgxTraceEvent.MatchString(prefix) {
+		return "", fmt.Errorf("prefix '%s' must be alphanumeric or underscore: %w", prefix, errInvalidInput)
+	}
+
+	b := make([]byte, 8)
+	if _, err := rand.Read(b); err != nil {
+		return "", fmt.Errorf("reading random bytes: %w", err)
+	}
+
+	group := fmt.Sprintf("%s_%x", prefix, b)
+	if len(group) > 63 {
+		return "", fmt.Errorf("group name '%s' cannot be longer than 63 characters: %w", group, errInvalidInput)
+	}
+
+	return group, nil
+}
+
+func kprobePrefix(ret bool) string {
+	if ret {
+		return "r"
+	}
+	return "p"
+}

+ 229 - 0
vendor/github.com/cilium/ebpf/link/link.go

@@ -0,0 +1,229 @@
+package link
+
+import (
+	"fmt"
+	"unsafe"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/internal"
+)
+
+var ErrNotSupported = internal.ErrNotSupported
+
+// Link represents a Program attached to a BPF hook.
+type Link interface {
+	// Replace the current program with a new program.
+	//
+	// Passing a nil program is an error. May return an error wrapping ErrNotSupported.
+	Update(*ebpf.Program) error
+
+	// Persist a link by pinning it into a bpffs.
+	//
+	// May return an error wrapping ErrNotSupported.
+	Pin(string) error
+
+	// Undo a previous call to Pin.
+	//
+	// May return an error wrapping ErrNotSupported.
+	Unpin() error
+
+	// Close frees resources.
+	//
+	// The link will be broken unless it has been pinned. A link
+	// may continue past the lifetime of the process if Close is
+	// not called.
+	Close() error
+
+	// Prevent external users from implementing this interface.
+	isLink()
+}
+
+// ID uniquely identifies a BPF link.
+type ID uint32
+
+// RawLinkOptions control the creation of a raw link.
+type RawLinkOptions struct {
+	// File descriptor to attach to. This differs for each attach type.
+	Target int
+	// Program to attach.
+	Program *ebpf.Program
+	// Attach must match the attach type of Program.
+	Attach ebpf.AttachType
+}
+
+// RawLinkInfo contains metadata on a link.
+type RawLinkInfo struct {
+	Type    Type
+	ID      ID
+	Program ebpf.ProgramID
+}
+
+// RawLink is the low-level API to bpf_link.
+//
+// You should consider using the higher level interfaces in this
+// package instead.
+type RawLink struct {
+	fd         *internal.FD
+	pinnedPath string
+}
+
+// AttachRawLink creates a raw link.
+func AttachRawLink(opts RawLinkOptions) (*RawLink, error) {
+	if err := haveBPFLink(); err != nil {
+		return nil, err
+	}
+
+	if opts.Target < 0 {
+		return nil, fmt.Errorf("invalid target: %s", internal.ErrClosedFd)
+	}
+
+	progFd := opts.Program.FD()
+	if progFd < 0 {
+		return nil, fmt.Errorf("invalid program: %s", internal.ErrClosedFd)
+	}
+
+	attr := bpfLinkCreateAttr{
+		targetFd:   uint32(opts.Target),
+		progFd:     uint32(progFd),
+		attachType: opts.Attach,
+	}
+	fd, err := bpfLinkCreate(&attr)
+	if err != nil {
+		return nil, fmt.Errorf("can't create link: %s", err)
+	}
+
+	return &RawLink{fd, ""}, nil
+}
+
+// LoadPinnedRawLink loads a persisted link from a bpffs.
+//
+// Returns an error if the pinned link type doesn't match linkType. Pass
+// UnspecifiedType to disable this behaviour.
+func LoadPinnedRawLink(fileName string, linkType Type, opts *ebpf.LoadPinOptions) (*RawLink, error) {
+	fd, err := internal.BPFObjGet(fileName, opts.Marshal())
+	if err != nil {
+		return nil, fmt.Errorf("load pinned link: %w", err)
+	}
+
+	link := &RawLink{fd, fileName}
+	if linkType == UnspecifiedType {
+		return link, nil
+	}
+
+	info, err := link.Info()
+	if err != nil {
+		link.Close()
+		return nil, fmt.Errorf("get pinned link info: %s", err)
+	}
+
+	if info.Type != linkType {
+		link.Close()
+		return nil, fmt.Errorf("link type %v doesn't match %v", info.Type, linkType)
+	}
+
+	return link, nil
+}
+
+func (l *RawLink) isLink() {}
+
+// FD returns the raw file descriptor.
+func (l *RawLink) FD() int {
+	fd, err := l.fd.Value()
+	if err != nil {
+		return -1
+	}
+	return int(fd)
+}
+
+// Close breaks the link.
+//
+// Use Pin if you want to make the link persistent.
+func (l *RawLink) Close() error {
+	return l.fd.Close()
+}
+
+// Pin persists a link past the lifetime of the process.
+//
+// Calling Close on a pinned Link will not break the link
+// until the pin is removed.
+func (l *RawLink) Pin(fileName string) error {
+	if err := internal.Pin(l.pinnedPath, fileName, l.fd); err != nil {
+		return err
+	}
+	l.pinnedPath = fileName
+	return nil
+}
+
+// Unpin implements the Link interface.
+func (l *RawLink) Unpin() error {
+	if err := internal.Unpin(l.pinnedPath); err != nil {
+		return err
+	}
+	l.pinnedPath = ""
+	return nil
+}
+
+// Update implements the Link interface.
+func (l *RawLink) Update(new *ebpf.Program) error {
+	return l.UpdateArgs(RawLinkUpdateOptions{
+		New: new,
+	})
+}
+
+// RawLinkUpdateOptions control the behaviour of RawLink.UpdateArgs.
+type RawLinkUpdateOptions struct {
+	New   *ebpf.Program
+	Old   *ebpf.Program
+	Flags uint32
+}
+
+// UpdateArgs updates a link based on args.
+func (l *RawLink) UpdateArgs(opts RawLinkUpdateOptions) error {
+	newFd := opts.New.FD()
+	if newFd < 0 {
+		return fmt.Errorf("invalid program: %s", internal.ErrClosedFd)
+	}
+
+	var oldFd int
+	if opts.Old != nil {
+		oldFd = opts.Old.FD()
+		if oldFd < 0 {
+			return fmt.Errorf("invalid replacement program: %s", internal.ErrClosedFd)
+		}
+	}
+
+	linkFd, err := l.fd.Value()
+	if err != nil {
+		return fmt.Errorf("can't update link: %s", err)
+	}
+
+	attr := bpfLinkUpdateAttr{
+		linkFd:    linkFd,
+		newProgFd: uint32(newFd),
+		oldProgFd: uint32(oldFd),
+		flags:     opts.Flags,
+	}
+	return bpfLinkUpdate(&attr)
+}
+
+// struct bpf_link_info
+type bpfLinkInfo struct {
+	typ     uint32
+	id      uint32
+	prog_id uint32
+}
+
+// Info returns metadata about the link.
+func (l *RawLink) Info() (*RawLinkInfo, error) {
+	var info bpfLinkInfo
+	err := internal.BPFObjGetInfoByFD(l.fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
+	if err != nil {
+		return nil, fmt.Errorf("link info: %s", err)
+	}
+
+	return &RawLinkInfo{
+		Type(info.typ),
+		ID(info.id),
+		ebpf.ProgramID(info.prog_id),
+	}, nil
+}

+ 60 - 0
vendor/github.com/cilium/ebpf/link/netns.go

@@ -0,0 +1,60 @@
+package link
+
+import (
+	"fmt"
+
+	"github.com/cilium/ebpf"
+)
+
+// NetNsInfo contains metadata about a network namespace link.
+type NetNsInfo struct {
+	RawLinkInfo
+}
+
+// NetNsLink is a program attached to a network namespace.
+type NetNsLink struct {
+	*RawLink
+}
+
+// AttachNetNs attaches a program to a network namespace.
+func AttachNetNs(ns int, prog *ebpf.Program) (*NetNsLink, error) {
+	var attach ebpf.AttachType
+	switch t := prog.Type(); t {
+	case ebpf.FlowDissector:
+		attach = ebpf.AttachFlowDissector
+	case ebpf.SkLookup:
+		attach = ebpf.AttachSkLookup
+	default:
+		return nil, fmt.Errorf("can't attach %v to network namespace", t)
+	}
+
+	link, err := AttachRawLink(RawLinkOptions{
+		Target:  ns,
+		Program: prog,
+		Attach:  attach,
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return &NetNsLink{link}, nil
+}
+
+// LoadPinnedNetNs loads a network namespace link from bpffs.
+func LoadPinnedNetNs(fileName string, opts *ebpf.LoadPinOptions) (*NetNsLink, error) {
+	link, err := LoadPinnedRawLink(fileName, NetNsType, opts)
+	if err != nil {
+		return nil, err
+	}
+
+	return &NetNsLink{link}, nil
+}
+
+// Info returns information about the link.
+func (nns *NetNsLink) Info() (*NetNsInfo, error) {
+	info, err := nns.RawLink.Info()
+	if err != nil {
+		return nil, err
+	}
+	return &NetNsInfo{*info}, nil
+}

+ 253 - 0
vendor/github.com/cilium/ebpf/link/perf_event.go

@@ -0,0 +1,253 @@
+package link
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"unsafe"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/internal"
+	"github.com/cilium/ebpf/internal/unix"
+)
+
+// Getting the terminology right is usually the hardest part. For posterity and
+// for staying sane during implementation:
+//
+// - trace event: Representation of a kernel runtime hook. Filesystem entries
+//   under <tracefs>/events. Can be tracepoints (static), kprobes or uprobes.
+//   Can be instantiated into perf events (see below).
+// - tracepoint: A predetermined hook point in the kernel. Exposed as trace
+//   events in (sub)directories under <tracefs>/events. Cannot be closed or
+//   removed, they are static.
+// - k(ret)probe: Ephemeral trace events based on entry or exit points of
+//   exported kernel symbols. kprobe-based (tracefs) trace events can be
+//   created system-wide by writing to the <tracefs>/kprobe_events file, or
+//   they can be scoped to the current process by creating PMU perf events.
+// - perf event: An object instantiated based on an existing trace event or
+//   kernel symbol. Referred to by fd in userspace.
+//   Exactly one eBPF program can be attached to a perf event. Multiple perf
+//   events can be created from a single trace event. Closing a perf event
+//   stops any further invocations of the attached eBPF program.
+
+var (
+	tracefsPath = "/sys/kernel/debug/tracing"
+
+	// Trace event groups, names and kernel symbols must adhere to this set
+	// of characters. Non-empty, first character must not be a number, all
+	// characters must be alphanumeric or underscore.
+	rgxTraceEvent = regexp.MustCompile("^[a-zA-Z_][0-9a-zA-Z_]*$")
+
+	errInvalidInput = errors.New("invalid input")
+)
+
+const (
+	perfAllThreads = -1
+)
+
+// A perfEvent represents a perf event kernel object. Exactly one eBPF program
+// can be attached to it. It is created based on a tracefs trace event or a
+// Performance Monitoring Unit (PMU).
+type perfEvent struct {
+
+	// Group and name of the tracepoint/kprobe/uprobe.
+	group string
+	name  string
+
+	// PMU event ID read from sysfs. Valid IDs are non-zero.
+	pmuID uint64
+	// ID of the trace event read from tracefs. Valid IDs are non-zero.
+	tracefsID uint64
+
+	// True for kretprobes/uretprobes.
+	ret bool
+
+	fd       *internal.FD
+	progType ebpf.ProgramType
+}
+
+func (pe *perfEvent) isLink() {}
+
+func (pe *perfEvent) Pin(string) error {
+	return fmt.Errorf("pin perf event: %w", ErrNotSupported)
+}
+
+func (pe *perfEvent) Unpin() error {
+	return fmt.Errorf("unpin perf event: %w", ErrNotSupported)
+}
+
+// Since 4.15 (e87c6bc3852b "bpf: permit multiple bpf attachments for a single perf event"),
+// calling PERF_EVENT_IOC_SET_BPF appends the given program to a prog_array
+// owned by the perf event, which means multiple programs can be attached
+// simultaneously.
+//
+// Before 4.15, calling PERF_EVENT_IOC_SET_BPF more than once on a perf event
+// returns EEXIST.
+//
+// Detaching a program from a perf event is currently not possible, so a
+// program replacement mechanism cannot be implemented for perf events.
+func (pe *perfEvent) Update(prog *ebpf.Program) error {
+	return fmt.Errorf("can't replace eBPF program in perf event: %w", ErrNotSupported)
+}
+
+func (pe *perfEvent) Close() error {
+	if pe.fd == nil {
+		return nil
+	}
+
+	pfd, err := pe.fd.Value()
+	if err != nil {
+		return fmt.Errorf("getting perf event fd: %w", err)
+	}
+
+	err = unix.IoctlSetInt(int(pfd), unix.PERF_EVENT_IOC_DISABLE, 0)
+	if err != nil {
+		return fmt.Errorf("disabling perf event: %w", err)
+	}
+
+	err = pe.fd.Close()
+	if err != nil {
+		return fmt.Errorf("closing perf event fd: %w", err)
+	}
+
+	switch t := pe.progType; t {
+	case ebpf.Kprobe:
+		// For kprobes created using tracefs, clean up the <tracefs>/kprobe_events entry.
+		if pe.tracefsID != 0 {
+			return closeTraceFSKprobeEvent(pe.group, pe.name)
+		}
+	case ebpf.TracePoint:
+		// Tracepoint trace events don't hold any extra resources.
+		return nil
+	}
+
+	return nil
+}
+
+// attach the given eBPF prog to the perf event stored in pe.
+// pe must contain a valid perf event fd.
+// prog's type must match the program type stored in pe.
+func (pe *perfEvent) attach(prog *ebpf.Program) error {
+	if prog == nil {
+		return errors.New("cannot attach a nil program")
+	}
+	if pe.fd == nil {
+		return errors.New("cannot attach to nil perf event")
+	}
+	if t := prog.Type(); t != pe.progType {
+		return fmt.Errorf("invalid program type (expected %s): %s", pe.progType, t)
+	}
+	if prog.FD() < 0 {
+		return fmt.Errorf("invalid program: %w", internal.ErrClosedFd)
+	}
+
+	// The ioctl below will fail when the fd is invalid.
+	kfd, _ := pe.fd.Value()
+
+	// Assign the eBPF program to the perf event.
+	err := unix.IoctlSetInt(int(kfd), unix.PERF_EVENT_IOC_SET_BPF, prog.FD())
+	if err != nil {
+		return fmt.Errorf("setting perf event bpf program: %w", err)
+	}
+
+	// PERF_EVENT_IOC_ENABLE and _DISABLE ignore their given values.
+	if err := unix.IoctlSetInt(int(kfd), unix.PERF_EVENT_IOC_ENABLE, 0); err != nil {
+		return fmt.Errorf("enable perf event: %s", err)
+	}
+
+	// Close the perf event when its reference is lost to avoid leaking system resources.
+	runtime.SetFinalizer(pe, (*perfEvent).Close)
+	return nil
+}
+
+// unsafeStringPtr returns an unsafe.Pointer to a NUL-terminated copy of str.
+func unsafeStringPtr(str string) (unsafe.Pointer, error) {
+	p, err := unix.BytePtrFromString(str)
+	if err != nil {
+		return nil, err
+	}
+	return unsafe.Pointer(p), nil
+}
+
+// getTraceEventID reads a trace event's ID from tracefs given its group and name.
+// group and name must be alphanumeric or underscore, as required by the kernel.
+func getTraceEventID(group, name string) (uint64, error) {
+	tid, err := uint64FromFile(tracefsPath, "events", group, name, "id")
+	if errors.Is(err, ErrNotSupported) {
+		return 0, fmt.Errorf("trace event %s/%s: %w", group, name, ErrNotSupported)
+	}
+	if err != nil {
+		return 0, fmt.Errorf("reading trace event ID of %s/%s: %w", group, name, err)
+	}
+
+	return tid, nil
+}
+
+// getPMUEventType reads a Performance Monitoring Unit's type (numeric identifier)
+// from /sys/bus/event_source/devices/<pmu>/type.
+func getPMUEventType(pmu string) (uint64, error) {
+	et, err := uint64FromFile("/sys/bus/event_source/devices", pmu, "type")
+	if errors.Is(err, ErrNotSupported) {
+		return 0, fmt.Errorf("pmu type %s: %w", pmu, ErrNotSupported)
+	}
+	if err != nil {
+		return 0, fmt.Errorf("reading pmu type %s: %w", pmu, err)
+	}
+
+	return et, nil
+}
+
+// openTracepointPerfEvent opens a tracepoint-type perf event. System-wide
+// kprobes created by writing to <tracefs>/kprobe_events are tracepoints
+// behind the scenes, and can be attached to using these perf events.
+func openTracepointPerfEvent(tid uint64) (*internal.FD, error) {
+	attr := unix.PerfEventAttr{
+		Type:        unix.PERF_TYPE_TRACEPOINT,
+		Config:      tid,
+		Sample_type: unix.PERF_SAMPLE_RAW,
+		Sample:      1,
+		Wakeup:      1,
+	}
+
+	fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
+	if err != nil {
+		return nil, fmt.Errorf("opening tracepoint perf event: %w", err)
+	}
+
+	return internal.NewFD(uint32(fd)), nil
+}
+
+// uint64FromFile reads a uint64 from a file. All elements of path are sanitized
+// and joined onto base. Returns error if base no longer prefixes the path after
+// joining all components.
+func uint64FromFile(base string, path ...string) (uint64, error) {
+
+	// Resolve leaf path separately for error feedback. Makes the join onto
+	// base more readable (can't mix with variadic args).
+	l := filepath.Join(path...)
+
+	p := filepath.Join(base, l)
+	if !strings.HasPrefix(p, base) {
+		return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput)
+	}
+
+	data, err := ioutil.ReadFile(p)
+	if os.IsNotExist(err) {
+		// Only echo leaf path, the base path can be prepended at the call site
+		// if more verbosity is required.
+		return 0, fmt.Errorf("symbol %s: %w", l, ErrNotSupported)
+	}
+	if err != nil {
+		return 0, fmt.Errorf("reading file %s: %w", p, err)
+	}
+
+	et := bytes.TrimSpace(data)
+	return strconv.ParseUint(string(et), 10, 64)
+}

+ 76 - 0
vendor/github.com/cilium/ebpf/link/program.go

@@ -0,0 +1,76 @@
+package link
+
+import (
+	"fmt"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/internal"
+)
+
+type RawAttachProgramOptions struct {
+	// File descriptor to attach to. This differs for each attach type.
+	Target int
+	// Program to attach.
+	Program *ebpf.Program
+	// Program to replace (cgroups).
+	Replace *ebpf.Program
+	// Attach must match the attach type of Program (and Replace).
+	Attach ebpf.AttachType
+	// Flags control the attach behaviour. This differs for each attach type.
+	Flags uint32
+}
+
+// RawAttachProgram is a low level wrapper around BPF_PROG_ATTACH.
+//
+// You should use one of the higher level abstractions available in this
+// package if possible.
+func RawAttachProgram(opts RawAttachProgramOptions) error {
+	if err := haveProgAttach(); err != nil {
+		return err
+	}
+
+	var replaceFd uint32
+	if opts.Replace != nil {
+		replaceFd = uint32(opts.Replace.FD())
+	}
+
+	attr := internal.BPFProgAttachAttr{
+		TargetFd:     uint32(opts.Target),
+		AttachBpfFd:  uint32(opts.Program.FD()),
+		ReplaceBpfFd: replaceFd,
+		AttachType:   uint32(opts.Attach),
+		AttachFlags:  uint32(opts.Flags),
+	}
+
+	if err := internal.BPFProgAttach(&attr); err != nil {
+		return fmt.Errorf("can't attach program: %s", err)
+	}
+	return nil
+}
+
+type RawDetachProgramOptions struct {
+	Target  int
+	Program *ebpf.Program
+	Attach  ebpf.AttachType
+}
+
+// RawDetachProgram is a low level wrapper around BPF_PROG_DETACH.
+//
+// You should use one of the higher level abstractions available in this
+// package if possible.
+func RawDetachProgram(opts RawDetachProgramOptions) error {
+	if err := haveProgAttach(); err != nil {
+		return err
+	}
+
+	attr := internal.BPFProgDetachAttr{
+		TargetFd:    uint32(opts.Target),
+		AttachBpfFd: uint32(opts.Program.FD()),
+		AttachType:  uint32(opts.Attach),
+	}
+	if err := internal.BPFProgDetach(&attr); err != nil {
+		return fmt.Errorf("can't detach program: %s", err)
+	}
+
+	return nil
+}

+ 61 - 0
vendor/github.com/cilium/ebpf/link/raw_tracepoint.go

@@ -0,0 +1,61 @@
+package link
+
+import (
+	"fmt"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/internal"
+)
+
+type RawTracepointOptions struct {
+	// Tracepoint name.
+	Name string
+	// Program must be of type RawTracepoint*
+	Program *ebpf.Program
+}
+
+// AttachRawTracepoint links a BPF program to a raw_tracepoint.
+//
+// Requires at least Linux 4.17.
+func AttachRawTracepoint(opts RawTracepointOptions) (Link, error) {
+	if t := opts.Program.Type(); t != ebpf.RawTracepoint && t != ebpf.RawTracepointWritable {
+		return nil, fmt.Errorf("invalid program type %s, expected RawTracepoint(Writable)", t)
+	}
+	if opts.Program.FD() < 0 {
+		return nil, fmt.Errorf("invalid program: %w", internal.ErrClosedFd)
+	}
+
+	fd, err := bpfRawTracepointOpen(&bpfRawTracepointOpenAttr{
+		name: internal.NewStringPointer(opts.Name),
+		fd:   uint32(opts.Program.FD()),
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return &progAttachRawTracepoint{fd: fd}, nil
+}
+
+type progAttachRawTracepoint struct {
+	fd *internal.FD
+}
+
+var _ Link = (*progAttachRawTracepoint)(nil)
+
+func (rt *progAttachRawTracepoint) isLink() {}
+
+func (rt *progAttachRawTracepoint) Close() error {
+	return rt.fd.Close()
+}
+
+func (rt *progAttachRawTracepoint) Update(_ *ebpf.Program) error {
+	return fmt.Errorf("can't update raw_tracepoint: %w", ErrNotSupported)
+}
+
+func (rt *progAttachRawTracepoint) Pin(_ string) error {
+	return fmt.Errorf("can't pin raw_tracepoint: %w", ErrNotSupported)
+}
+
+func (rt *progAttachRawTracepoint) Unpin() error {
+	return fmt.Errorf("unpin raw_tracepoint: %w", ErrNotSupported)
+}

+ 173 - 0
vendor/github.com/cilium/ebpf/link/syscalls.go

@@ -0,0 +1,173 @@
+package link
+
+import (
+	"errors"
+	"unsafe"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/asm"
+	"github.com/cilium/ebpf/internal"
+	"github.com/cilium/ebpf/internal/unix"
+)
+
+// Type is the kind of link.
+type Type uint32
+
+// Valid link types.
+//
+// Equivalent to enum bpf_link_type.
+const (
+	UnspecifiedType Type = iota
+	RawTracepointType
+	TracingType
+	CgroupType
+	IterType
+	NetNsType
+	XDPType
+)
+
+var haveProgAttach = internal.FeatureTest("BPF_PROG_ATTACH", "4.10", func() error {
+	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
+		Type:       ebpf.CGroupSKB,
+		AttachType: ebpf.AttachCGroupInetIngress,
+		License:    "MIT",
+		Instructions: asm.Instructions{
+			asm.Mov.Imm(asm.R0, 0),
+			asm.Return(),
+		},
+	})
+	if err != nil {
+		return internal.ErrNotSupported
+	}
+
+	// BPF_PROG_ATTACH was introduced at the same time as CGgroupSKB,
+	// so being able to load the program is enough to infer that we
+	// have the syscall.
+	prog.Close()
+	return nil
+})
+
+var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replacement", "5.5", func() error {
+	if err := haveProgAttach(); err != nil {
+		return err
+	}
+
+	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
+		Type:       ebpf.CGroupSKB,
+		AttachType: ebpf.AttachCGroupInetIngress,
+		License:    "MIT",
+		Instructions: asm.Instructions{
+			asm.Mov.Imm(asm.R0, 0),
+			asm.Return(),
+		},
+	})
+	if err != nil {
+		return internal.ErrNotSupported
+	}
+	defer prog.Close()
+
+	// We know that we have BPF_PROG_ATTACH since we can load CGroupSKB programs.
+	// If passing BPF_F_REPLACE gives us EINVAL we know that the feature isn't
+	// present.
+	attr := internal.BPFProgAttachAttr{
+		// We rely on this being checked after attachFlags.
+		TargetFd:    ^uint32(0),
+		AttachBpfFd: uint32(prog.FD()),
+		AttachType:  uint32(ebpf.AttachCGroupInetIngress),
+		AttachFlags: uint32(flagReplace),
+	}
+
+	err = internal.BPFProgAttach(&attr)
+	if errors.Is(err, unix.EINVAL) {
+		return internal.ErrNotSupported
+	}
+	if errors.Is(err, unix.EBADF) {
+		return nil
+	}
+	return err
+})
+
+type bpfLinkCreateAttr struct {
+	progFd     uint32
+	targetFd   uint32
+	attachType ebpf.AttachType
+	flags      uint32
+}
+
+func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {
+	ptr, err := internal.BPF(internal.BPF_LINK_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
+	if err != nil {
+		return nil, err
+	}
+	return internal.NewFD(uint32(ptr)), nil
+}
+
+type bpfLinkUpdateAttr struct {
+	linkFd    uint32
+	newProgFd uint32
+	flags     uint32
+	oldProgFd uint32
+}
+
+func bpfLinkUpdate(attr *bpfLinkUpdateAttr) error {
+	_, err := internal.BPF(internal.BPF_LINK_UPDATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
+	return err
+}
+
+var haveBPFLink = internal.FeatureTest("bpf_link", "5.7", func() error {
+	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
+		Type:       ebpf.CGroupSKB,
+		AttachType: ebpf.AttachCGroupInetIngress,
+		License:    "MIT",
+		Instructions: asm.Instructions{
+			asm.Mov.Imm(asm.R0, 0),
+			asm.Return(),
+		},
+	})
+	if err != nil {
+		return internal.ErrNotSupported
+	}
+	defer prog.Close()
+
+	attr := bpfLinkCreateAttr{
+		// This is a hopefully invalid file descriptor, which triggers EBADF.
+		targetFd:   ^uint32(0),
+		progFd:     uint32(prog.FD()),
+		attachType: ebpf.AttachCGroupInetIngress,
+	}
+	_, err = bpfLinkCreate(&attr)
+	if errors.Is(err, unix.EINVAL) {
+		return internal.ErrNotSupported
+	}
+	if errors.Is(err, unix.EBADF) {
+		return nil
+	}
+	return err
+})
+
+type bpfIterCreateAttr struct {
+	linkFd uint32
+	flags  uint32
+}
+
+func bpfIterCreate(attr *bpfIterCreateAttr) (*internal.FD, error) {
+	ptr, err := internal.BPF(internal.BPF_ITER_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
+	if err == nil {
+		return internal.NewFD(uint32(ptr)), nil
+	}
+	return nil, err
+}
+
+type bpfRawTracepointOpenAttr struct {
+	name internal.Pointer
+	fd   uint32
+	_    uint32
+}
+
+func bpfRawTracepointOpen(attr *bpfRawTracepointOpenAttr) (*internal.FD, error) {
+	ptr, err := internal.BPF(internal.BPF_RAW_TRACEPOINT_OPEN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
+	if err == nil {
+		return internal.NewFD(uint32(ptr)), nil
+	}
+	return nil, err
+}

+ 56 - 0
vendor/github.com/cilium/ebpf/link/tracepoint.go

@@ -0,0 +1,56 @@
+package link
+
+import (
+	"fmt"
+
+	"github.com/cilium/ebpf"
+)
+
+// Tracepoint attaches the given eBPF program to the tracepoint with the given
+// group and name. See /sys/kernel/debug/tracing/events to find available
+// tracepoints. The top-level directory is the group, the event's subdirectory
+// is the name. Example:
+//
+//	Tracepoint("syscalls", "sys_enter_fork")
+//
+// Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is
+// only possible as of kernel 4.14 (commit cf5f5ce).
+func Tracepoint(group, name string, prog *ebpf.Program) (Link, error) {
+	if group == "" || name == "" {
+		return nil, fmt.Errorf("group and name cannot be empty: %w", errInvalidInput)
+	}
+	if prog == nil {
+		return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
+	}
+	if !rgxTraceEvent.MatchString(group) || !rgxTraceEvent.MatchString(name) {
+		return nil, fmt.Errorf("group and name '%s/%s' must be alphanumeric or underscore: %w", group, name, errInvalidInput)
+	}
+	if prog.Type() != ebpf.TracePoint {
+		return nil, fmt.Errorf("eBPF program type %s is not a Tracepoint: %w", prog.Type(), errInvalidInput)
+	}
+
+	tid, err := getTraceEventID(group, name)
+	if err != nil {
+		return nil, err
+	}
+
+	fd, err := openTracepointPerfEvent(tid)
+	if err != nil {
+		return nil, err
+	}
+
+	pe := &perfEvent{
+		fd:        fd,
+		tracefsID: tid,
+		group:     group,
+		name:      name,
+		progType:  ebpf.TracePoint,
+	}
+
+	if err := pe.attach(prog); err != nil {
+		pe.Close()
+		return nil, err
+	}
+
+	return pe, nil
+}

+ 6 - 6
vendor/github.com/containerd/cgroups/go.mod

@@ -3,16 +3,16 @@ module github.com/containerd/cgroups
 go 1.13
 
 require (
-	github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775
-	github.com/coreos/go-systemd/v22 v22.0.0
+	github.com/cilium/ebpf v0.4.0
+	github.com/coreos/go-systemd/v22 v22.1.0
 	github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
 	github.com/docker/go-units v0.4.0
 	github.com/godbus/dbus/v5 v5.0.3
-	github.com/gogo/protobuf v1.3.1
+	github.com/gogo/protobuf v1.3.2
 	github.com/opencontainers/runtime-spec v1.0.2
 	github.com/pkg/errors v0.9.1
-	github.com/sirupsen/logrus v1.6.0
-	github.com/stretchr/testify v1.2.2
+	github.com/sirupsen/logrus v1.7.0
+	github.com/stretchr/testify v1.6.1
 	github.com/urfave/cli v1.22.2
-	golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9
+	golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
 )

+ 4 - 0
vendor/github.com/containerd/cgroups/net_cls.go

@@ -55,3 +55,7 @@ func (n *netclsController) Create(path string, resources *specs.LinuxResources)
 	}
 	return nil
 }
+
+func (n *netclsController) Update(path string, resources *specs.LinuxResources) error {
+	return n.Create(path, resources)
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 593 - 513
vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.go


+ 5 - 2
vendor/github.com/containerd/cgroups/subsystem.go

@@ -18,6 +18,7 @@ package cgroups
 
 import (
 	"fmt"
+	"os"
 
 	v1 "github.com/containerd/cgroups/stats/v1"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -46,7 +47,6 @@ const (
 // available on most linux systems
 func Subsystems() []Name {
 	n := []Name{
-		Hugetlb,
 		Freezer,
 		Pids,
 		NetCLS,
@@ -59,9 +59,12 @@ func Subsystems() []Name {
 		Blkio,
 		Rdma,
 	}
-	if !isUserNS {
+	if !RunningInUserNS() {
 		n = append(n, Devices)
 	}
+	if _, err := os.Stat("/sys/kernel/mm/hugepages"); err == nil {
+		n = append(n, Hugetlb)
+	}
 	return n
 }
 

+ 31 - 26
vendor/github.com/containerd/cgroups/utils.go

@@ -36,7 +36,8 @@ import (
 )
 
 var (
-	isUserNS  = runningInUserNS()
+	nsOnce    sync.Once
+	inUserNS  bool
 	checkMode sync.Once
 	cgMode    CGMode
 )
@@ -81,33 +82,37 @@ func Mode() CGMode {
 	return cgMode
 }
 
-// runningInUserNS detects whether we are currently running in a user namespace.
+// RunningInUserNS detects whether we are currently running in a user namespace.
 // Copied from github.com/lxc/lxd/shared/util.go
-func runningInUserNS() bool {
-	file, err := os.Open("/proc/self/uid_map")
-	if err != nil {
-		// This kernel-provided file only exists if user namespaces are supported
-		return false
-	}
-	defer file.Close()
+func RunningInUserNS() bool {
+	nsOnce.Do(func() {
+		file, err := os.Open("/proc/self/uid_map")
+		if err != nil {
+			// This kernel-provided file only exists if user namespaces are supported
+			return
+		}
+		defer file.Close()
 
-	buf := bufio.NewReader(file)
-	l, _, err := buf.ReadLine()
-	if err != nil {
-		return false
-	}
+		buf := bufio.NewReader(file)
+		l, _, err := buf.ReadLine()
+		if err != nil {
+			return
+		}
 
-	line := string(l)
-	var a, b, c int64
-	fmt.Sscanf(line, "%d %d %d", &a, &b, &c)
-	/*
-	 * We assume we are in the initial user namespace if we have a full
-	 * range - 4294967295 uids starting at uid 0.
-	 */
-	if a == 0 && b == 0 && c == 4294967295 {
-		return false
-	}
-	return true
+		line := string(l)
+		var a, b, c int64
+		fmt.Sscanf(line, "%d %d %d", &a, &b, &c)
+
+		/*
+		 * We assume we are in the initial user namespace if we have a full
+		 * range - 4294967295 uids starting at uid 0.
+		 */
+		if a == 0 && b == 0 && c == 4294967295 {
+			return
+		}
+		inUserNS = true
+	})
+	return inUserNS
 }
 
 // defaults returns all known groups
@@ -132,7 +137,7 @@ func defaults(root string) ([]Subsystem, error) {
 	}
 	// only add the devices cgroup if we are not in a user namespace
 	// because modifications are not allowed
-	if !isUserNS {
+	if !RunningInUserNS() {
 		s = append(s, NewDevices(root))
 	}
 	// add the hugetlb cgroup if error wasn't due to missing hugetlb

+ 15 - 3
vendor/github.com/containerd/cgroups/v2/ebpf.go

@@ -19,6 +19,7 @@ package v2
 import (
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf/asm"
+	"github.com/cilium/ebpf/link"
 	"github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
@@ -42,12 +43,23 @@ func LoadAttachCgroupDeviceFilter(insts asm.Instructions, license string, dirFD
 	if err != nil {
 		return nilCloser, err
 	}
-	if err := prog.Attach(dirFD, ebpf.AttachCGroupDevice, unix.BPF_F_ALLOW_MULTI); err != nil {
+	err = link.RawAttachProgram(link.RawAttachProgramOptions{
+		Target:  dirFD,
+		Program: prog,
+		Attach:  ebpf.AttachCGroupDevice,
+		Flags:   unix.BPF_F_ALLOW_MULTI,
+	})
+	if err != nil {
 		return nilCloser, errors.Wrap(err, "failed to call BPF_PROG_ATTACH (BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI)")
 	}
 	closer := func() error {
-		if err := prog.Detach(dirFD, ebpf.AttachCGroupDevice, unix.BPF_F_ALLOW_MULTI); err != nil {
-			return errors.Wrap(err, "failed to call BPF_PROG_DETACH (BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI)")
+		err = link.RawDetachProgram(link.RawDetachProgramOptions{
+			Target:  dirFD,
+			Program: prog,
+			Attach:  ebpf.AttachCGroupDevice,
+		})
+		if err != nil {
+			return errors.Wrap(err, "failed to call BPF_PROG_DETACH (BPF_CGROUP_DEVICE)")
 		}
 		return nil
 	}

Diferenças do arquivo suprimidas por serem muito extensas
+ 415 - 353
vendor/github.com/containerd/cgroups/v2/stats/metrics.pb.go


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff