From 8e5bb0d8c453f75f4c174a0c9ad2fafeab57ec51 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 31 Jan 2025 15:56:24 -0800 Subject: [PATCH] deps: roll back to cilium/ebpf v0.16.0 Also, exclude v0.17.x until there is a fix for runc issue 4594. Signed-off-by: Kir Kolyshkin --- go.mod | 10 +- go.sum | 6 +- vendor/github.com/cilium/ebpf/.golangci.yaml | 6 - vendor/github.com/cilium/ebpf/CODEOWNERS | 2 - vendor/github.com/cilium/ebpf/Makefile | 6 +- vendor/github.com/cilium/ebpf/README.md | 1 - .../github.com/cilium/ebpf/asm/instruction.go | 3 +- vendor/github.com/cilium/ebpf/btf/btf.go | 24 +- .../github.com/cilium/ebpf/btf/btf_types.go | 1 - vendor/github.com/cilium/ebpf/btf/ext_info.go | 150 +++---- vendor/github.com/cilium/ebpf/btf/feature.go | 55 +-- vendor/github.com/cilium/ebpf/btf/format.go | 3 - vendor/github.com/cilium/ebpf/btf/kernel.go | 6 +- vendor/github.com/cilium/ebpf/btf/marshal.go | 83 +--- .../github.com/cilium/ebpf/btf/traversal.go | 48 +-- vendor/github.com/cilium/ebpf/btf/types.go | 138 +------ .../github.com/cilium/ebpf/btf/workarounds.go | 2 +- vendor/github.com/cilium/ebpf/collection.go | 253 ++++-------- vendor/github.com/cilium/ebpf/elf_reader.go | 172 ++------ vendor/github.com/cilium/ebpf/info.go | 370 ++---------------- .../cilium/ebpf/internal/{linux => }/auxv.go | 2 +- .../github.com/cilium/ebpf/internal/errors.go | 6 +- .../cilium/ebpf/internal/feature.go | 55 +-- .../cilium/ebpf/internal/kallsyms/cache.go | 20 - .../cilium/ebpf/internal/kallsyms/kallsyms.go | 291 +++----------- .../cilium/ebpf/internal/kallsyms/reader.go | 118 ------ .../cilium/ebpf/internal/kconfig/kconfig.go | 45 ++- .../cilium/ebpf/internal/linux/doc.go | 2 - .../cilium/ebpf/internal/linux/kconfig.go | 31 -- .../cilium/ebpf/internal/linux/version.go | 34 -- .../github.com/cilium/ebpf/internal/math.go | 28 +- .../cilium/ebpf/internal/{sys => }/pinning.go | 16 +- .../ebpf/internal/{linux => }/platform.go | 2 +- .../ebpf/internal/{linux => }/statfs.go | 2 +- .../github.com/cilium/ebpf/internal/sys/fd.go | 74 +--- .../cilium/ebpf/internal/sys/fd_trace.go | 93 +++++ .../ebpf/internal/sys/mapflags_string.go | 53 +++ .../cilium/ebpf/internal/sys/ptr.go | 6 +- .../cilium/ebpf/internal/sys/syscall.go | 37 +- .../cilium/ebpf/internal/sys/types.go | 185 +-------- .../cilium/ebpf/internal/sysenc/buffer.go | 10 +- .../internal/testutils/fdtrace/fd_trace.go | 103 ----- .../ebpf/internal/testutils/fdtrace/main.go | 31 -- .../cilium/ebpf/internal/tracefs/kprobe.go | 8 +- .../cilium/ebpf/internal/unix/types_linux.go | 5 +- .../cilium/ebpf/internal/unix/types_other.go | 5 +- .../cilium/ebpf/internal/{linux => }/vdso.go | 9 +- .../cilium/ebpf/internal/version.go | 30 ++ vendor/github.com/cilium/ebpf/link/kprobe.go | 12 +- .../cilium/ebpf/link/kprobe_multi.go | 8 +- vendor/github.com/cilium/ebpf/link/link.go | 15 +- .../github.com/cilium/ebpf/link/netfilter.go | 2 +- .../github.com/cilium/ebpf/link/perf_event.go | 8 +- .../github.com/cilium/ebpf/link/syscalls.go | 24 +- vendor/github.com/cilium/ebpf/link/tracing.go | 2 +- vendor/github.com/cilium/ebpf/link/uprobe.go | 6 +- .../cilium/ebpf/link/uprobe_multi.go | 13 +- vendor/github.com/cilium/ebpf/linker.go | 41 -- vendor/github.com/cilium/ebpf/map.go | 127 ++---- vendor/github.com/cilium/ebpf/memory.go | 145 ------- vendor/github.com/cilium/ebpf/prog.go | 102 ++--- vendor/github.com/cilium/ebpf/syscalls.go | 80 ++-- vendor/github.com/cilium/ebpf/types.go | 28 +- vendor/github.com/cilium/ebpf/types_string.go | 8 +- vendor/github.com/cilium/ebpf/variable.go | 230 ----------- vendor/golang.org/x/exp/LICENSE | 27 ++ vendor/golang.org/x/exp/PATENTS | 22 ++ .../x/exp/constraints/constraints.go | 50 +++ vendor/modules.txt | 9 +- 69 files changed, 872 insertions(+), 2727 deletions(-) rename vendor/github.com/cilium/ebpf/internal/{linux => }/auxv.go (98%) delete mode 100644 vendor/github.com/cilium/ebpf/internal/kallsyms/cache.go delete mode 100644 vendor/github.com/cilium/ebpf/internal/kallsyms/reader.go delete mode 100644 vendor/github.com/cilium/ebpf/internal/linux/doc.go delete mode 100644 vendor/github.com/cilium/ebpf/internal/linux/kconfig.go delete mode 100644 vendor/github.com/cilium/ebpf/internal/linux/version.go rename vendor/github.com/cilium/ebpf/internal/{sys => }/pinning.go (77%) rename vendor/github.com/cilium/ebpf/internal/{linux => }/platform.go (97%) rename vendor/github.com/cilium/ebpf/internal/{linux => }/statfs.go (96%) create mode 100644 vendor/github.com/cilium/ebpf/internal/sys/fd_trace.go create mode 100644 vendor/github.com/cilium/ebpf/internal/sys/mapflags_string.go delete mode 100644 vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/fd_trace.go delete mode 100644 vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/main.go rename vendor/github.com/cilium/ebpf/internal/{linux => }/vdso.go (93%) delete mode 100644 vendor/github.com/cilium/ebpf/memory.go delete mode 100644 vendor/github.com/cilium/ebpf/variable.go create mode 100644 vendor/golang.org/x/exp/LICENSE create mode 100644 vendor/golang.org/x/exp/PATENTS create mode 100644 vendor/golang.org/x/exp/constraints/constraints.go diff --git a/go.mod b/go.mod index a25592b1c12..5fff44cc736 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ toolchain go1.22.4 require ( github.com/checkpoint-restore/go-criu/v6 v6.3.0 - github.com/cilium/ebpf v0.17.1 + github.com/cilium/ebpf v0.16.0 github.com/containerd/console v1.0.4 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.4.1 @@ -31,8 +31,16 @@ require ( google.golang.org/protobuf v1.36.4 ) +// https://github.com/cilium/ebpf/pull/1660 +exclude ( + github.com/cilium/ebpf v0.17.0 + github.com/cilium/ebpf v0.17.1 + github.com/cilium/ebpf v0.17.2 +) + require ( github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/vishvananda/netns v0.0.4 // indirect + golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect ) diff --git a/go.sum b/go.sum index aa8a64296ea..b7b2d42ce1e 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= -github.com/cilium/ebpf v0.17.1 h1:G8mzU81R2JA1nE5/8SRubzqvBMmAmri2VL8BIZPWvV0= -github.com/cilium/ebpf v0.17.1/go.mod h1:vay2FaYSmIlv3r8dNACd4mW/OCaZLJKJOo+IHBvCIO8= +github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= +github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -81,6 +81,8 @@ github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQ github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= diff --git a/vendor/github.com/cilium/ebpf/.golangci.yaml b/vendor/github.com/cilium/ebpf/.golangci.yaml index 366d4893f20..65f91b910bf 100644 --- a/vendor/github.com/cilium/ebpf/.golangci.yaml +++ b/vendor/github.com/cilium/ebpf/.golangci.yaml @@ -11,9 +11,3 @@ linters: - typecheck - unused - gofmt -linters-settings: - goimports: - # A comma-separated list of prefixes, which, if set, checks import paths - # with the given prefixes are grouped after 3rd-party packages. - # Default: "" - local-prefixes: github.com/cilium/ebpf diff --git a/vendor/github.com/cilium/ebpf/CODEOWNERS b/vendor/github.com/cilium/ebpf/CODEOWNERS index 0f76dce85c8..ca65d23c09d 100644 --- a/vendor/github.com/cilium/ebpf/CODEOWNERS +++ b/vendor/github.com/cilium/ebpf/CODEOWNERS @@ -9,5 +9,3 @@ ringbuf/ @florianl btf/ @dylandreimerink cmd/bpf2go/ @mejedi - -docs/ @ti-mo diff --git a/vendor/github.com/cilium/ebpf/Makefile b/vendor/github.com/cilium/ebpf/Makefile index e0fe9749206..d355eea71ca 100644 --- a/vendor/github.com/cilium/ebpf/Makefile +++ b/vendor/github.com/cilium/ebpf/Makefile @@ -39,18 +39,16 @@ TARGETS := \ testdata/subprog_reloc \ testdata/fwd_decl \ testdata/kconfig \ - testdata/ksym \ + testdata/kconfig_config \ testdata/kfunc \ testdata/invalid-kfunc \ testdata/kfunc-kmod \ testdata/constants \ testdata/errors \ - testdata/variables \ btf/testdata/relocs \ btf/testdata/relocs_read \ btf/testdata/relocs_read_tgt \ btf/testdata/relocs_enum \ - btf/testdata/tags \ cmd/bpf2go/testdata/minimal .PHONY: all clean container-all container-shell generate @@ -59,7 +57,7 @@ TARGETS := \ # Build all ELF binaries using a containerized LLVM toolchain. container-all: - +${CONTAINER_ENGINE} run --rm -ti ${CONTAINER_RUN_ARGS} \ + +${CONTAINER_ENGINE} run --rm -t ${CONTAINER_RUN_ARGS} \ -v "${REPODIR}":/ebpf -w /ebpf --env MAKEFLAGS \ --env HOME="/tmp" \ --env BPF2GO_CC="$(CLANG)" \ diff --git a/vendor/github.com/cilium/ebpf/README.md b/vendor/github.com/cilium/ebpf/README.md index 8238256c8ed..85871db1ae3 100644 --- a/vendor/github.com/cilium/ebpf/README.md +++ b/vendor/github.com/cilium/ebpf/README.md @@ -53,7 +53,6 @@ This library includes the following packages: * [rlimit](https://pkg.go.dev/github.com/cilium/ebpf/rlimit) provides a convenient API to lift the `RLIMIT_MEMLOCK` constraint on kernels before 5.11. * [btf](https://pkg.go.dev/github.com/cilium/ebpf/btf) allows reading the BPF Type Format. -* [pin](https://pkg.go.dev/github.com/cilium/ebpf/pin) provides APIs for working with pinned objects on bpffs. ## Requirements diff --git a/vendor/github.com/cilium/ebpf/asm/instruction.go b/vendor/github.com/cilium/ebpf/asm/instruction.go index 86b384c02a9..67cd39d6f67 100644 --- a/vendor/github.com/cilium/ebpf/asm/instruction.go +++ b/vendor/github.com/cilium/ebpf/asm/instruction.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/cilium/ebpf/internal/sys" + "github.com/cilium/ebpf/internal/unix" ) // InstructionSize is the size of a BPF instruction in bytes @@ -803,7 +804,7 @@ func (insns Instructions) Tag(bo binary.ByteOrder) (string, error) { return "", fmt.Errorf("instruction %d: %w", i, err) } } - return hex.EncodeToString(h.Sum(nil)[:sys.BPF_TAG_SIZE]), nil + return hex.EncodeToString(h.Sum(nil)[:unix.BPF_TAG_SIZE]), nil } // encodeFunctionReferences populates the Offset (or Constant, depending on diff --git a/vendor/github.com/cilium/ebpf/btf/btf.go b/vendor/github.com/cilium/ebpf/btf/btf.go index 880c5ade0c1..671f680b2af 100644 --- a/vendor/github.com/cilium/ebpf/btf/btf.go +++ b/vendor/github.com/cilium/ebpf/btf/btf.go @@ -443,19 +443,13 @@ func fixupDatasec(types []Type, sectionSizes map[string]uint32, offsets map[symb // Some Datasecs are virtual and don't have corresponding ELF sections. switch name { case ".ksyms": - // .ksyms describes forward declarations of kfunc signatures, as well as - // references to kernel symbols. + // .ksyms describes forward declarations of kfunc signatures. // Nothing to fix up, all sizes and offsets are 0. for _, vsi := range ds.Vars { - switch t := vsi.Type.(type) { - case *Func: - continue - case *Var: - if _, ok := t.Type.(*Void); !ok { - return fmt.Errorf("data section %s: expected %s to be *Void, not %T: %w", name, vsi.Type.TypeName(), vsi.Type, ErrNotSupported) - } - default: - return fmt.Errorf("data section %s: expected to be either *btf.Func or *btf.Var, not %T: %w", name, vsi.Type, ErrNotSupported) + _, ok := vsi.Type.(*Func) + if !ok { + // Only Funcs are supported in the .ksyms Datasec. + return fmt.Errorf("data section %s: expected *btf.Func, not %T: %w", name, vsi.Type, ErrNotSupported) } } @@ -701,13 +695,5 @@ func (iter *TypesIterator) Next() bool { iter.Type, ok = iter.spec.typeByID(iter.id) iter.id++ iter.done = !ok - if !iter.done { - // Skip declTags, during unmarshaling declTags become `Tags` fields of other types. - // We keep them in the spec to avoid holes in the ID space, but for the purposes of - // iteration, they are not useful to the user. - if _, ok := iter.Type.(*declTag); ok { - return iter.Next() - } - } return !iter.done } diff --git a/vendor/github.com/cilium/ebpf/btf/btf_types.go b/vendor/github.com/cilium/ebpf/btf/btf_types.go index 320311b3320..f0e327abc0e 100644 --- a/vendor/github.com/cilium/ebpf/btf/btf_types.go +++ b/vendor/github.com/cilium/ebpf/btf/btf_types.go @@ -39,7 +39,6 @@ const ( kindFloat // Float // Added 5.16 kindDeclTag // DeclTag - // Added 5.17 kindTypeTag // TypeTag // Added 6.0 kindEnum64 // Enum64 diff --git a/vendor/github.com/cilium/ebpf/btf/ext_info.go b/vendor/github.com/cilium/ebpf/btf/ext_info.go index 2c684fe2a79..eb9044badf2 100644 --- a/vendor/github.com/cilium/ebpf/btf/ext_info.go +++ b/vendor/github.com/cilium/ebpf/btf/ext_info.go @@ -16,8 +16,8 @@ import ( // ExtInfos contains ELF section metadata. type ExtInfos struct { // The slices are sorted by offset in ascending order. - funcInfos map[string]FuncOffsets - lineInfos map[string]LineOffsets + funcInfos map[string]FuncInfos + lineInfos map[string]LineInfos relocationInfos map[string]CORERelocationInfos } @@ -58,9 +58,9 @@ func loadExtInfos(r io.ReaderAt, bo binary.ByteOrder, spec *Spec) (*ExtInfos, er return nil, fmt.Errorf("parsing BTF function info: %w", err) } - funcInfos := make(map[string]FuncOffsets, len(btfFuncInfos)) + funcInfos := make(map[string]FuncInfos, len(btfFuncInfos)) for section, bfis := range btfFuncInfos { - funcInfos[section], err = newFuncOffsets(bfis, spec) + funcInfos[section], err = newFuncInfos(bfis, spec) if err != nil { return nil, fmt.Errorf("section %s: func infos: %w", section, err) } @@ -72,7 +72,7 @@ func loadExtInfos(r io.ReaderAt, bo binary.ByteOrder, spec *Spec) (*ExtInfos, er return nil, fmt.Errorf("parsing BTF line info: %w", err) } - lineInfos := make(map[string]LineOffsets, len(btfLineInfos)) + lineInfos := make(map[string]LineInfos, len(btfLineInfos)) for section, blis := range btfLineInfos { lineInfos[section], err = newLineInfos(blis, spec.strings) if err != nil { @@ -102,10 +102,8 @@ func loadExtInfos(r io.ReaderAt, bo binary.ByteOrder, spec *Spec) (*ExtInfos, er return &ExtInfos{funcInfos, lineInfos, coreRelos}, nil } -type ( - funcInfoMeta struct{} - coreRelocationMeta struct{} -) +type funcInfoMeta struct{} +type coreRelocationMeta struct{} // Assign per-section metadata from BTF to a section's instructions. func (ei *ExtInfos) Assign(insns asm.Instructions, section string) { @@ -119,20 +117,20 @@ func (ei *ExtInfos) Assign(insns asm.Instructions, section string) { // Assign per-instruction metadata to the instructions in insns. func AssignMetadataToInstructions( insns asm.Instructions, - funcInfos FuncOffsets, - lineInfos LineOffsets, + funcInfos FuncInfos, + lineInfos LineInfos, reloInfos CORERelocationInfos, ) { iter := insns.Iterate() for iter.Next() { - if len(funcInfos) > 0 && funcInfos[0].Offset == iter.Offset { - *iter.Ins = WithFuncMetadata(*iter.Ins, funcInfos[0].Func) - funcInfos = funcInfos[1:] + if len(funcInfos.infos) > 0 && funcInfos.infos[0].offset == iter.Offset { + *iter.Ins = WithFuncMetadata(*iter.Ins, funcInfos.infos[0].fn) + funcInfos.infos = funcInfos.infos[1:] } - if len(lineInfos) > 0 && lineInfos[0].Offset == iter.Offset { - *iter.Ins = iter.Ins.WithSource(lineInfos[0].Line) - lineInfos = lineInfos[1:] + if len(lineInfos.infos) > 0 && lineInfos.infos[0].offset == iter.Offset { + *iter.Ins = iter.Ins.WithSource(lineInfos.infos[0].line) + lineInfos.infos = lineInfos.infos[1:] } if len(reloInfos.infos) > 0 && reloInfos.infos[0].offset == iter.Offset { @@ -161,9 +159,9 @@ marshal: var fiBuf, liBuf bytes.Buffer for { if fn := FuncMetadata(iter.Ins); fn != nil { - fi := &FuncOffset{ - Func: fn, - Offset: iter.Offset, + fi := &funcInfo{ + fn: fn, + offset: iter.Offset, } if err := fi.marshal(&fiBuf, b); err != nil { return nil, nil, fmt.Errorf("write func info: %w", err) @@ -180,9 +178,9 @@ marshal: } } - li := &LineOffset{ - Offset: iter.Offset, - Line: line, + li := &lineInfo{ + line: line, + offset: iter.Offset, } if err := li.marshal(&liBuf, b); err != nil { return nil, nil, fmt.Errorf("write line info: %w", err) @@ -335,17 +333,17 @@ func parseExtInfoRecordSize(r io.Reader, bo binary.ByteOrder) (uint32, error) { return recordSize, nil } -// FuncOffsets is a sorted slice of FuncOffset. -type FuncOffsets []FuncOffset +// FuncInfos contains a sorted list of func infos. +type FuncInfos struct { + infos []funcInfo +} // The size of a FuncInfo in BTF wire format. var FuncInfoSize = uint32(binary.Size(bpfFuncInfo{})) -// FuncOffset represents a [btf.Func] and its raw instruction offset within a -// BPF program. -type FuncOffset struct { - Offset asm.RawInstructionOffset - Func *Func +type funcInfo struct { + fn *Func + offset asm.RawInstructionOffset } type bpfFuncInfo struct { @@ -354,7 +352,7 @@ type bpfFuncInfo struct { TypeID TypeID } -func newFuncOffset(fi bpfFuncInfo, spec *Spec) (*FuncOffset, error) { +func newFuncInfo(fi bpfFuncInfo, spec *Spec) (*funcInfo, error) { typ, err := spec.TypeByID(fi.TypeID) if err != nil { return nil, err @@ -370,32 +368,31 @@ func newFuncOffset(fi bpfFuncInfo, spec *Spec) (*FuncOffset, error) { return nil, fmt.Errorf("func with type ID %d doesn't have a name", fi.TypeID) } - return &FuncOffset{ - asm.RawInstructionOffset(fi.InsnOff), + return &funcInfo{ fn, + asm.RawInstructionOffset(fi.InsnOff), }, nil } -func newFuncOffsets(bfis []bpfFuncInfo, spec *Spec) (FuncOffsets, error) { - fos := make(FuncOffsets, 0, len(bfis)) - +func newFuncInfos(bfis []bpfFuncInfo, spec *Spec) (FuncInfos, error) { + fis := FuncInfos{ + infos: make([]funcInfo, 0, len(bfis)), + } for _, bfi := range bfis { - fi, err := newFuncOffset(bfi, spec) + fi, err := newFuncInfo(bfi, spec) if err != nil { - return FuncOffsets{}, fmt.Errorf("offset %d: %w", bfi.InsnOff, err) + return FuncInfos{}, fmt.Errorf("offset %d: %w", bfi.InsnOff, err) } - fos = append(fos, *fi) + fis.infos = append(fis.infos, *fi) } - sort.Slice(fos, func(i, j int) bool { - return fos[i].Offset <= fos[j].Offset + sort.Slice(fis.infos, func(i, j int) bool { + return fis.infos[i].offset <= fis.infos[j].offset }) - return fos, nil + return fis, nil } -// LoadFuncInfos parses BTF func info from kernel wire format into a -// [FuncOffsets], a sorted slice of [btf.Func]s of (sub)programs within a BPF -// program with their corresponding raw instruction offsets. -func LoadFuncInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec *Spec) (FuncOffsets, error) { +// LoadFuncInfos parses BTF func info in kernel wire format. +func LoadFuncInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec *Spec) (FuncInfos, error) { fis, err := parseFuncInfoRecords( reader, bo, @@ -404,20 +401,20 @@ func LoadFuncInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec false, ) if err != nil { - return FuncOffsets{}, fmt.Errorf("parsing BTF func info: %w", err) + return FuncInfos{}, fmt.Errorf("parsing BTF func info: %w", err) } - return newFuncOffsets(fis, spec) + return newFuncInfos(fis, spec) } // marshal into the BTF wire format. -func (fi *FuncOffset) marshal(w *bytes.Buffer, b *Builder) error { - id, err := b.Add(fi.Func) +func (fi *funcInfo) marshal(w *bytes.Buffer, b *Builder) error { + id, err := b.Add(fi.fn) if err != nil { return err } bfi := bpfFuncInfo{ - InsnOff: uint32(fi.Offset), + InsnOff: uint32(fi.offset), TypeID: id, } buf := make([]byte, FuncInfoSize) @@ -518,13 +515,14 @@ func (li *Line) String() string { return li.line } -// LineOffsets contains a sorted list of line infos. -type LineOffsets []LineOffset +// LineInfos contains a sorted list of line infos. +type LineInfos struct { + infos []lineInfo +} -// LineOffset represents a line info and its raw instruction offset. -type LineOffset struct { - Offset asm.RawInstructionOffset - Line *Line +type lineInfo struct { + line *Line + offset asm.RawInstructionOffset } // Constants for the format of bpfLineInfo.LineCol. @@ -543,7 +541,7 @@ type bpfLineInfo struct { } // LoadLineInfos parses BTF line info in kernel wire format. -func LoadLineInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec *Spec) (LineOffsets, error) { +func LoadLineInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec *Spec) (LineInfos, error) { lis, err := parseLineInfoRecords( reader, bo, @@ -552,55 +550,57 @@ func LoadLineInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec false, ) if err != nil { - return LineOffsets{}, fmt.Errorf("parsing BTF line info: %w", err) + return LineInfos{}, fmt.Errorf("parsing BTF line info: %w", err) } return newLineInfos(lis, spec.strings) } -func newLineInfo(li bpfLineInfo, strings *stringTable) (LineOffset, error) { +func newLineInfo(li bpfLineInfo, strings *stringTable) (lineInfo, error) { line, err := strings.Lookup(li.LineOff) if err != nil { - return LineOffset{}, fmt.Errorf("lookup of line: %w", err) + return lineInfo{}, fmt.Errorf("lookup of line: %w", err) } fileName, err := strings.Lookup(li.FileNameOff) if err != nil { - return LineOffset{}, fmt.Errorf("lookup of filename: %w", err) + return lineInfo{}, fmt.Errorf("lookup of filename: %w", err) } lineNumber := li.LineCol >> bpfLineShift lineColumn := li.LineCol & bpfColumnMax - return LineOffset{ - asm.RawInstructionOffset(li.InsnOff), + return lineInfo{ &Line{ fileName, line, lineNumber, lineColumn, }, + asm.RawInstructionOffset(li.InsnOff), }, nil } -func newLineInfos(blis []bpfLineInfo, strings *stringTable) (LineOffsets, error) { - lis := make([]LineOffset, 0, len(blis)) +func newLineInfos(blis []bpfLineInfo, strings *stringTable) (LineInfos, error) { + lis := LineInfos{ + infos: make([]lineInfo, 0, len(blis)), + } for _, bli := range blis { li, err := newLineInfo(bli, strings) if err != nil { - return LineOffsets{}, fmt.Errorf("offset %d: %w", bli.InsnOff, err) + return LineInfos{}, fmt.Errorf("offset %d: %w", bli.InsnOff, err) } - lis = append(lis, li) + lis.infos = append(lis.infos, li) } - sort.Slice(lis, func(i, j int) bool { - return lis[i].Offset <= lis[j].Offset + sort.Slice(lis.infos, func(i, j int) bool { + return lis.infos[i].offset <= lis.infos[j].offset }) return lis, nil } // marshal writes the binary representation of the LineInfo to w. -func (li *LineOffset) marshal(w *bytes.Buffer, b *Builder) error { - line := li.Line +func (li *lineInfo) marshal(w *bytes.Buffer, b *Builder) error { + line := li.line if line.lineNumber > bpfLineMax { return fmt.Errorf("line %d exceeds %d", line.lineNumber, bpfLineMax) } @@ -620,7 +620,7 @@ func (li *LineOffset) marshal(w *bytes.Buffer, b *Builder) error { } bli := bpfLineInfo{ - uint32(li.Offset), + uint32(li.offset), fileNameOff, lineOff, (line.lineNumber << bpfLineShift) | line.lineColumn, @@ -799,7 +799,7 @@ func parseCORERelos(r io.Reader, bo binary.ByteOrder, strings *stringTable) (map return nil, err } - records, err := parseCOREReloRecords(r, bo, infoHeader.NumInfo) + records, err := parseCOREReloRecords(r, bo, recordSize, infoHeader.NumInfo) if err != nil { return nil, fmt.Errorf("section %v: %w", secName, err) } @@ -811,7 +811,7 @@ func parseCORERelos(r io.Reader, bo binary.ByteOrder, strings *stringTable) (map // parseCOREReloRecords parses a stream of CO-RE relocation entries into a // coreRelos. These records appear after a btf_ext_info_sec header in the // core_relos sub-section of .BTF.ext. -func parseCOREReloRecords(r io.Reader, bo binary.ByteOrder, recordNum uint32) ([]bpfCORERelo, error) { +func parseCOREReloRecords(r io.Reader, bo binary.ByteOrder, recordSize uint32, recordNum uint32) ([]bpfCORERelo, error) { var out []bpfCORERelo var relo bpfCORERelo diff --git a/vendor/github.com/cilium/ebpf/btf/feature.go b/vendor/github.com/cilium/ebpf/btf/feature.go index e71c707fe4d..6feb08dfbb0 100644 --- a/vendor/github.com/cilium/ebpf/btf/feature.go +++ b/vendor/github.com/cilium/ebpf/btf/feature.go @@ -11,19 +11,19 @@ import ( // haveBTF attempts to load a BTF blob containing an Int. It should pass on any // kernel that supports BPF_BTF_LOAD. -var haveBTF = internal.NewFeatureTest("BTF", func() error { +var haveBTF = internal.NewFeatureTest("BTF", "4.18", func() error { // 0-length anonymous integer err := probeBTF(&Int{}) if errors.Is(err, unix.EINVAL) || errors.Is(err, unix.EPERM) { return internal.ErrNotSupported } return err -}, "4.18") +}) // haveMapBTF attempts to load a minimal BTF blob containing a Var. It is // used as a proxy for .bss, .data and .rodata map support, which generally // come with a Var and Datasec. These were introduced in Linux 5.2. -var haveMapBTF = internal.NewFeatureTest("Map BTF (Var/Datasec)", func() error { +var haveMapBTF = internal.NewFeatureTest("Map BTF (Var/Datasec)", "5.2", func() error { if err := haveBTF(); err != nil { return err } @@ -40,12 +40,12 @@ var haveMapBTF = internal.NewFeatureTest("Map BTF (Var/Datasec)", func() error { return internal.ErrNotSupported } return err -}, "5.2") +}) // haveProgBTF attempts to load a BTF blob containing a Func and FuncProto. It // is used as a proxy for ext_info (func_info) support, which depends on // Func(Proto) by definition. -var haveProgBTF = internal.NewFeatureTest("Program BTF (func/line_info)", func() error { +var haveProgBTF = internal.NewFeatureTest("Program BTF (func/line_info)", "5.0", func() error { if err := haveBTF(); err != nil { return err } @@ -60,9 +60,9 @@ var haveProgBTF = internal.NewFeatureTest("Program BTF (func/line_info)", func() return internal.ErrNotSupported } return err -}, "5.0") +}) -var haveFuncLinkage = internal.NewFeatureTest("BTF func linkage", func() error { +var haveFuncLinkage = internal.NewFeatureTest("BTF func linkage", "5.6", func() error { if err := haveProgBTF(); err != nil { return err } @@ -78,44 +78,9 @@ var haveFuncLinkage = internal.NewFeatureTest("BTF func linkage", func() error { return internal.ErrNotSupported } return err -}, "5.6") +}) -var haveDeclTags = internal.NewFeatureTest("BTF decl tags", func() error { - if err := haveBTF(); err != nil { - return err - } - - t := &Typedef{ - Name: "a", - Type: &Int{}, - Tags: []string{"a"}, - } - - err := probeBTF(t) - if errors.Is(err, unix.EINVAL) { - return internal.ErrNotSupported - } - return err -}, "5.16") - -var haveTypeTags = internal.NewFeatureTest("BTF type tags", func() error { - if err := haveBTF(); err != nil { - return err - } - - t := &TypeTag{ - Type: &Int{}, - Value: "a", - } - - err := probeBTF(t) - if errors.Is(err, unix.EINVAL) { - return internal.ErrNotSupported - } - return err -}, "5.17") - -var haveEnum64 = internal.NewFeatureTest("ENUM64", func() error { +var haveEnum64 = internal.NewFeatureTest("ENUM64", "6.0", func() error { if err := haveBTF(); err != nil { return err } @@ -132,7 +97,7 @@ var haveEnum64 = internal.NewFeatureTest("ENUM64", func() error { return internal.ErrNotSupported } return err -}, "6.0") +}) func probeBTF(typ Type) error { b, err := NewBuilder([]Type{typ}) diff --git a/vendor/github.com/cilium/ebpf/btf/format.go b/vendor/github.com/cilium/ebpf/btf/format.go index 3e0dedaa2bd..5e581b4a851 100644 --- a/vendor/github.com/cilium/ebpf/btf/format.go +++ b/vendor/github.com/cilium/ebpf/btf/format.go @@ -161,9 +161,6 @@ func (gf *GoFormatter) writeTypeLit(typ Type, depth int) error { case *Datasec: err = gf.writeDatasecLit(v, depth) - case *Var: - err = gf.writeTypeLit(v.Type, depth) - default: return fmt.Errorf("type %T: %w", v, ErrNotSupported) } diff --git a/vendor/github.com/cilium/ebpf/btf/kernel.go b/vendor/github.com/cilium/ebpf/btf/kernel.go index 1a9321f054c..8584ebcb932 100644 --- a/vendor/github.com/cilium/ebpf/btf/kernel.go +++ b/vendor/github.com/cilium/ebpf/btf/kernel.go @@ -8,7 +8,7 @@ import ( "sync" "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/linux" + "github.com/cilium/ebpf/internal/kallsyms" ) var kernelBTF = struct { @@ -21,6 +21,8 @@ var kernelBTF = struct { // FlushKernelSpec removes any cached kernel type information. func FlushKernelSpec() { + kallsyms.FlushKernelModuleCache() + kernelBTF.Lock() defer kernelBTF.Unlock() @@ -128,7 +130,7 @@ func loadKernelModuleSpec(module string, base *Spec) (*Spec, error) { // findVMLinux scans multiple well-known paths for vmlinux kernel images. func findVMLinux() (*os.File, error) { - release, err := linux.KernelRelease() + release, err := internal.KernelRelease() if err != nil { return nil, err } diff --git a/vendor/github.com/cilium/ebpf/btf/marshal.go b/vendor/github.com/cilium/ebpf/btf/marshal.go index d7204e62476..f14cfa6e973 100644 --- a/vendor/github.com/cilium/ebpf/btf/marshal.go +++ b/vendor/github.com/cilium/ebpf/btf/marshal.go @@ -18,10 +18,6 @@ type MarshalOptions struct { Order binary.ByteOrder // Remove function linkage information for compatibility with <5.6 kernels. StripFuncLinkage bool - // Replace decl tags with a placeholder for compatibility with <5.16 kernels. - ReplaceDeclTags bool - // Replace TypeTags with a placeholder for compatibility with <5.17 kernels. - ReplaceTypeTags bool // Replace Enum64 with a placeholder for compatibility with <6.0 kernels. ReplaceEnum64 bool // Prevent the "No type found" error when loading BTF without any types. @@ -33,8 +29,6 @@ func KernelMarshalOptions() *MarshalOptions { return &MarshalOptions{ Order: internal.NativeEndian, StripFuncLinkage: haveFuncLinkage() != nil, - ReplaceDeclTags: haveDeclTags() != nil, - ReplaceTypeTags: haveTypeTags() != nil, ReplaceEnum64: haveEnum64() != nil, PreventNoTypeFound: true, // All current kernels require this. } @@ -324,7 +318,15 @@ func (e *encoder) deflateType(typ Type) (err error) { return errors.New("Void is implicit in BTF wire format") case *Int: - e.deflateInt(&raw, v) + raw.SetKind(kindInt) + raw.SetSize(v.Size) + + var bi btfInt + bi.SetEncoding(v.Encoding) + // We need to set bits in addition to size, since btf_type_int_is_regular + // otherwise flags this as a bitfield. + bi.SetBits(byte(v.Size) * 8) + raw.data = bi case *Pointer: raw.SetKind(kindPointer) @@ -366,7 +368,8 @@ func (e *encoder) deflateType(typ Type) (err error) { raw.SetType(e.id(v.Type)) case *Const: - e.deflateConst(&raw, v) + raw.SetKind(kindConst) + raw.SetType(e.id(v.Type)) case *Restrict: raw.SetKind(kindRestrict) @@ -401,10 +404,15 @@ func (e *encoder) deflateType(typ Type) (err error) { raw.SetSize(v.Size) case *declTag: - err = e.deflateDeclTag(&raw, v) + raw.SetKind(kindDeclTag) + raw.SetType(e.id(v.Type)) + raw.data = &btfDeclTag{uint32(v.Index)} + raw.NameOff, err = e.strings.Add(v.Value) - case *TypeTag: - err = e.deflateTypeTag(&raw, v) + case *typeTag: + raw.SetKind(kindTypeTag) + raw.SetType(e.id(v.Type)) + raw.NameOff, err = e.strings.Add(v.Value) default: return fmt.Errorf("don't know how to deflate %T", v) @@ -417,57 +425,6 @@ func (e *encoder) deflateType(typ Type) (err error) { return raw.Marshal(e.buf, e.Order) } -func (e *encoder) deflateInt(raw *rawType, i *Int) { - raw.SetKind(kindInt) - raw.SetSize(i.Size) - - var bi btfInt - bi.SetEncoding(i.Encoding) - // We need to set bits in addition to size, since btf_type_int_is_regular - // otherwise flags this as a bitfield. - bi.SetBits(byte(i.Size) * 8) - raw.data = bi -} - -func (e *encoder) deflateDeclTag(raw *rawType, tag *declTag) (err error) { - // Replace a decl tag with an integer for compatibility with <5.16 kernels, - // following libbpf behaviour. - if e.ReplaceDeclTags { - typ := &Int{"decl_tag_placeholder", 1, Unsigned} - e.deflateInt(raw, typ) - - // Add the placeholder type name to the string table. The encoder added the - // original type name before this call. - raw.NameOff, err = e.strings.Add(typ.TypeName()) - return - } - - raw.SetKind(kindDeclTag) - raw.SetType(e.id(tag.Type)) - raw.data = &btfDeclTag{uint32(tag.Index)} - raw.NameOff, err = e.strings.Add(tag.Value) - return -} - -func (e *encoder) deflateConst(raw *rawType, c *Const) { - raw.SetKind(kindConst) - raw.SetType(e.id(c.Type)) -} - -func (e *encoder) deflateTypeTag(raw *rawType, tag *TypeTag) (err error) { - // Replace a type tag with a const qualifier for compatibility with <5.17 - // kernels, following libbpf behaviour. - if e.ReplaceTypeTags { - e.deflateConst(raw, &Const{tag.Type}) - return - } - - raw.SetKind(kindTypeTag) - raw.SetType(e.id(tag.Type)) - raw.NameOff, err = e.strings.Add(tag.Value) - return -} - func (e *encoder) deflateUnion(raw *rawType, union *Union) (err error) { raw.SetKind(kindUnion) raw.SetSize(union.Size) @@ -564,7 +521,7 @@ func (e *encoder) deflateEnum64(raw *rawType, enum *Enum) (err error) { }) } - return e.deflateUnion(raw, &Union{enum.Name, enum.Size, members, nil}) + return e.deflateUnion(raw, &Union{enum.Name, enum.Size, members}) } raw.SetKind(kindEnum64) diff --git a/vendor/github.com/cilium/ebpf/btf/traversal.go b/vendor/github.com/cilium/ebpf/btf/traversal.go index 13647d931ff..c39dc66e46c 100644 --- a/vendor/github.com/cilium/ebpf/btf/traversal.go +++ b/vendor/github.com/cilium/ebpf/btf/traversal.go @@ -40,12 +40,9 @@ func children(typ Type, yield func(child *Type) bool) bool { // Explicitly type switch on the most common types to allow the inliner to // do its work. This avoids allocating intermediate slices from walk() on // the heap. - var tags []string switch v := typ.(type) { - case *Void, *Int, *Enum, *Fwd, *Float, *declTag: + case *Void, *Int, *Enum, *Fwd, *Float: // No children to traverse. - // declTags is declared as a leaf type since it's parsed into .Tags fields of other types - // during unmarshaling. case *Pointer: if !yield(&v.Target) { return false @@ -62,32 +59,17 @@ func children(typ Type, yield func(child *Type) bool) bool { if !yield(&v.Members[i].Type) { return false } - for _, t := range v.Members[i].Tags { - var tag Type = &declTag{v, t, i} - if !yield(&tag) { - return false - } - } } - tags = v.Tags case *Union: for i := range v.Members { if !yield(&v.Members[i].Type) { return false } - for _, t := range v.Members[i].Tags { - var tag Type = &declTag{v, t, i} - if !yield(&tag) { - return false - } - } } - tags = v.Tags case *Typedef: if !yield(&v.Type) { return false } - tags = v.Tags case *Volatile: if !yield(&v.Type) { return false @@ -104,20 +86,6 @@ func children(typ Type, yield func(child *Type) bool) bool { if !yield(&v.Type) { return false } - if fp, ok := v.Type.(*FuncProto); ok { - for i := range fp.Params { - if len(v.ParamTags) <= i { - continue - } - for _, t := range v.ParamTags[i] { - var tag Type = &declTag{v, t, i} - if !yield(&tag) { - return false - } - } - } - } - tags = v.Tags case *FuncProto: if !yield(&v.Return) { return false @@ -131,14 +99,17 @@ func children(typ Type, yield func(child *Type) bool) bool { if !yield(&v.Type) { return false } - tags = v.Tags case *Datasec: for i := range v.Vars { if !yield(&v.Vars[i].Type) { return false } } - case *TypeTag: + case *declTag: + if !yield(&v.Type) { + return false + } + case *typeTag: if !yield(&v.Type) { return false } @@ -148,12 +119,5 @@ func children(typ Type, yield func(child *Type) bool) bool { panic(fmt.Sprintf("don't know how to walk Type %T", v)) } - for _, t := range tags { - var tag Type = &declTag{typ, t, -1} - if !yield(&tag) { - return false - } - } - return true } diff --git a/vendor/github.com/cilium/ebpf/btf/types.go b/vendor/github.com/cilium/ebpf/btf/types.go index dbcdf9dd7aa..a3397460b9d 100644 --- a/vendor/github.com/cilium/ebpf/btf/types.go +++ b/vendor/github.com/cilium/ebpf/btf/types.go @@ -67,7 +67,7 @@ var ( _ Type = (*Datasec)(nil) _ Type = (*Float)(nil) _ Type = (*declTag)(nil) - _ Type = (*TypeTag)(nil) + _ Type = (*typeTag)(nil) _ Type = (*cycle)(nil) ) @@ -169,7 +169,6 @@ type Struct struct { // The size of the struct including padding, in bytes Size uint32 Members []Member - Tags []string } func (s *Struct) Format(fs fmt.State, verb rune) { @@ -183,7 +182,6 @@ func (s *Struct) size() uint32 { return s.Size } func (s *Struct) copy() Type { cpy := *s cpy.Members = copyMembers(s.Members) - cpy.Tags = copyTags(cpy.Tags) return &cpy } @@ -197,7 +195,6 @@ type Union struct { // The size of the union including padding, in bytes. Size uint32 Members []Member - Tags []string } func (u *Union) Format(fs fmt.State, verb rune) { @@ -211,7 +208,6 @@ func (u *Union) size() uint32 { return u.Size } func (u *Union) copy() Type { cpy := *u cpy.Members = copyMembers(u.Members) - cpy.Tags = copyTags(cpy.Tags) return &cpy } @@ -222,18 +218,6 @@ func (u *Union) members() []Member { func copyMembers(orig []Member) []Member { cpy := make([]Member, len(orig)) copy(cpy, orig) - for i, member := range cpy { - cpy[i].Tags = copyTags(member.Tags) - } - return cpy -} - -func copyTags(orig []string) []string { - if orig == nil { // preserve nil vs zero-len slice distinction - return nil - } - cpy := make([]string, len(orig)) - copy(cpy, orig) return cpy } @@ -263,7 +247,6 @@ type Member struct { Type Type Offset Bits BitfieldSize Bits - Tags []string } // Enum lists possible values. @@ -351,7 +334,6 @@ func (f *Fwd) matches(typ Type) bool { type Typedef struct { Name string Type Type - Tags []string } func (td *Typedef) Format(fs fmt.State, verb rune) { @@ -362,7 +344,6 @@ func (td *Typedef) TypeName() string { return td.Name } func (td *Typedef) copy() Type { cpy := *td - cpy.Tags = copyTags(td.Tags) return &cpy } @@ -422,12 +403,6 @@ type Func struct { Name string Type Type Linkage FuncLinkage - Tags []string - // ParamTags holds a list of tags for each parameter of the FuncProto to which `Type` points. - // If no tags are present for any param, the outer slice will be nil/len(ParamTags)==0. - // If at least 1 param has a tag, the outer slice will have the same length as the number of params. - // The inner slice contains the tags and may be nil/len(ParamTags[i])==0 if no tags are present for that param. - ParamTags [][]string } func FuncMetadata(ins *asm.Instruction) *Func { @@ -449,14 +424,6 @@ func (f *Func) TypeName() string { return f.Name } func (f *Func) copy() Type { cpy := *f - cpy.Tags = copyTags(f.Tags) - if f.ParamTags != nil { // preserve nil vs zero-len slice distinction - ptCopy := make([][]string, len(f.ParamTags)) - for i, tags := range f.ParamTags { - ptCopy[i] = copyTags(tags) - } - cpy.ParamTags = ptCopy - } return &cpy } @@ -489,7 +456,6 @@ type Var struct { Name string Type Type Linkage VarLinkage - Tags []string } func (v *Var) Format(fs fmt.State, verb rune) { @@ -500,7 +466,6 @@ func (v *Var) TypeName() string { return v.Name } func (v *Var) copy() Type { cpy := *v - cpy.Tags = copyTags(v.Tags) return &cpy } @@ -575,25 +540,19 @@ func (dt *declTag) copy() Type { return &cpy } -// TypeTag associates metadata with a pointer type. Tag types act as a custom -// modifier(const, restrict, volatile) for the target type. Unlike declTags, -// TypeTags are ordered so the order in which they are added matters. -// -// One of their uses is to mark pointers as `__kptr` meaning a pointer points -// to kernel memory. Adding a `__kptr` to pointers in map values allows you -// to store pointers to kernel memory in maps. -type TypeTag struct { +// typeTag associates metadata with a type. +type typeTag struct { Type Type Value string } -func (tt *TypeTag) Format(fs fmt.State, verb rune) { +func (tt *typeTag) Format(fs fmt.State, verb rune) { formatType(fs, verb, tt, "type=", tt.Type, "value=", tt.Value) } -func (tt *TypeTag) TypeName() string { return "" } -func (tt *TypeTag) qualify() Type { return tt.Type } -func (tt *TypeTag) copy() Type { +func (tt *typeTag) TypeName() string { return "" } +func (tt *typeTag) qualify() Type { return tt.Type } +func (tt *typeTag) copy() Type { cpy := *tt return &cpy } @@ -632,7 +591,7 @@ var ( _ qualifier = (*Const)(nil) _ qualifier = (*Restrict)(nil) _ qualifier = (*Volatile)(nil) - _ qualifier = (*TypeTag)(nil) + _ qualifier = (*typeTag)(nil) ) var errUnsizedType = errors.New("type is unsized") @@ -959,7 +918,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt if err != nil { return nil, fmt.Errorf("struct %s (id %d): %w", name, id, err) } - typ = &Struct{name, header.Size(), members, nil} + typ = &Struct{name, header.Size(), members} case kindUnion: vlen := header.Vlen() @@ -976,7 +935,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt if err != nil { return nil, fmt.Errorf("union %s (id %d): %w", name, id, err) } - typ = &Union{name, header.Size(), members, nil} + typ = &Union{name, header.Size(), members} case kindEnum: vlen := header.Vlen() @@ -1009,7 +968,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt typ = &Fwd{name, header.FwdKind()} case kindTypedef: - typedef := &Typedef{name, nil, nil} + typedef := &Typedef{name, nil} fixup(header.Type(), &typedef.Type) typ = typedef @@ -1029,7 +988,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt typ = restrict case kindFunc: - fn := &Func{name, nil, header.Linkage(), nil, nil} + fn := &Func{name, nil, header.Linkage()} fixup(header.Type(), &fn.Type) typ = fn @@ -1071,7 +1030,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt return nil, fmt.Errorf("can't read btfVariable, id: %d: %w", id, err) } - v := &Var{name, nil, VarLinkage(bVariable.Linkage), nil} + v := &Var{name, nil, VarLinkage(bVariable.Linkage)} fixup(header.Type(), &v.Type) typ = v @@ -1122,7 +1081,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt declTags = append(declTags, dt) case kindTypeTag: - tt := &TypeTag{nil, name} + tt := &typeTag{nil, name} fixup(header.Type(), &tt.Type) typ = tt @@ -1183,69 +1142,26 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt for _, dt := range declTags { switch t := dt.Type.(type) { - case *Var: - if dt.Index != -1 { - return nil, fmt.Errorf("type %s: component idx %d is not -1", dt, dt.Index) - } - t.Tags = append(t.Tags, dt.Value) - - case *Typedef: + case *Var, *Typedef: if dt.Index != -1 { - return nil, fmt.Errorf("type %s: component idx %d is not -1", dt, dt.Index) + return nil, fmt.Errorf("type %s: index %d is not -1", dt, dt.Index) } - t.Tags = append(t.Tags, dt.Value) case composite: - if dt.Index >= 0 { - members := t.members() - if dt.Index >= len(members) { - return nil, fmt.Errorf("type %s: component idx %d exceeds members of %s", dt, dt.Index, t) - } - - members[dt.Index].Tags = append(members[dt.Index].Tags, dt.Value) - continue - } - - if dt.Index == -1 { - switch t2 := t.(type) { - case *Struct: - t2.Tags = append(t2.Tags, dt.Value) - case *Union: - t2.Tags = append(t2.Tags, dt.Value) - } - - continue + if dt.Index >= len(t.members()) { + return nil, fmt.Errorf("type %s: index %d exceeds members of %s", dt, dt.Index, t) } - return nil, fmt.Errorf("type %s: decl tag for type %s has invalid component idx", dt, t) - case *Func: fp, ok := t.Type.(*FuncProto) if !ok { return nil, fmt.Errorf("type %s: %s is not a FuncProto", dt, t.Type) } - // Ensure the number of argument tag lists equals the number of arguments - if len(t.ParamTags) == 0 { - t.ParamTags = make([][]string, len(fp.Params)) - } - - if dt.Index >= 0 { - if dt.Index >= len(fp.Params) { - return nil, fmt.Errorf("type %s: component idx %d exceeds params of %s", dt, dt.Index, t) - } - - t.ParamTags[dt.Index] = append(t.ParamTags[dt.Index], dt.Value) - continue + if dt.Index >= len(fp.Params) { + return nil, fmt.Errorf("type %s: index %d exceeds params of %s", dt, dt.Index, t) } - if dt.Index == -1 { - t.Tags = append(t.Tags, dt.Value) - continue - } - - return nil, fmt.Errorf("type %s: decl tag for type %s has invalid component idx", dt, t) - default: return nil, fmt.Errorf("type %s: decl tag for type %s is not supported", dt, t) } @@ -1291,20 +1207,6 @@ func UnderlyingType(typ Type) Type { return &cycle{typ} } -// QualifiedType returns the type with all qualifiers removed. -func QualifiedType(typ Type) Type { - result := typ - for depth := 0; depth <= maxResolveDepth; depth++ { - switch v := (result).(type) { - case qualifier: - result = v.qualify() - default: - return result - } - } - return &cycle{typ} -} - // As returns typ if is of type T. Otherwise it peels qualifiers and Typedefs // until it finds a T. // diff --git a/vendor/github.com/cilium/ebpf/btf/workarounds.go b/vendor/github.com/cilium/ebpf/btf/workarounds.go index eb09047fb30..12a89b87eed 100644 --- a/vendor/github.com/cilium/ebpf/btf/workarounds.go +++ b/vendor/github.com/cilium/ebpf/btf/workarounds.go @@ -12,7 +12,7 @@ func datasecResolveWorkaround(b *Builder, ds *Datasec) error { } switch v.Type.(type) { - case *Typedef, *Volatile, *Const, *Restrict, *TypeTag: + case *Typedef, *Volatile, *Const, *Restrict, *typeTag: // NB: We must never call Add on a Datasec, otherwise we risk // infinite recursion. _, err := b.Add(v.Type) diff --git a/vendor/github.com/cilium/ebpf/collection.go b/vendor/github.com/cilium/ebpf/collection.go index 1bda110a401..b2cb214adce 100644 --- a/vendor/github.com/cilium/ebpf/collection.go +++ b/vendor/github.com/cilium/ebpf/collection.go @@ -10,10 +10,8 @@ import ( "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/btf" "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/kallsyms" "github.com/cilium/ebpf/internal/kconfig" - "github.com/cilium/ebpf/internal/linux" - "github.com/cilium/ebpf/internal/sys" + "github.com/cilium/ebpf/internal/sysenc" ) // CollectionOptions control loading a collection into the kernel. @@ -40,11 +38,6 @@ type CollectionSpec struct { Maps map[string]*MapSpec Programs map[string]*ProgramSpec - // Variables refer to global variables declared in the ELF. They can be read - // and modified freely before loading the Collection. Modifying them after - // loading has no effect on a running eBPF program. - Variables map[string]*VariableSpec - // Types holds type information about Maps and Programs. // Modifications to Types are currently undefined behaviour. Types *btf.Spec @@ -63,7 +56,6 @@ func (cs *CollectionSpec) Copy() *CollectionSpec { cpy := CollectionSpec{ Maps: make(map[string]*MapSpec, len(cs.Maps)), Programs: make(map[string]*ProgramSpec, len(cs.Programs)), - Variables: make(map[string]*VariableSpec, len(cs.Variables)), ByteOrder: cs.ByteOrder, Types: cs.Types.Copy(), } @@ -76,10 +68,6 @@ func (cs *CollectionSpec) Copy() *CollectionSpec { cpy.Programs[name] = spec.Copy() } - for name, spec := range cs.Variables { - cpy.Variables[name] = spec.copy(&cpy) - } - return &cpy } @@ -146,24 +134,65 @@ func (m *MissingConstantsError) Error() string { // From Linux 5.5 the verifier will use constants to eliminate dead code. // // Returns an error wrapping [MissingConstantsError] if a constant doesn't exist. -// -// Deprecated: Use [CollectionSpec.Variables] to interact with constants instead. -// RewriteConstants is now a wrapper around the VariableSpec API. func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error { - var missing []string - for n, c := range consts { - v, ok := cs.Variables[n] - if !ok { - missing = append(missing, n) + replaced := make(map[string]bool) + + for name, spec := range cs.Maps { + if !strings.HasPrefix(name, ".rodata") { continue } - if !v.Constant() { - return fmt.Errorf("variable %s is not a constant", n) + b, ds, err := spec.dataSection() + if errors.Is(err, errMapNoBTFValue) { + // Data sections without a BTF Datasec are valid, but don't support + // constant replacements. + continue + } + if err != nil { + return fmt.Errorf("map %s: %w", name, err) } - if err := v.Set(c); err != nil { - return fmt.Errorf("rewriting constant %s: %w", n, err) + // MapSpec.Copy() performs a shallow copy. Fully copy the byte slice + // to avoid any changes affecting other copies of the MapSpec. + cpy := make([]byte, len(b)) + copy(cpy, b) + + for _, v := range ds.Vars { + vname := v.Type.TypeName() + replacement, ok := consts[vname] + if !ok { + continue + } + + if _, ok := v.Type.(*btf.Var); !ok { + return fmt.Errorf("section %s: unexpected type %T for variable %s", name, v.Type, vname) + } + + if replaced[vname] { + return fmt.Errorf("section %s: duplicate variable %s", name, vname) + } + + if int(v.Offset+v.Size) > len(cpy) { + return fmt.Errorf("section %s: offset %d(+%d) for variable %s is out of bounds", name, v.Offset, v.Size, vname) + } + + b, err := sysenc.Marshal(replacement, int(v.Size)) + if err != nil { + return fmt.Errorf("marshaling constant replacement %s: %w", vname, err) + } + + b.CopyTo(cpy[v.Offset : v.Offset+v.Size]) + + replaced[vname] = true + } + + spec.Contents[0] = MapKV{Key: uint32(0), Value: cpy} + } + + var missing []string + for c := range consts { + if !replaced[c] { + missing = append(missing, c) } } @@ -181,23 +210,25 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error // if this sounds useful. // // 'to' must be a pointer to a struct. A field of the -// struct is updated with values from Programs, Maps or Variables if it -// has an `ebpf` tag and its type is *ProgramSpec, *MapSpec or *VariableSpec. +// struct is updated with values from Programs or Maps if it +// has an `ebpf` tag and its type is *ProgramSpec or *MapSpec. // The tag's value specifies the name of the program or map as // found in the CollectionSpec. // // struct { -// Foo *ebpf.ProgramSpec `ebpf:"xdp_foo"` -// Bar *ebpf.MapSpec `ebpf:"bar_map"` -// Var *ebpf.VariableSpec `ebpf:"some_var"` +// Foo *ebpf.ProgramSpec `ebpf:"xdp_foo"` +// Bar *ebpf.MapSpec `ebpf:"bar_map"` // Ignored int // } // // Returns an error if any of the eBPF objects can't be found, or -// if the same Spec is assigned multiple times. +// if the same MapSpec or ProgramSpec is assigned multiple times. func (cs *CollectionSpec) Assign(to interface{}) error { + // Assign() only supports assigning ProgramSpecs and MapSpecs, + // so doesn't load any resources into the kernel. getValue := func(typ reflect.Type, name string) (interface{}, error) { switch typ { + case reflect.TypeOf((*ProgramSpec)(nil)): if p := cs.Programs[name]; p != nil { return p, nil @@ -210,12 +241,6 @@ func (cs *CollectionSpec) Assign(to interface{}) error { } return nil, fmt.Errorf("missing map %q", name) - case reflect.TypeOf((*VariableSpec)(nil)): - if v := cs.Variables[name]; v != nil { - return v, nil - } - return nil, fmt.Errorf("missing variable %q", name) - default: return nil, fmt.Errorf("unsupported type %s", typ) } @@ -261,7 +286,6 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) // Support assigning Programs and Maps, lazy-loading the required objects. assignedMaps := make(map[string]bool) assignedProgs := make(map[string]bool) - assignedVars := make(map[string]bool) getValue := func(typ reflect.Type, name string) (interface{}, error) { switch typ { @@ -274,10 +298,6 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) assignedMaps[name] = true return loader.loadMap(name) - case reflect.TypeOf((*Variable)(nil)): - assignedVars[name] = true - return loader.loadVariable(name) - default: return nil, fmt.Errorf("unsupported type %s", typ) } @@ -318,22 +338,15 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) for p := range assignedProgs { delete(loader.programs, p) } - for p := range assignedVars { - delete(loader.vars, p) - } return nil } -// Collection is a collection of live BPF resources present in the kernel. +// Collection is a collection of Programs and Maps associated +// with their symbols type Collection struct { Programs map[string]*Program Maps map[string]*Map - - // Variables contains global variables used by the Collection's program(s). On - // kernels older than 5.5, most interactions with Variables return - // [ErrNotSupported]. - Variables map[string]*Variable } // NewCollection creates a Collection from the given spec, creating and @@ -374,26 +387,19 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co } } - for varName := range spec.Variables { - if _, err := loader.loadVariable(varName); err != nil { - return nil, err - } - } - // Maps can contain Program and Map stubs, so populate them after // all Maps and Programs have been successfully loaded. if err := loader.populateDeferredMaps(); err != nil { return nil, err } - // Prevent loader.cleanup from closing maps, programs and vars. - maps, progs, vars := loader.maps, loader.programs, loader.vars - loader.maps, loader.programs, loader.vars = nil, nil, nil + // Prevent loader.cleanup from closing maps and programs. + maps, progs := loader.maps, loader.programs + loader.maps, loader.programs = nil, nil return &Collection{ progs, maps, - vars, }, nil } @@ -402,7 +408,6 @@ type collectionLoader struct { opts *CollectionOptions maps map[string]*Map programs map[string]*Program - vars map[string]*Variable } func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collectionLoader, error) { @@ -422,58 +427,14 @@ func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collec } } - if err := populateKallsyms(coll.Programs); err != nil { - return nil, fmt.Errorf("populating kallsyms caches: %w", err) - } - return &collectionLoader{ coll, opts, make(map[string]*Map), make(map[string]*Program), - make(map[string]*Variable), }, nil } -// populateKallsyms populates kallsyms caches, making lookups cheaper later on -// during individual program loading. Since we have less context available -// at those stages, we batch the lookups here instead to avoid redundant work. -func populateKallsyms(progs map[string]*ProgramSpec) error { - // Look up associated kernel modules for all symbols referenced by - // ProgramSpec.AttachTo for program types that support attaching to kmods. - mods := make(map[string]string) - for _, p := range progs { - if p.AttachTo != "" && p.targetsKernelModule() { - mods[p.AttachTo] = "" - } - } - if len(mods) != 0 { - if err := kallsyms.AssignModules(mods); err != nil { - return fmt.Errorf("getting modules from kallsyms: %w", err) - } - } - - // Look up addresses of all kernel symbols referenced by all programs. - addrs := make(map[string]uint64) - for _, p := range progs { - iter := p.Instructions.Iterate() - for iter.Next() { - ins := iter.Ins - meta, _ := ins.Metadata.Get(ksymMetaKey{}).(*ksymMeta) - if meta != nil { - addrs[meta.Name] = 0 - } - } - } - if len(addrs) != 0 { - if err := kallsyms.AssignAddresses(addrs); err != nil { - return fmt.Errorf("getting addresses from kallsyms: %w", err) - } - } - - return nil -} - // close all resources left over in the collectionLoader. func (cl *collectionLoader) close() { for _, m := range cl.maps { @@ -505,13 +466,6 @@ func (cl *collectionLoader) loadMap(mapName string) (*Map, error) { return m, nil } - // Defer setting the mmapable flag on maps until load time. This avoids the - // MapSpec having different flags on some kernel versions. Also avoid running - // syscalls during ELF loading, so platforms like wasm can also parse an ELF. - if isDataSection(mapSpec.Name) && haveMmapableMaps() == nil { - mapSpec.Flags |= sys.BPF_F_MMAPABLE - } - m, err := newMapWithOptions(mapSpec, cl.opts.Maps) if err != nil { return nil, fmt.Errorf("map %s: %w", mapName, err) @@ -583,58 +537,6 @@ func (cl *collectionLoader) loadProgram(progName string) (*Program, error) { return prog, nil } -func (cl *collectionLoader) loadVariable(varName string) (*Variable, error) { - if v := cl.vars[varName]; v != nil { - return v, nil - } - - varSpec := cl.coll.Variables[varName] - if varSpec == nil { - return nil, fmt.Errorf("unknown variable %s", varName) - } - - // Get the key of the VariableSpec's MapSpec in the CollectionSpec. - var mapName string - for n, ms := range cl.coll.Maps { - if ms == varSpec.m { - mapName = n - break - } - } - if mapName == "" { - return nil, fmt.Errorf("variable %s: underlying MapSpec %s was removed from CollectionSpec", varName, varSpec.m.Name) - } - - m, err := cl.loadMap(mapName) - if err != nil { - return nil, fmt.Errorf("variable %s: %w", varName, err) - } - - // If the kernel is too old or the underlying map was created without - // BPF_F_MMAPABLE, [Map.Memory] will return ErrNotSupported. In this case, - // emit a Variable with a nil Memory. This keeps Collection{Spec}.Variables - // consistent across systems with different feature sets without breaking - // LoadAndAssign. - mm, err := m.Memory() - if err != nil && !errors.Is(err, ErrNotSupported) { - return nil, fmt.Errorf("variable %s: getting memory for map %s: %w", varName, mapName, err) - } - - v, err := newVariable( - varSpec.name, - varSpec.offset, - varSpec.size, - varSpec.t, - mm, - ) - if err != nil { - return nil, fmt.Errorf("variable %s: %w", varName, err) - } - - cl.vars[varName] = v - return v, nil -} - // populateDeferredMaps iterates maps holding programs or other maps and loads // any dependencies. Populates all maps in cl and freezes them if specified. func (cl *collectionLoader) populateDeferredMaps() error { @@ -701,7 +603,6 @@ func resolveKconfig(m *MapSpec) error { type configInfo struct { offset uint32 - size uint32 typ btf.Type } @@ -718,7 +619,7 @@ func resolveKconfig(m *MapSpec) error { return fmt.Errorf("variable %s must be a 32 bits integer, got %s", n, v.Type) } - kv, err := linux.KernelVersion() + kv, err := internal.KernelVersion() if err != nil { return fmt.Errorf("getting kernel version: %w", err) } @@ -743,7 +644,6 @@ func resolveKconfig(m *MapSpec) error { default: // Catch CONFIG_*. configs[n] = configInfo{ offset: vsi.Offset, - size: vsi.Size, typ: v.Type, } } @@ -751,7 +651,7 @@ func resolveKconfig(m *MapSpec) error { // We only parse kconfig file if a CONFIG_* variable was found. if len(configs) > 0 { - f, err := linux.FindKConfig() + f, err := kconfig.Find() if err != nil { return fmt.Errorf("cannot find a kconfig file: %w", err) } @@ -770,10 +670,10 @@ func resolveKconfig(m *MapSpec) error { for n, info := range configs { value, ok := kernelConfig[n] if !ok { - return fmt.Errorf("config option %q does not exist on this kernel", n) + return fmt.Errorf("config option %q does not exists for this kernel", n) } - err := kconfig.PutValue(data[info.offset:info.offset+info.size], info.typ, value) + err := kconfig.PutValue(data[info.offset:], info.typ, value) if err != nil { return fmt.Errorf("problem adding value for %s: %w", n, err) } @@ -823,7 +723,6 @@ func LoadCollection(file string) (*Collection, error) { func (coll *Collection) Assign(to interface{}) error { assignedMaps := make(map[string]bool) assignedProgs := make(map[string]bool) - assignedVars := make(map[string]bool) // Assign() only transfers already-loaded Maps and Programs. No extra // loading is done. @@ -844,13 +743,6 @@ func (coll *Collection) Assign(to interface{}) error { } return nil, fmt.Errorf("missing map %q", name) - case reflect.TypeOf((*Variable)(nil)): - if v := coll.Variables[name]; v != nil { - assignedVars[name] = true - return v, nil - } - return nil, fmt.Errorf("missing variable %q", name) - default: return nil, fmt.Errorf("unsupported type %s", typ) } @@ -867,9 +759,6 @@ func (coll *Collection) Assign(to interface{}) error { for m := range assignedMaps { delete(coll.Maps, m) } - for s := range assignedVars { - delete(coll.Variables, s) - } return nil } diff --git a/vendor/github.com/cilium/ebpf/elf_reader.go b/vendor/github.com/cilium/ebpf/elf_reader.go index 9e8dbc7ae5a..620037d80a8 100644 --- a/vendor/github.com/cilium/ebpf/elf_reader.go +++ b/vendor/github.com/cilium/ebpf/elf_reader.go @@ -16,6 +16,7 @@ import ( "github.com/cilium/ebpf/btf" "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/sys" + "github.com/cilium/ebpf/internal/unix" ) type kconfigMetaKey struct{} @@ -32,13 +33,6 @@ type kfuncMeta struct { Func *btf.Func } -type ksymMetaKey struct{} - -type ksymMeta struct { - Binding elf.SymBind - Name string -} - // elfCode is a convenience to reduce the amount of arguments that have to // be passed around explicitly. You should treat its contents as immutable. type elfCode struct { @@ -49,9 +43,7 @@ type elfCode struct { btf *btf.Spec extInfo *btf.ExtInfos maps map[string]*MapSpec - vars map[string]*VariableSpec kfuncs map[string]*btf.Func - ksyms map[string]struct{} kconfig *MapSpec } @@ -79,7 +71,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { // Checks if the ELF file is for BPF data. // Old LLVM versions set e_machine to EM_NONE. - if f.File.Machine != elf.EM_NONE && f.File.Machine != elf.EM_BPF { + if f.File.Machine != unix.EM_NONE && f.File.Machine != elf.EM_BPF { return nil, fmt.Errorf("unexpected machine type for BPF ELF: %s", f.File.Machine) } @@ -109,7 +101,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { sections[idx] = newElfSection(sec, mapSection) case sec.Name == ".maps": sections[idx] = newElfSection(sec, btfMapSection) - case isDataSection(sec.Name): + case sec.Name == ".bss" || sec.Name == ".data" || strings.HasPrefix(sec.Name, ".rodata"): sections[idx] = newElfSection(sec, dataSection) case sec.Type == elf.SHT_REL: // Store relocations under the section index of the target @@ -142,9 +134,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { btf: btfSpec, extInfo: btfExtInfo, maps: make(map[string]*MapSpec), - vars: make(map[string]*VariableSpec), kfuncs: make(map[string]*btf.Func), - ksyms: make(map[string]struct{}), } symbols, err := f.Symbols() @@ -184,7 +174,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { return nil, fmt.Errorf("load programs: %w", err) } - return &CollectionSpec{ec.maps, progs, ec.vars, btfSpec, ec.ByteOrder}, nil + return &CollectionSpec{ec.maps, progs, btfSpec, ec.ByteOrder}, nil } func loadLicense(sec *elf.Section) (string, error) { @@ -211,18 +201,6 @@ func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) { return version, nil } -func isDataSection(name string) bool { - return name == ".bss" || strings.HasPrefix(name, ".data") || strings.HasPrefix(name, ".rodata") -} - -func isConstantDataSection(name string) bool { - return strings.HasPrefix(name, ".rodata") -} - -func isKconfigSection(name string) bool { - return name == ".kconfig" -} - type elfSectionKind int const ( @@ -528,7 +506,7 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err case elf.STT_OBJECT: // LLVM 9 emits OBJECT-LOCAL symbols for anonymous constants. - if bind != elf.STB_GLOBAL && bind != elf.STB_LOCAL && bind != elf.STB_WEAK { + if bind != elf.STB_GLOBAL && bind != elf.STB_LOCAL { return fmt.Errorf("direct load: %s: %w: %s", name, errUnsupportedBinding, bind) } @@ -636,8 +614,6 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err } kf := ec.kfuncs[name] - _, ks := ec.ksyms[name] - switch { // If a Call / DWordLoad instruction is found and the datasec has a btf.Func with a Name // that matches the symbol name we mark the instruction as a referencing a kfunc. @@ -658,15 +634,6 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err ins.Constant = 0 - case ks && ins.OpCode.IsDWordLoad(): - if bind != elf.STB_GLOBAL && bind != elf.STB_WEAK { - return fmt.Errorf("asm relocation: %s: %w: %s", name, errUnsupportedBinding, bind) - } - ins.Metadata.Set(ksymMetaKey{}, &ksymMeta{ - Binding: bind, - Name: name, - }) - // If no kconfig map is found, this must be a symbol reference from inline // asm (see testdata/loader.c:asm_relocation()) or a call to a forward // function declaration (see testdata/fwd_decl.c). Don't interfere, These @@ -1013,13 +980,6 @@ func mapSpecFromBTF(es *elfSection, vs *btf.VarSecinfo, def *btf.Struct, spec *b } } - // Some maps don't support value sizes, but annotating their map definitions - // with __type macros can still be useful, especially to let bpf2go generate - // type definitions for them. - if value != nil && !mapType.canHaveValueSize() { - valueSize = 0 - } - return &MapSpec{ Name: SanitizeName(name, -1), Type: MapType(mapType), @@ -1132,21 +1092,12 @@ func (ec *elfCode) loadDataSections() error { continue } - // If a section has no references, it will be freed as soon as the - // Collection closes, so creating and populating it is wasteful. If it has - // no symbols, it is likely an ephemeral section used during compilation - // that wasn't sanitized by the bpf linker. (like .rodata.str1.1) - // - // No symbols means no VariableSpecs can be generated from it, making it - // pointless to emit a data section for. - if sec.references == 0 && len(sec.symbols) == 0 { + if sec.references == 0 { + // Prune data sections which are not referenced by any + // instructions. continue } - if sec.Size > math.MaxUint32 { - return fmt.Errorf("data section %s: contents exceed maximum size", sec.Name) - } - mapSpec := &MapSpec{ Name: SanitizeName(sec.Name, -1), Type: Array, @@ -1155,10 +1106,6 @@ func (ec *elfCode) loadDataSections() error { MaxEntries: 1, } - if isConstantDataSection(sec.Name) { - mapSpec.Flags = sys.BPF_F_RDONLY_PROG - } - switch sec.Type { // Only open the section if we know there's actual data to be read. case elf.SHT_PROGBITS: @@ -1166,56 +1113,20 @@ func (ec *elfCode) loadDataSections() error { if err != nil { return fmt.Errorf("data section %s: can't get contents: %w", sec.Name, err) } + + if uint64(len(data)) > math.MaxUint32 { + return fmt.Errorf("data section %s: contents exceed maximum size", sec.Name) + } mapSpec.Contents = []MapKV{{uint32(0), data}} case elf.SHT_NOBITS: - // NOBITS sections like .bss contain only zeroes and are not allocated in - // the ELF. Since data sections are Arrays, the kernel can preallocate - // them. Don't attempt reading zeroes from the ELF, instead allocate the - // zeroed memory to support getting and setting VariableSpecs for sections - // like .bss. - mapSpec.Contents = []MapKV{{uint32(0), make([]byte, sec.Size)}} - + // NOBITS sections like .bss contain only zeroes, and since data sections + // are Arrays, the kernel already preallocates them. Skip reading zeroes + // from the ELF. default: return fmt.Errorf("data section %s: unknown section type %s", sec.Name, sec.Type) } - for off, sym := range sec.symbols { - // Skip symbols marked with the 'hidden' attribute. - if elf.ST_VISIBILITY(sym.Other) == elf.STV_HIDDEN || - elf.ST_VISIBILITY(sym.Other) == elf.STV_INTERNAL { - continue - } - - // Only accept symbols with global or weak bindings. The common - // alternative is STB_LOCAL, which are either function-scoped or declared - // 'static'. - if elf.ST_BIND(sym.Info) != elf.STB_GLOBAL && - elf.ST_BIND(sym.Info) != elf.STB_WEAK { - continue - } - - if ec.vars[sym.Name] != nil { - return fmt.Errorf("data section %s: duplicate variable %s", sec.Name, sym.Name) - } - - // Skip symbols starting with a dot, they are compiler-internal symbols - // emitted by clang 11 and earlier and are not cleaned up by the bpf - // compiler backend (e.g. symbols named .Lconstinit.1 in sections like - // .rodata.cst32). Variables in C cannot start with a dot, so filter these - // out. - if strings.HasPrefix(sym.Name, ".") { - continue - } - - ec.vars[sym.Name] = &VariableSpec{ - name: sym.Name, - offset: off, - size: sym.Size, - m: mapSpec, - } - } - // It is possible for a data section to exist without a corresponding BTF Datasec // if it only contains anonymous values like macro-defined arrays. if ec.btf != nil { @@ -1224,40 +1135,14 @@ func (ec *elfCode) loadDataSections() error { // Assign the spec's key and BTF only if the Datasec lookup was successful. mapSpec.Key = &btf.Void{} mapSpec.Value = ds - - // Populate VariableSpecs with type information, if available. - for _, v := range ds.Vars { - name := v.Type.TypeName() - if name == "" { - return fmt.Errorf("data section %s: anonymous variable %v", sec.Name, v) - } - - vt, ok := v.Type.(*btf.Var) - if !ok { - return fmt.Errorf("data section %s: unexpected type %T for variable %s", sec.Name, v.Type, name) - } - - ev := ec.vars[name] - if ev == nil { - // Hidden symbols appear in the BTF Datasec but don't receive a VariableSpec. - continue - } - - if uint64(v.Offset) != ev.offset { - return fmt.Errorf("data section %s: variable %s datasec offset (%d) doesn't match ELF symbol offset (%d)", sec.Name, name, v.Offset, ev.offset) - } - - if uint64(v.Size) != ev.size { - return fmt.Errorf("data section %s: variable %s size in datasec (%d) doesn't match ELF symbol size (%d)", sec.Name, name, v.Size, ev.size) - } - - // Decouple the Var in the VariableSpec from the underlying DataSec in - // the MapSpec to avoid modifications from affecting map loads later on. - ev.t = btf.Copy(vt).(*btf.Var) - } } } + if strings.HasPrefix(sec.Name, ".rodata") { + mapSpec.Flags = unix.BPF_F_RDONLY_PROG + mapSpec.Freeze = true + } + ec.maps[sec.Name] = mapSpec } @@ -1290,7 +1175,8 @@ func (ec *elfCode) loadKconfigSection() error { KeySize: uint32(4), ValueSize: ds.Size, MaxEntries: 1, - Flags: sys.BPF_F_RDONLY_PROG, + Flags: unix.BPF_F_RDONLY_PROG, + Freeze: true, Key: &btf.Int{Size: 4}, Value: ds, } @@ -1315,14 +1201,8 @@ func (ec *elfCode) loadKsymsSection() error { } for _, v := range ds.Vars { - switch t := v.Type.(type) { - case *btf.Func: - ec.kfuncs[t.TypeName()] = t - case *btf.Var: - ec.ksyms[t.TypeName()] = struct{}{} - default: - return fmt.Errorf("unexpected variable type in .ksyms: %T", v) - } + // we have already checked the .ksyms Datasec to only contain Func Vars. + ec.kfuncs[v.Type.TypeName()] = v.Type.(*btf.Func) } return nil @@ -1386,10 +1266,10 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) { var flags uint32 if t.flags&_SEC_SLEEPABLE > 0 { - flags |= sys.BPF_F_SLEEPABLE + flags |= unix.BPF_F_SLEEPABLE } if t.flags&_SEC_XDP_FRAGS > 0 { - flags |= sys.BPF_F_XDP_HAS_FRAGS + flags |= unix.BPF_F_XDP_HAS_FRAGS } if t.flags&_SEC_EXP_ATTACH_OPT > 0 { if programType == XDP { diff --git a/vendor/github.com/cilium/ebpf/info.go b/vendor/github.com/cilium/ebpf/info.go index 56a1f1e9a31..04c60c64b89 100644 --- a/vendor/github.com/cilium/ebpf/info.go +++ b/vendor/github.com/cilium/ebpf/info.go @@ -8,10 +8,10 @@ import ( "fmt" "io" "os" - "reflect" "strings" "syscall" "time" + "unsafe" "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/btf" @@ -39,83 +39,53 @@ import ( // MapInfo describes a map. type MapInfo struct { - // Type of the map. - Type MapType - // KeySize is the size of the map key in bytes. - KeySize uint32 - // ValueSize is the size of the map value in bytes. - ValueSize uint32 - // MaxEntries is the maximum number of entries the map can hold. Its meaning - // is map-specific. + Type MapType + id MapID + KeySize uint32 + ValueSize uint32 MaxEntries uint32 - // Flags used during map creation. - Flags uint32 + Flags uint32 // Name as supplied by user space at load time. Available from 4.15. Name string - id MapID - btf btf.ID - mapExtra uint64 - memlock uint64 - frozen bool + btf btf.ID } -// newMapInfoFromFd queries map information about the given fd. [sys.ObjInfo] is -// attempted first, supplementing any missing values with information from -// /proc/self/fdinfo. Ignores EINVAL from ObjInfo as well as ErrNotSupported -// from reading fdinfo (indicating the file exists, but no fields of interest -// were found). If both fail, an error is always returned. func newMapInfoFromFd(fd *sys.FD) (*MapInfo, error) { var info sys.MapInfo - err1 := sys.ObjInfo(fd, &info) - // EINVAL means the kernel doesn't support BPF_OBJ_GET_INFO_BY_FD. Continue - // with fdinfo if that's the case. - if err1 != nil && !errors.Is(err1, unix.EINVAL) { - return nil, fmt.Errorf("getting object info: %w", err1) + err := sys.ObjInfo(fd, &info) + if errors.Is(err, syscall.EINVAL) { + return newMapInfoFromProc(fd) + } + if err != nil { + return nil, err } - mi := &MapInfo{ + return &MapInfo{ MapType(info.Type), + MapID(info.Id), info.KeySize, info.ValueSize, info.MaxEntries, uint32(info.MapFlags), unix.ByteSliceToString(info.Name[:]), - MapID(info.Id), btf.ID(info.BtfId), - info.MapExtra, - 0, - false, - } - - // Supplement OBJ_INFO with data from /proc/self/fdinfo. It contains fields - // like memlock and frozen that are not present in OBJ_INFO. - err2 := readMapInfoFromProc(fd, mi) - if err2 != nil && !errors.Is(err2, ErrNotSupported) { - return nil, fmt.Errorf("getting map info from fdinfo: %w", err2) - } - - if err1 != nil && err2 != nil { - return nil, fmt.Errorf("ObjInfo and fdinfo both failed: objinfo: %w, fdinfo: %w", err1, err2) - } - - return mi, nil + }, nil } -// readMapInfoFromProc queries map information about the given fd from -// /proc/self/fdinfo. It only writes data into fields that have a zero value. -func readMapInfoFromProc(fd *sys.FD, mi *MapInfo) error { - return scanFdInfo(fd, map[string]interface{}{ +func newMapInfoFromProc(fd *sys.FD) (*MapInfo, error) { + var mi MapInfo + err := scanFdInfo(fd, map[string]interface{}{ "map_type": &mi.Type, - "map_id": &mi.id, "key_size": &mi.KeySize, "value_size": &mi.ValueSize, "max_entries": &mi.MaxEntries, "map_flags": &mi.Flags, - "map_extra": &mi.mapExtra, - "memlock": &mi.memlock, - "frozen": &mi.frozen, }) + if err != nil { + return nil, err + } + return &mi, nil } // ID returns the map ID. @@ -139,35 +109,6 @@ func (mi *MapInfo) BTFID() (btf.ID, bool) { return mi.btf, mi.btf > 0 } -// MapExtra returns an opaque field whose meaning is map-specific. -// -// Available from 5.16. -// -// The bool return value indicates whether this optional field is available and -// populated, if it was specified during Map creation. -func (mi *MapInfo) MapExtra() (uint64, bool) { - return mi.mapExtra, mi.mapExtra > 0 -} - -// Memlock returns an approximate number of bytes allocated to this map. -// -// Available from 4.10. -// -// The bool return value indicates whether this optional field is available. -func (mi *MapInfo) Memlock() (uint64, bool) { - return mi.memlock, mi.memlock > 0 -} - -// Frozen indicates whether [Map.Freeze] was called on this map. If true, -// modifications from user space are not allowed. -// -// Available from 5.2. Requires access to procfs. -// -// If the kernel doesn't support map freezing, this field will always be false. -func (mi *MapInfo) Frozen() bool { - return mi.frozen -} - // programStats holds statistics of a program. type programStats struct { // Total accumulated runtime of the program ins ns. @@ -179,40 +120,6 @@ type programStats struct { recursionMisses uint64 } -// programJitedInfo holds information about JITed info of a program. -type programJitedInfo struct { - // ksyms holds the ksym addresses of the BPF program, including those of its - // subprograms. - // - // Available from 4.18. - ksyms []uintptr - numKsyms uint32 - - // insns holds the JITed machine native instructions of the program, - // including those of its subprograms. - // - // Available from 4.13. - insns []byte - numInsns uint32 - - // lineInfos holds the JITed line infos, which are kernel addresses. - // - // Available from 5.0. - lineInfos []uint64 - numLineInfos uint32 - - // lineInfoRecSize is the size of a single line info record. - // - // Available from 5.0. - lineInfoRecSize uint32 - - // funcLens holds the insns length of each function. - // - // Available from 4.18. - funcLens []uint32 - numFuncLens uint32 -} - // ProgramInfo describes a program. type ProgramInfo struct { Type ProgramType @@ -226,14 +133,9 @@ type ProgramInfo struct { haveCreatedByUID bool btf btf.ID stats *programStats - loadTime time.Duration - - maps []MapID - insns []byte - jitedSize uint32 - verifiedInstructions uint32 - jitedInfo programJitedInfo + maps []MapID + insns []byte lineInfos []byte numLineInfos uint32 @@ -262,9 +164,6 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) { runCount: info.RunCnt, recursionMisses: info.RecursionMisses, }, - jitedSize: info.JitedProgLen, - loadTime: time.Duration(info.LoadTime), - verifiedInstructions: info.VerifiedInsns, } // Start with a clean struct for the second call, otherwise we may get EFAULT. @@ -275,7 +174,7 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) { if info.NrMapIds > 0 { pi.maps = make([]MapID, info.NrMapIds) info2.NrMapIds = info.NrMapIds - info2.MapIds = sys.NewSlicePointer(pi.maps) + info2.MapIds = sys.NewPointer(unsafe.Pointer(&pi.maps[0])) makeSecondCall = true } else if haveProgramInfoMapIDs() == nil { // This program really has no associated maps. @@ -316,40 +215,6 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) { makeSecondCall = true } - pi.jitedInfo.lineInfoRecSize = info.JitedLineInfoRecSize - if info.JitedProgLen > 0 { - pi.jitedInfo.numInsns = info.JitedProgLen - pi.jitedInfo.insns = make([]byte, info.JitedProgLen) - info2.JitedProgLen = info.JitedProgLen - info2.JitedProgInsns = sys.NewSlicePointer(pi.jitedInfo.insns) - makeSecondCall = true - } - - if info.NrJitedFuncLens > 0 { - pi.jitedInfo.numFuncLens = info.NrJitedFuncLens - pi.jitedInfo.funcLens = make([]uint32, info.NrJitedFuncLens) - info2.NrJitedFuncLens = info.NrJitedFuncLens - info2.JitedFuncLens = sys.NewSlicePointer(pi.jitedInfo.funcLens) - makeSecondCall = true - } - - if info.NrJitedLineInfo > 0 { - pi.jitedInfo.numLineInfos = info.NrJitedLineInfo - pi.jitedInfo.lineInfos = make([]uint64, info.NrJitedLineInfo) - info2.NrJitedLineInfo = info.NrJitedLineInfo - info2.JitedLineInfo = sys.NewSlicePointer(pi.jitedInfo.lineInfos) - info2.JitedLineInfoRecSize = info.JitedLineInfoRecSize - makeSecondCall = true - } - - if info.NrJitedKsyms > 0 { - pi.jitedInfo.numKsyms = info.NrJitedKsyms - pi.jitedInfo.ksyms = make([]uintptr, info.NrJitedKsyms) - info2.JitedKsyms = sys.NewSlicePointer(pi.jitedInfo.ksyms) - info2.NrJitedKsyms = info.NrJitedKsyms - makeSecondCall = true - } - if makeSecondCall { if err := sys.ObjInfo(fd, &info2); err != nil { return nil, err @@ -365,7 +230,7 @@ func newProgramInfoFromProc(fd *sys.FD) (*ProgramInfo, error) { "prog_type": &info.Type, "prog_tag": &info.Tag, }) - if errors.Is(err, ErrNotSupported) { + if errors.Is(err, errMissingFields) { return nil, &internal.UnsupportedFeatureError{ Name: "reading program info from /proc/self/fdinfo", MinimumVersion: internal.Version{4, 10, 0}, @@ -440,52 +305,6 @@ func (pi *ProgramInfo) RecursionMisses() (uint64, bool) { return 0, false } -// btfSpec returns the BTF spec associated with the program. -func (pi *ProgramInfo) btfSpec() (*btf.Spec, error) { - id, ok := pi.BTFID() - if !ok { - return nil, fmt.Errorf("program created without BTF or unsupported kernel: %w", ErrNotSupported) - } - - h, err := btf.NewHandleFromID(id) - if err != nil { - return nil, fmt.Errorf("get BTF handle: %w", err) - } - defer h.Close() - - spec, err := h.Spec(nil) - if err != nil { - return nil, fmt.Errorf("get BTF spec: %w", err) - } - - return spec, nil -} - -// LineInfos returns the BTF line information of the program. -// -// Available from 5.0. -// -// Requires CAP_SYS_ADMIN or equivalent for reading BTF information. Returns -// ErrNotSupported if the program was created without BTF or if the kernel -// doesn't support the field. -func (pi *ProgramInfo) LineInfos() (btf.LineOffsets, error) { - if len(pi.lineInfos) == 0 { - return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported) - } - - spec, err := pi.btfSpec() - if err != nil { - return nil, err - } - - return btf.LoadLineInfos( - bytes.NewReader(pi.lineInfos), - internal.NativeEndian, - pi.numLineInfos, - spec, - ) -} - // Instructions returns the 'xlated' instruction stream of the program // after it has been verified and rewritten by the kernel. These instructions // cannot be loaded back into the kernel as-is, this is mainly used for @@ -572,29 +391,6 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) { return insns, nil } -// JitedSize returns the size of the program's JIT-compiled machine code in bytes, which is the -// actual code executed on the host's CPU. This field requires the BPF JIT compiler to be enabled. -// -// Available from 4.13. Reading this metadata requires CAP_BPF or equivalent. -func (pi *ProgramInfo) JitedSize() (uint32, error) { - if pi.jitedSize == 0 { - return 0, fmt.Errorf("insufficient permissions, unsupported kernel, or JIT compiler disabled: %w", ErrNotSupported) - } - return pi.jitedSize, nil -} - -// TranslatedSize returns the size of the program's translated instructions in bytes, after it has -// been verified and rewritten by the kernel. -// -// Available from 4.13. Reading this metadata requires CAP_BPF or equivalent. -func (pi *ProgramInfo) TranslatedSize() (int, error) { - insns := len(pi.insns) - if insns == 0 { - return 0, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported) - } - return insns, nil -} - // MapIDs returns the maps related to the program. // // Available from 4.15. @@ -604,89 +400,6 @@ func (pi *ProgramInfo) MapIDs() ([]MapID, bool) { return pi.maps, pi.maps != nil } -// LoadTime returns when the program was loaded since boot time. -// -// Available from 4.15. -// -// The bool return value indicates whether this optional field is available. -func (pi *ProgramInfo) LoadTime() (time.Duration, bool) { - // loadTime and NrMapIds were introduced in the same kernel version. - return pi.loadTime, pi.loadTime > 0 -} - -// VerifiedInstructions returns the number verified instructions in the program. -// -// Available from 5.16. -// -// The bool return value indicates whether this optional field is available. -func (pi *ProgramInfo) VerifiedInstructions() (uint32, bool) { - return pi.verifiedInstructions, pi.verifiedInstructions > 0 -} - -// JitedKsymAddrs returns the ksym addresses of the BPF program, including its -// subprograms. The addresses correspond to their symbols in /proc/kallsyms. -// -// Available from 4.18. Note that before 5.x, this field can be empty for -// programs without subprograms (bpf2bpf calls). -// -// The bool return value indicates whether this optional field is available. -func (pi *ProgramInfo) JitedKsymAddrs() ([]uintptr, bool) { - return pi.jitedInfo.ksyms, len(pi.jitedInfo.ksyms) > 0 -} - -// JitedInsns returns the JITed machine native instructions of the program. -// -// Available from 4.13. -// -// The bool return value indicates whether this optional field is available. -func (pi *ProgramInfo) JitedInsns() ([]byte, bool) { - return pi.jitedInfo.insns, len(pi.jitedInfo.insns) > 0 -} - -// JitedLineInfos returns the JITed line infos of the program. -// -// Available from 5.0. -// -// The bool return value indicates whether this optional field is available. -func (pi *ProgramInfo) JitedLineInfos() ([]uint64, bool) { - return pi.jitedInfo.lineInfos, len(pi.jitedInfo.lineInfos) > 0 -} - -// JitedFuncLens returns the insns length of each function in the JITed program. -// -// Available from 4.18. -// -// The bool return value indicates whether this optional field is available. -func (pi *ProgramInfo) JitedFuncLens() ([]uint32, bool) { - return pi.jitedInfo.funcLens, len(pi.jitedInfo.funcLens) > 0 -} - -// FuncInfos returns the offset and function information of all (sub)programs in -// a BPF program. -// -// Available from 5.0. -// -// Requires CAP_SYS_ADMIN or equivalent for reading BTF information. Returns -// ErrNotSupported if the program was created without BTF or if the kernel -// doesn't support the field. -func (pi *ProgramInfo) FuncInfos() (btf.FuncOffsets, error) { - if len(pi.funcInfos) == 0 { - return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported) - } - - spec, err := pi.btfSpec() - if err != nil { - return nil, err - } - - return btf.LoadFuncInfos( - bytes.NewReader(pi.funcInfos), - internal.NativeEndian, - pi.numFuncInfos, - spec, - ) -} - func scanFdInfo(fd *sys.FD, fields map[string]interface{}) error { fh, err := os.Open(fmt.Sprintf("/proc/self/fdinfo/%d", fd.Int())) if err != nil { @@ -700,6 +413,8 @@ func scanFdInfo(fd *sys.FD, fields map[string]interface{}) error { return nil } +var errMissingFields = errors.New("missing fields") + func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error { var ( scanner = bufio.NewScanner(r) @@ -718,37 +433,26 @@ func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error { continue } - // If field already contains a non-zero value, don't overwrite it with fdinfo. - if zero(field) { - if n, err := fmt.Sscanln(parts[1], field); err != nil || n != 1 { - return fmt.Errorf("can't parse field %s: %v", name, err) - } + if n, err := fmt.Sscanln(parts[1], field); err != nil || n != 1 { + return fmt.Errorf("can't parse field %s: %v", name, err) } scanned++ } if err := scanner.Err(); err != nil { - return fmt.Errorf("scanning fdinfo: %w", err) + return err } if len(fields) > 0 && scanned == 0 { return ErrNotSupported } - return nil -} - -func zero(arg any) bool { - v := reflect.ValueOf(arg) - - // Unwrap pointers and interfaces. - for v.Kind() == reflect.Pointer || - v.Kind() == reflect.Interface { - v = v.Elem() + if scanned != len(fields) { + return errMissingFields } - return v.IsZero() + return nil } // EnableStats starts the measuring of the runtime @@ -767,7 +471,7 @@ func EnableStats(which uint32) (io.Closer, error) { return fd, nil } -var haveProgramInfoMapIDs = internal.NewFeatureTest("map IDs in program info", func() error { +var haveProgramInfoMapIDs = internal.NewFeatureTest("map IDs in program info", "4.15", func() error { prog, err := progLoad(asm.Instructions{ asm.LoadImm(asm.R0, 0, asm.DWord), asm.Return(), @@ -792,4 +496,4 @@ var haveProgramInfoMapIDs = internal.NewFeatureTest("map IDs in program info", f } return err -}, "4.15") +}) diff --git a/vendor/github.com/cilium/ebpf/internal/linux/auxv.go b/vendor/github.com/cilium/ebpf/internal/auxv.go similarity index 98% rename from vendor/github.com/cilium/ebpf/internal/linux/auxv.go rename to vendor/github.com/cilium/ebpf/internal/auxv.go index 98bb5d83cad..45fd0d37f13 100644 --- a/vendor/github.com/cilium/ebpf/internal/linux/auxv.go +++ b/vendor/github.com/cilium/ebpf/internal/auxv.go @@ -1,4 +1,4 @@ -package linux +package internal import ( "errors" diff --git a/vendor/github.com/cilium/ebpf/internal/errors.go b/vendor/github.com/cilium/ebpf/internal/errors.go index 19d5294ca04..83a371ad35d 100644 --- a/vendor/github.com/cilium/ebpf/internal/errors.go +++ b/vendor/github.com/cilium/ebpf/internal/errors.go @@ -23,7 +23,7 @@ func ErrorWithLog(source string, err error, log []byte) *VerifierError { log = bytes.Trim(log, whitespace) if len(log) == 0 { - return &VerifierError{source, err, nil} + return &VerifierError{source, err, nil, false} } logLines := bytes.Split(log, []byte{'\n'}) @@ -34,7 +34,7 @@ func ErrorWithLog(source string, err error, log []byte) *VerifierError { lines = append(lines, string(bytes.TrimRight(line, whitespace))) } - return &VerifierError{source, err, lines} + return &VerifierError{source, err, lines, false} } // VerifierError includes information from the eBPF verifier. @@ -46,6 +46,8 @@ type VerifierError struct { Cause error // The verifier output split into lines. Log []string + // Deprecated: the log is never truncated anymore. + Truncated bool } func (le *VerifierError) Unwrap() error { diff --git a/vendor/github.com/cilium/ebpf/internal/feature.go b/vendor/github.com/cilium/ebpf/internal/feature.go index 6399be08514..2b856c735e7 100644 --- a/vendor/github.com/cilium/ebpf/internal/feature.go +++ b/vendor/github.com/cilium/ebpf/internal/feature.go @@ -3,25 +3,15 @@ package internal import ( "errors" "fmt" - "runtime" - "strings" "sync" ) -// ErrNotSupported indicates that a feature is not supported. +// ErrNotSupported indicates that a feature is not supported by the current kernel. var ErrNotSupported = errors.New("not supported") -// ErrNotSupportedOnOS indicates that a feature is not supported on the current -// operating system. -var ErrNotSupportedOnOS = fmt.Errorf("%w on %s", ErrNotSupported, runtime.GOOS) - // UnsupportedFeatureError is returned by FeatureTest() functions. type UnsupportedFeatureError struct { - // The minimum version required for this feature. - // - // On Linux this refers to the mainline kernel version, on other platforms - // to the version of the runtime. - // + // The minimum Linux mainline version required for this feature. // Used for the error string, and for sanity checking during testing. MinimumVersion Version @@ -68,44 +58,11 @@ type FeatureTest struct { type FeatureTestFn func() error // NewFeatureTest is a convenient way to create a single [FeatureTest]. -// -// versions specifies in which version of a BPF runtime a feature appeared. -// The format is "GOOS:Major.Minor[.Patch]". GOOS may be omitted when targeting -// Linux. Returns [ErrNotSupportedOnOS] if there is no version specified for the -// current OS. -func NewFeatureTest(name string, fn FeatureTestFn, versions ...string) func() error { - const nativePrefix = runtime.GOOS + ":" - - if len(versions) == 0 { - return func() error { - return fmt.Errorf("feature test %q: no versions specified", name) - } - } - +func NewFeatureTest(name, version string, fn FeatureTestFn) func() error { ft := &FeatureTest{ - Name: name, - Fn: fn, - } - - for _, version := range versions { - if strings.HasPrefix(version, nativePrefix) { - ft.Version = strings.TrimPrefix(version, nativePrefix) - break - } - - if runtime.GOOS == "linux" && !strings.ContainsRune(version, ':') { - // Allow version numbers without a GOOS prefix on Linux. - ft.Version = version - break - } - } - - if ft.Version == "" { - return func() error { - // We don't return an UnsupportedFeatureError here, since that will - // trigger version checks which don't make sense. - return fmt.Errorf("%s: %w", name, ErrNotSupportedOnOS) - } + Name: name, + Version: version, + Fn: fn, } return ft.execute diff --git a/vendor/github.com/cilium/ebpf/internal/kallsyms/cache.go b/vendor/github.com/cilium/ebpf/internal/kallsyms/cache.go deleted file mode 100644 index b7f3e0b7819..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/kallsyms/cache.go +++ /dev/null @@ -1,20 +0,0 @@ -package kallsyms - -import "sync" - -type cache[K, V comparable] struct { - m sync.Map -} - -func (c *cache[K, V]) Load(key K) (value V, _ bool) { - v, ok := c.m.Load(key) - if !ok { - return value, false - } - value = v.(V) - return value, true -} - -func (c *cache[K, V]) Store(key K, value V) { - c.m.Store(key, value) -} diff --git a/vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go b/vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go index f93d785849c..776c7a10a28 100644 --- a/vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go +++ b/vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go @@ -1,277 +1,74 @@ package kallsyms import ( - "errors" - "fmt" + "bufio" + "bytes" "io" "os" - "slices" - "strconv" - "strings" + "sync" ) -var errAmbiguousKsym = errors.New("multiple kernel symbols with the same name") - -var symAddrs cache[string, uint64] -var symModules cache[string, string] - -// Module returns the kernel module providing the given symbol in the kernel, if -// any. Returns an empty string and no error if the symbol is not present in the -// kernel. Only function symbols are considered. Returns an error if multiple -// symbols with the same name were found. -// -// Consider [AssignModules] if you need to resolve multiple symbols, as it will -// only perform one iteration over /proc/kallsyms. -func Module(name string) (string, error) { - if name == "" { - return "", nil - } - - if mod, ok := symModules.Load(name); ok { - return mod, nil - } - - request := map[string]string{name: ""} - if err := AssignModules(request); err != nil { - return "", err - } - - return request[name], nil +var kernelModules struct { + sync.RWMutex + // function to kernel module mapping + kmods map[string]string } -// AssignModules looks up the kernel module providing each given symbol, if any, -// and assigns them to their corresponding values in the symbols map. Only -// function symbols are considered. Results of all lookups are cached, -// successful or otherwise. -// -// Any symbols missing in the kernel are ignored. Returns an error if multiple -// symbols with a given name were found. -func AssignModules(symbols map[string]string) error { - if len(symbols) == 0 { - return nil - } +// KernelModule returns the kernel module, if any, a probe-able function is contained in. +func KernelModule(fn string) (string, error) { + kernelModules.RLock() + kmods := kernelModules.kmods + kernelModules.RUnlock() - // Attempt to fetch symbols from cache. - request := make(map[string]string) - for name := range symbols { - if mod, ok := symModules.Load(name); ok { - symbols[name] = mod - continue - } - - // Mark the symbol to be read from /proc/kallsyms. - request[name] = "" + if kmods == nil { + kernelModules.Lock() + defer kernelModules.Unlock() + kmods = kernelModules.kmods } - if len(request) == 0 { - // All symbols satisfied from cache. - return nil + + if kmods != nil { + return kmods[fn], nil } f, err := os.Open("/proc/kallsyms") if err != nil { - return err - } - - if err := assignModules(f, request); err != nil { - return fmt.Errorf("assigning symbol modules: %w", err) - } - - // Update the cache with the new symbols. Cache all requested symbols, even if - // they're missing or don't belong to a module. - for name, mod := range request { - symModules.Store(name, mod) - symbols[name] = mod - } - - return nil -} - -// assignModules assigns kernel symbol modules read from f to values requested -// by symbols. Always scans the whole input to make sure the user didn't request -// an ambiguous symbol. -func assignModules(f io.Reader, symbols map[string]string) error { - if len(symbols) == 0 { - return nil - } - - found := make(map[string]struct{}) - r := newReader(f) - for r.Line() { - // Only look for function symbols in the kernel's text section (tT). - s, err, skip := parseSymbol(r, []rune{'t', 'T'}) - if err != nil { - return fmt.Errorf("parsing kallsyms line: %w", err) - } - if skip { - continue - } - - if _, requested := symbols[s.name]; !requested { - continue - } - - if _, ok := found[s.name]; ok { - // We've already seen this symbol. Return an error to avoid silently - // attaching to a symbol in the wrong module. libbpf also rejects - // referring to ambiguous symbols. - // - // We can't simply check if we already have a value for the given symbol, - // since many won't have an associated kernel module. - return fmt.Errorf("symbol %s: duplicate found at address 0x%x (module %q): %w", - s.name, s.addr, s.mod, errAmbiguousKsym) - } - - symbols[s.name] = s.mod - found[s.name] = struct{}{} + return "", err } - if err := r.Err(); err != nil { - return fmt.Errorf("reading kallsyms: %w", err) + defer f.Close() + kmods, err = loadKernelModuleMapping(f) + if err != nil { + return "", err } - return nil + kernelModules.kmods = kmods + return kmods[fn], nil } -// Address returns the address of the given symbol in the kernel. Returns 0 and -// no error if the symbol is not present. Returns an error if multiple addresses -// were found for a symbol. -// -// Consider [AssignAddresses] if you need to resolve multiple symbols, as it -// will only perform one iteration over /proc/kallsyms. -func Address(symbol string) (uint64, error) { - if symbol == "" { - return 0, nil - } - - if addr, ok := symAddrs.Load(symbol); ok { - return addr, nil - } - - request := map[string]uint64{symbol: 0} - if err := AssignAddresses(request); err != nil { - return 0, err - } +// FlushKernelModuleCache removes any cached information about function to kernel module mapping. +func FlushKernelModuleCache() { + kernelModules.Lock() + defer kernelModules.Unlock() - return request[symbol], nil + kernelModules.kmods = nil } -// AssignAddresses looks up the addresses of the requested symbols in the kernel -// and assigns them to their corresponding values in the symbols map. Results -// of all lookups are cached, successful or otherwise. -// -// Any symbols missing in the kernel are ignored. Returns an error if multiple -// addresses were found for a symbol. -func AssignAddresses(symbols map[string]uint64) error { - if len(symbols) == 0 { - return nil - } - - // Attempt to fetch symbols from cache. - request := make(map[string]uint64) - for name := range symbols { - if addr, ok := symAddrs.Load(name); ok { - symbols[name] = addr +func loadKernelModuleMapping(f io.Reader) (map[string]string, error) { + mods := make(map[string]string) + scanner := bufio.NewScanner(f) + for scanner.Scan() { + fields := bytes.Fields(scanner.Bytes()) + if len(fields) < 4 { continue } - - // Mark the symbol to be read from /proc/kallsyms. - request[name] = 0 - } - if len(request) == 0 { - // All symbols satisfied from cache. - return nil - } - - f, err := os.Open("/proc/kallsyms") - if err != nil { - return err - } - - if err := assignAddresses(f, request); err != nil { - return fmt.Errorf("loading symbol addresses: %w", err) - } - - // Update the cache with the new symbols. Cache all requested symbols even if - // they weren't found, to avoid repeated lookups. - for name, addr := range request { - symAddrs.Store(name, addr) - symbols[name] = addr - } - - return nil -} - -// assignAddresses assigns kernel symbol addresses read from f to values -// requested by symbols. Always scans the whole input to make sure the user -// didn't request an ambiguous symbol. -func assignAddresses(f io.Reader, symbols map[string]uint64) error { - if len(symbols) == 0 { - return nil - } - r := newReader(f) - for r.Line() { - s, err, skip := parseSymbol(r, nil) - if err != nil { - return fmt.Errorf("parsing kallsyms line: %w", err) - } - if skip { + switch string(fields[1]) { + case "t", "T": + mods[string(fields[2])] = string(bytes.Trim(fields[3], "[]")) + default: continue } - - existing, requested := symbols[s.name] - if existing != 0 { - // Multiple addresses for a symbol have been found. Return a friendly - // error to avoid silently attaching to the wrong symbol. libbpf also - // rejects referring to ambiguous symbols. - return fmt.Errorf("symbol %s(0x%x): duplicate found at address 0x%x: %w", s.name, existing, s.addr, errAmbiguousKsym) - } - if requested { - symbols[s.name] = s.addr - } } - if err := r.Err(); err != nil { - return fmt.Errorf("reading kallsyms: %w", err) + if scanner.Err() != nil { + return nil, scanner.Err() } - - return nil -} - -type ksym struct { - addr uint64 - name string - mod string -} - -// parseSymbol parses a line from /proc/kallsyms into an address, type, name and -// module. Skip will be true if the symbol doesn't match any of the given symbol -// types. See `man 1 nm` for all available types. -// -// Example line: `ffffffffc1682010 T nf_nat_init [nf_nat]` -func parseSymbol(r *reader, types []rune) (s ksym, err error, skip bool) { - for i := 0; r.Word(); i++ { - switch i { - // Address of the symbol. - case 0: - s.addr, err = strconv.ParseUint(r.Text(), 16, 64) - if err != nil { - return s, fmt.Errorf("parsing address: %w", err), false - } - // Type of the symbol. Assume the character is ASCII-encoded by converting - // it directly to a rune, since it's a fixed field controlled by the kernel. - case 1: - if len(types) > 0 && !slices.Contains(types, rune(r.Bytes()[0])) { - return s, nil, true - } - // Name of the symbol. - case 2: - s.name = r.Text() - // Kernel module the symbol is provided by. - case 3: - s.mod = strings.Trim(r.Text(), "[]") - // Ignore any future fields. - default: - break - } - } - - return + return mods, nil } diff --git a/vendor/github.com/cilium/ebpf/internal/kallsyms/reader.go b/vendor/github.com/cilium/ebpf/internal/kallsyms/reader.go deleted file mode 100644 index 2bd4f8eafcb..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/kallsyms/reader.go +++ /dev/null @@ -1,118 +0,0 @@ -package kallsyms - -import ( - "bufio" - "io" - "unicode" - "unicode/utf8" -) - -// reader is a line and word-oriented reader built for reading /proc/kallsyms. -// It takes an io.Reader and iterates its contents line by line, then word by -// word. -// -// It's designed to allow partial reading of lines without paying the cost of -// allocating objects that will never be accessed, resulting in less work for -// the garbage collector. -type reader struct { - s *bufio.Scanner - line []byte - word []byte - - err error -} - -func newReader(r io.Reader) *reader { - return &reader{ - s: bufio.NewScanner(r), - } -} - -// Bytes returns the current word as a byte slice. -func (r *reader) Bytes() []byte { - return r.word -} - -// Text returns the output of Bytes as a string. -func (r *reader) Text() string { - return string(r.Bytes()) -} - -// Line advances the reader to the next line in the input. Calling Line resets -// the current word, making [reader.Bytes] and [reader.Text] return empty -// values. Follow this up with a call to [reader.Word]. -// -// Like [bufio.Scanner], [reader.Err] needs to be checked after Line returns -// false to determine if an error occurred during reading. -// -// Returns true if Line can be called again. Returns false if all lines in the -// input have been read. -func (r *reader) Line() bool { - for r.s.Scan() { - line := r.s.Bytes() - if len(line) == 0 { - continue - } - - r.line = line - r.word = nil - - return true - } - if err := r.s.Err(); err != nil { - r.err = err - } - - return false -} - -// Word advances the reader to the next word in the current line. -// -// Returns true if a word is found and Word should be called again. Returns -// false when all words on the line have been read. -func (r *reader) Word() bool { - if len(r.line) == 0 { - return false - } - - // Find next word start, skipping leading spaces. - start := 0 - for width := 0; start < len(r.line); start += width { - var c rune - c, width = utf8.DecodeRune(r.line[start:]) - if !unicode.IsSpace(c) { - break - } - } - - // Whitespace scanning reached the end of the line due to trailing whitespace, - // meaning there are no more words to read - if start == len(r.line) { - return false - } - - // Find next word end. - for width, i := 0, start; i < len(r.line); i += width { - var c rune - c, width = utf8.DecodeRune(r.line[i:]) - if unicode.IsSpace(c) { - r.word = r.line[start:i] - r.line = r.line[i:] - return true - } - } - - // The line contains data, but no end-of-word boundary was found. This is the - // last, unterminated word in the line. - if len(r.line) > start { - r.word = r.line[start:] - r.line = nil - return true - } - - return false -} - -func (r *reader) Err() error { - return r.err -} diff --git a/vendor/github.com/cilium/ebpf/internal/kconfig/kconfig.go b/vendor/github.com/cilium/ebpf/internal/kconfig/kconfig.go index 29c62b6266e..1921e4f15ad 100644 --- a/vendor/github.com/cilium/ebpf/internal/kconfig/kconfig.go +++ b/vendor/github.com/cilium/ebpf/internal/kconfig/kconfig.go @@ -1,4 +1,3 @@ -// Package kconfig implements a parser for the format of Linux's .config file. package kconfig import ( @@ -8,6 +7,7 @@ import ( "fmt" "io" "math" + "os" "strconv" "strings" @@ -15,6 +15,30 @@ import ( "github.com/cilium/ebpf/internal" ) +// Find find a kconfig file on the host. +// It first reads from /boot/config- of the current running kernel and tries +// /proc/config.gz if nothing was found in /boot. +// If none of the file provide a kconfig, it returns an error. +func Find() (*os.File, error) { + kernelRelease, err := internal.KernelRelease() + if err != nil { + return nil, fmt.Errorf("cannot get kernel release: %w", err) + } + + path := "/boot/config-" + kernelRelease + f, err := os.Open(path) + if err == nil { + return f, nil + } + + f, err = os.Open("/proc/config.gz") + if err == nil { + return f, nil + } + + return nil, fmt.Errorf("neither %s nor /proc/config.gz provide a kconfig", path) +} + // Parse parses the kconfig file for which a reader is given. // All the CONFIG_* which are in filter and which are set set will be // put in the returned map as key with their corresponding value as map value. @@ -103,13 +127,12 @@ func PutValue(data []byte, typ btf.Type, value string) error { switch value { case "y", "n", "m": return putValueTri(data, typ, value) + default: + if strings.HasPrefix(value, `"`) { + return putValueString(data, typ, value) + } + return putValueNumber(data, typ, value) } - - if strings.HasPrefix(value, `"`) { - return putValueString(data, typ, value) - } - - return putValueNumber(data, typ, value) } // Golang translation of libbpf_tristate enum: @@ -146,10 +169,6 @@ func putValueTri(data []byte, typ btf.Type, value string) error { return fmt.Errorf("cannot use enum %q, only libbpf_tristate is supported", v.Name) } - if len(data) != 4 { - return fmt.Errorf("expected enum value to occupy 4 bytes in datasec, got: %d", len(data)) - } - var tri triState switch value { case "y": @@ -159,10 +178,10 @@ func putValueTri(data []byte, typ btf.Type, value string) error { case "n": tri = TriNo default: - return fmt.Errorf("value %q is not supported for libbpf_tristate", value) + return fmt.Errorf("value %q is not support for libbpf_tristate", value) } - internal.NativeEndian.PutUint32(data, uint32(tri)) + internal.NativeEndian.PutUint64(data, uint64(tri)) default: return fmt.Errorf("cannot add number value, expected btf.Int or btf.Enum, got: %T", v) } diff --git a/vendor/github.com/cilium/ebpf/internal/linux/doc.go b/vendor/github.com/cilium/ebpf/internal/linux/doc.go deleted file mode 100644 index 064e75437d8..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/linux/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package linux contains OS specific wrappers around package unix. -package linux diff --git a/vendor/github.com/cilium/ebpf/internal/linux/kconfig.go b/vendor/github.com/cilium/ebpf/internal/linux/kconfig.go deleted file mode 100644 index 1488ecb35c3..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/linux/kconfig.go +++ /dev/null @@ -1,31 +0,0 @@ -package linux - -import ( - "fmt" - "os" -) - -// FindKConfig searches for a kconfig file on the host. -// -// It first reads from /boot/config- of the current running kernel and tries -// /proc/config.gz if nothing was found in /boot. -// If none of the file provide a kconfig, it returns an error. -func FindKConfig() (*os.File, error) { - kernelRelease, err := KernelRelease() - if err != nil { - return nil, fmt.Errorf("cannot get kernel release: %w", err) - } - - path := "/boot/config-" + kernelRelease - f, err := os.Open(path) - if err == nil { - return f, nil - } - - f, err = os.Open("/proc/config.gz") - if err == nil { - return f, nil - } - - return nil, fmt.Errorf("neither %s nor /proc/config.gz provide a kconfig", path) -} diff --git a/vendor/github.com/cilium/ebpf/internal/linux/version.go b/vendor/github.com/cilium/ebpf/internal/linux/version.go deleted file mode 100644 index 798dd3fed02..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/linux/version.go +++ /dev/null @@ -1,34 +0,0 @@ -package linux - -import ( - "fmt" - "sync" - - "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/unix" -) - -// KernelVersion returns the version of the currently running kernel. -var KernelVersion = sync.OnceValues(detectKernelVersion) - -// detectKernelVersion returns the version of the running kernel. -func detectKernelVersion() (internal.Version, error) { - vc, err := vdsoVersion() - if err != nil { - return internal.Version{}, err - } - return internal.NewVersionFromCode(vc), nil -} - -// KernelRelease returns the release string of the running kernel. -// Its format depends on the Linux distribution and corresponds to directory -// names in /lib/modules by convention. Some examples are 5.15.17-1-lts and -// 4.19.0-16-amd64. -func KernelRelease() (string, error) { - var uname unix.Utsname - if err := unix.Uname(&uname); err != nil { - return "", fmt.Errorf("uname failed: %w", err) - } - - return unix.ByteSliceToString(uname.Release[:]), nil -} diff --git a/vendor/github.com/cilium/ebpf/internal/math.go b/vendor/github.com/cilium/ebpf/internal/math.go index 10cde66860d..e95c8efde51 100644 --- a/vendor/github.com/cilium/ebpf/internal/math.go +++ b/vendor/github.com/cilium/ebpf/internal/math.go @@ -1,33 +1,13 @@ package internal +import "golang.org/x/exp/constraints" + // Align returns 'n' updated to 'alignment' boundary. -func Align[I Integer](n, alignment I) I { +func Align[I constraints.Integer](n, alignment I) I { return (n + alignment - 1) / alignment * alignment } // IsPow returns true if n is a power of two. -func IsPow[I Integer](n I) bool { +func IsPow[I constraints.Integer](n I) bool { return n != 0 && (n&(n-1)) == 0 } - -// Between returns the value clamped between a and b. -func Between[I Integer](val, a, b I) I { - lower, upper := a, b - if lower > upper { - upper, lower = a, b - } - - val = min(val, upper) - return max(val, lower) -} - -// Integer represents all possible integer types. -// Remove when x/exp/constraints is moved to the standard library. -type Integer interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr -} - -// List of integer types known by the Go compiler. Used by TestIntegerConstraint -// to warn if a new integer type is introduced. Remove when x/exp/constraints -// is moved to the standard library. -var integers = []string{"int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr"} diff --git a/vendor/github.com/cilium/ebpf/internal/sys/pinning.go b/vendor/github.com/cilium/ebpf/internal/pinning.go similarity index 77% rename from vendor/github.com/cilium/ebpf/internal/sys/pinning.go rename to vendor/github.com/cilium/ebpf/internal/pinning.go index 9a4c6c7a153..01d892f9344 100644 --- a/vendor/github.com/cilium/ebpf/internal/sys/pinning.go +++ b/vendor/github.com/cilium/ebpf/internal/pinning.go @@ -1,4 +1,4 @@ -package sys +package internal import ( "errors" @@ -7,11 +7,11 @@ import ( "path/filepath" "runtime" - "github.com/cilium/ebpf/internal/linux" + "github.com/cilium/ebpf/internal/sys" "github.com/cilium/ebpf/internal/unix" ) -func Pin(currentPath, newPath string, fd *FD) error { +func Pin(currentPath, newPath string, fd *sys.FD) error { if newPath == "" { return errors.New("given pinning path cannot be empty") } @@ -19,7 +19,7 @@ func Pin(currentPath, newPath string, fd *FD) error { return nil } - fsType, err := linux.FSType(filepath.Dir(newPath)) + fsType, err := FSType(filepath.Dir(newPath)) if err != nil { return err } @@ -30,8 +30,8 @@ func Pin(currentPath, newPath string, fd *FD) error { defer runtime.KeepAlive(fd) if currentPath == "" { - return ObjPin(&ObjPinAttr{ - Pathname: NewStringPointer(newPath), + return sys.ObjPin(&sys.ObjPinAttr{ + Pathname: sys.NewStringPointer(newPath), BpfFd: fd.Uint(), }) } @@ -47,8 +47,8 @@ func Pin(currentPath, newPath string, fd *FD) error { return fmt.Errorf("unable to move pinned object to new path %v: %w", newPath, err) } // Internal state not in sync with the file system so let's fix it. - return ObjPin(&ObjPinAttr{ - Pathname: NewStringPointer(newPath), + return sys.ObjPin(&sys.ObjPinAttr{ + Pathname: sys.NewStringPointer(newPath), BpfFd: fd.Uint(), }) } diff --git a/vendor/github.com/cilium/ebpf/internal/linux/platform.go b/vendor/github.com/cilium/ebpf/internal/platform.go similarity index 97% rename from vendor/github.com/cilium/ebpf/internal/linux/platform.go rename to vendor/github.com/cilium/ebpf/internal/platform.go index 39bdcc51f9a..6e90f2ef714 100644 --- a/vendor/github.com/cilium/ebpf/internal/linux/platform.go +++ b/vendor/github.com/cilium/ebpf/internal/platform.go @@ -1,4 +1,4 @@ -package linux +package internal import ( "runtime" diff --git a/vendor/github.com/cilium/ebpf/internal/linux/statfs.go b/vendor/github.com/cilium/ebpf/internal/statfs.go similarity index 96% rename from vendor/github.com/cilium/ebpf/internal/linux/statfs.go rename to vendor/github.com/cilium/ebpf/internal/statfs.go index e268c06fab6..44c02d676e6 100644 --- a/vendor/github.com/cilium/ebpf/internal/linux/statfs.go +++ b/vendor/github.com/cilium/ebpf/internal/statfs.go @@ -1,4 +1,4 @@ -package linux +package internal import ( "unsafe" diff --git a/vendor/github.com/cilium/ebpf/internal/sys/fd.go b/vendor/github.com/cilium/ebpf/internal/sys/fd.go index e2ba43fd3b3..941a56fb91b 100644 --- a/vendor/github.com/cilium/ebpf/internal/sys/fd.go +++ b/vendor/github.com/cilium/ebpf/internal/sys/fd.go @@ -4,12 +4,9 @@ import ( "fmt" "math" "os" - "path/filepath" "runtime" "strconv" - "strings" - "github.com/cilium/ebpf/internal/testutils/fdtrace" "github.com/cilium/ebpf/internal/unix" ) @@ -20,7 +17,15 @@ type FD struct { } func newFD(value int) *FD { - fdtrace.TraceFD(value, 1) + if onLeakFD != nil { + // Attempt to store the caller's stack for the given fd value. + // Panic if fds contains an existing stack for the fd. + old, exist := fds.LoadOrStore(value, callersFrames()) + if exist { + f := old.(*runtime.Frames) + panic(fmt.Sprintf("found existing stack for fd %d:\n%s", value, FormatFrames(f))) + } + } fd := &FD{value} runtime.SetFinalizer(fd, (*FD).finalize) @@ -34,7 +39,13 @@ func (fd *FD) finalize() { return } - fdtrace.LeakFD(fd.raw) + // Invoke the fd leak callback. Calls LoadAndDelete to guarantee the callback + // is invoked at most once for one sys.FD allocation, runtime.Frames can only + // be unwound once. + f, ok := fds.LoadAndDelete(fd.Int()) + if ok && onLeakFD != nil { + onLeakFD(f.(*runtime.Frames)) + } _ = fd.Close() } @@ -81,15 +92,12 @@ func (fd *FD) Close() error { return nil } - return unix.Close(fd.Disown()) + return unix.Close(fd.disown()) } -// Disown destroys the FD and returns its raw file descriptor without closing -// it. After this call, the underlying fd is no longer tied to the FD's -// lifecycle. -func (fd *FD) Disown() int { - value := fd.raw - fdtrace.ForgetFD(value) +func (fd *FD) disown() int { + value := int(fd.raw) + fds.Delete(int(value)) fd.raw = -1 runtime.SetFinalizer(fd, nil) @@ -121,45 +129,5 @@ func (fd *FD) File(name string) *os.File { return nil } - return os.NewFile(uintptr(fd.Disown()), name) -} - -// ObjGetTyped wraps [ObjGet] with a readlink call to extract the type of the -// underlying bpf object. -func ObjGetTyped(attr *ObjGetAttr) (*FD, ObjType, error) { - fd, err := ObjGet(attr) - if err != nil { - return nil, 0, err - } - - typ, err := readType(fd) - if err != nil { - _ = fd.Close() - return nil, 0, fmt.Errorf("reading fd type: %w", err) - } - - return fd, typ, nil -} - -// readType returns the bpf object type of the file descriptor by calling -// readlink(3). Returns an error if the file descriptor does not represent a bpf -// object. -func readType(fd *FD) (ObjType, error) { - s, err := os.Readlink(filepath.Join("/proc/self/fd/", fd.String())) - if err != nil { - return 0, fmt.Errorf("readlink fd %d: %w", fd.Int(), err) - } - - s = strings.TrimPrefix(s, "anon_inode:") - - switch s { - case "bpf-map": - return BPF_TYPE_MAP, nil - case "bpf-prog": - return BPF_TYPE_PROG, nil - case "bpf-link": - return BPF_TYPE_LINK, nil - } - - return 0, fmt.Errorf("unknown type %s of fd %d", s, fd.Int()) + return os.NewFile(uintptr(fd.disown()), name) } diff --git a/vendor/github.com/cilium/ebpf/internal/sys/fd_trace.go b/vendor/github.com/cilium/ebpf/internal/sys/fd_trace.go new file mode 100644 index 00000000000..cd50dd1f642 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/sys/fd_trace.go @@ -0,0 +1,93 @@ +package sys + +import ( + "bytes" + "fmt" + "runtime" + "sync" +) + +// OnLeakFD controls tracing [FD] lifetime to detect resources that are not +// closed by Close(). +// +// If fn is not nil, tracing is enabled for all FDs created going forward. fn is +// invoked for all FDs that are closed by the garbage collector instead of an +// explicit Close() by a caller. Calling OnLeakFD twice with a non-nil fn +// (without disabling tracing in the meantime) will cause a panic. +// +// If fn is nil, tracing will be disabled. Any FDs that have not been closed are +// considered to be leaked, fn will be invoked for them, and the process will be +// terminated. +// +// fn will be invoked at most once for every unique sys.FD allocation since a +// runtime.Frames can only be unwound once. +func OnLeakFD(fn func(*runtime.Frames)) { + // Enable leak tracing if new fn is provided. + if fn != nil { + if onLeakFD != nil { + panic("OnLeakFD called twice with non-nil fn") + } + + onLeakFD = fn + return + } + + // fn is nil past this point. + + if onLeakFD == nil { + return + } + + // Call onLeakFD for all open fds. + if fs := flushFrames(); len(fs) != 0 { + for _, f := range fs { + onLeakFD(f) + } + } + + onLeakFD = nil +} + +var onLeakFD func(*runtime.Frames) + +// fds is a registry of all file descriptors wrapped into sys.fds that were +// created while an fd tracer was active. +var fds sync.Map // map[int]*runtime.Frames + +// flushFrames removes all elements from fds and returns them as a slice. This +// deals with the fact that a runtime.Frames can only be unwound once using +// Next(). +func flushFrames() []*runtime.Frames { + var frames []*runtime.Frames + fds.Range(func(key, value any) bool { + frames = append(frames, value.(*runtime.Frames)) + fds.Delete(key) + return true + }) + return frames +} + +func callersFrames() *runtime.Frames { + c := make([]uintptr, 32) + + // Skip runtime.Callers and this function. + i := runtime.Callers(2, c) + if i == 0 { + return nil + } + + return runtime.CallersFrames(c) +} + +// FormatFrames formats a runtime.Frames as a human-readable string. +func FormatFrames(fs *runtime.Frames) string { + var b bytes.Buffer + for { + f, more := fs.Next() + b.WriteString(fmt.Sprintf("\t%s+%#x\n\t\t%s:%d\n", f.Function, f.PC-f.Entry, f.File, f.Line)) + if !more { + break + } + } + return b.String() +} diff --git a/vendor/github.com/cilium/ebpf/internal/sys/mapflags_string.go b/vendor/github.com/cilium/ebpf/internal/sys/mapflags_string.go new file mode 100644 index 00000000000..d9fe217222b --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/sys/mapflags_string.go @@ -0,0 +1,53 @@ +// Code generated by "stringer -type MapFlags"; DO NOT EDIT. + +package sys + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[BPF_F_NO_PREALLOC-1] + _ = x[BPF_F_NO_COMMON_LRU-2] + _ = x[BPF_F_NUMA_NODE-4] + _ = x[BPF_F_RDONLY-8] + _ = x[BPF_F_WRONLY-16] + _ = x[BPF_F_STACK_BUILD_ID-32] + _ = x[BPF_F_ZERO_SEED-64] + _ = x[BPF_F_RDONLY_PROG-128] + _ = x[BPF_F_WRONLY_PROG-256] + _ = x[BPF_F_CLONE-512] + _ = x[BPF_F_MMAPABLE-1024] + _ = x[BPF_F_PRESERVE_ELEMS-2048] + _ = x[BPF_F_INNER_MAP-4096] + _ = x[BPF_F_LINK-8192] + _ = x[BPF_F_PATH_FD-16384] +} + +const _MapFlags_name = "BPF_F_NO_PREALLOCBPF_F_NO_COMMON_LRUBPF_F_NUMA_NODEBPF_F_RDONLYBPF_F_WRONLYBPF_F_STACK_BUILD_IDBPF_F_ZERO_SEEDBPF_F_RDONLY_PROGBPF_F_WRONLY_PROGBPF_F_CLONEBPF_F_MMAPABLEBPF_F_PRESERVE_ELEMSBPF_F_INNER_MAPBPF_F_LINKBPF_F_PATH_FD" + +var _MapFlags_map = map[MapFlags]string{ + 1: _MapFlags_name[0:17], + 2: _MapFlags_name[17:36], + 4: _MapFlags_name[36:51], + 8: _MapFlags_name[51:63], + 16: _MapFlags_name[63:75], + 32: _MapFlags_name[75:95], + 64: _MapFlags_name[95:110], + 128: _MapFlags_name[110:127], + 256: _MapFlags_name[127:144], + 512: _MapFlags_name[144:155], + 1024: _MapFlags_name[155:169], + 2048: _MapFlags_name[169:189], + 4096: _MapFlags_name[189:204], + 8192: _MapFlags_name[204:214], + 16384: _MapFlags_name[214:227], +} + +func (i MapFlags) String() string { + if str, ok := _MapFlags_map[i]; ok { + return str + } + return "MapFlags(" + strconv.FormatInt(int64(i), 10) + ")" +} diff --git a/vendor/github.com/cilium/ebpf/internal/sys/ptr.go b/vendor/github.com/cilium/ebpf/internal/sys/ptr.go index af0c014e3b9..e9bb5905973 100644 --- a/vendor/github.com/cilium/ebpf/internal/sys/ptr.go +++ b/vendor/github.com/cilium/ebpf/internal/sys/ptr.go @@ -11,13 +11,13 @@ func NewPointer(ptr unsafe.Pointer) Pointer { return Pointer{ptr: ptr} } -// NewSlicePointer creates a 64-bit pointer from a slice. -func NewSlicePointer[T comparable](buf []T) Pointer { +// NewSlicePointer creates a 64-bit pointer from a byte slice. +func NewSlicePointer(buf []byte) Pointer { if len(buf) == 0 { return Pointer{} } - return Pointer{ptr: unsafe.Pointer(unsafe.SliceData(buf))} + return Pointer{ptr: unsafe.Pointer(&buf[0])} } // NewSlicePointerLen creates a 64-bit pointer from a byte slice. diff --git a/vendor/github.com/cilium/ebpf/internal/sys/syscall.go b/vendor/github.com/cilium/ebpf/internal/sys/syscall.go index e37f4cf6710..f6b6e934580 100644 --- a/vendor/github.com/cilium/ebpf/internal/sys/syscall.go +++ b/vendor/github.com/cilium/ebpf/internal/sys/syscall.go @@ -133,12 +133,12 @@ func ObjInfo(fd *FD, info Info) error { // BPFObjName is a null-terminated string made up of // 'A-Za-z0-9_' characters. -type ObjName [BPF_OBJ_NAME_LEN]byte +type ObjName [unix.BPF_OBJ_NAME_LEN]byte // NewObjName truncates the result if it is too long. func NewObjName(name string) ObjName { var result ObjName - copy(result[:BPF_OBJ_NAME_LEN-1], name) + copy(result[:unix.BPF_OBJ_NAME_LEN-1], name) return result } @@ -160,6 +160,29 @@ type BTFID uint32 // TypeID identifies a type in a BTF blob. type TypeID uint32 +// MapFlags control map behaviour. +type MapFlags uint32 + +//go:generate go run golang.org/x/tools/cmd/stringer@latest -type MapFlags + +const ( + BPF_F_NO_PREALLOC MapFlags = 1 << iota + BPF_F_NO_COMMON_LRU + BPF_F_NUMA_NODE + BPF_F_RDONLY + BPF_F_WRONLY + BPF_F_STACK_BUILD_ID + BPF_F_ZERO_SEED + BPF_F_RDONLY_PROG + BPF_F_WRONLY_PROG + BPF_F_CLONE + BPF_F_MMAPABLE + BPF_F_PRESERVE_ELEMS + BPF_F_INNER_MAP + BPF_F_LINK + BPF_F_PATH_FD +) + // Flags used by bpf_mprog. const ( BPF_F_REPLACE = 1 << (iota + 2) @@ -169,16 +192,6 @@ const ( BPF_F_LINK_MPROG = 1 << 13 // aka BPF_F_LINK ) -// Flags used by BPF_PROG_LOAD. -const ( - BPF_F_SLEEPABLE = 1 << 4 - BPF_F_XDP_HAS_FRAGS = 1 << 5 - BPF_F_XDP_DEV_BOUND_ONLY = 1 << 6 -) - -const BPF_TAG_SIZE = 8 -const BPF_OBJ_NAME_LEN = 16 - // wrappedErrno wraps syscall.Errno to prevent direct comparisons with // syscall.E* or unix.E* constants. // diff --git a/vendor/github.com/cilium/ebpf/internal/sys/types.go b/vendor/github.com/cilium/ebpf/internal/sys/types.go index 88001c319eb..70e754de71d 100644 --- a/vendor/github.com/cilium/ebpf/internal/sys/types.go +++ b/vendor/github.com/cilium/ebpf/internal/sys/types.go @@ -6,170 +6,6 @@ import ( "unsafe" ) -const ( - BPF_ADJ_ROOM_ENCAP_L2_MASK = 255 - BPF_ADJ_ROOM_ENCAP_L2_SHIFT = 56 - BPF_ANY = 0 - BPF_CSUM_LEVEL_DEC = 2 - BPF_CSUM_LEVEL_INC = 1 - BPF_CSUM_LEVEL_QUERY = 0 - BPF_CSUM_LEVEL_RESET = 3 - BPF_EXIST = 2 - BPF_FIB_LKUP_RET_BLACKHOLE = 1 - BPF_FIB_LKUP_RET_FRAG_NEEDED = 8 - BPF_FIB_LKUP_RET_FWD_DISABLED = 5 - BPF_FIB_LKUP_RET_NOT_FWDED = 4 - BPF_FIB_LKUP_RET_NO_NEIGH = 7 - BPF_FIB_LKUP_RET_NO_SRC_ADDR = 9 - BPF_FIB_LKUP_RET_PROHIBIT = 3 - BPF_FIB_LKUP_RET_SUCCESS = 0 - BPF_FIB_LKUP_RET_UNREACHABLE = 2 - BPF_FIB_LKUP_RET_UNSUPP_LWT = 6 - BPF_FIB_LOOKUP_DIRECT = 1 - BPF_FIB_LOOKUP_OUTPUT = 2 - BPF_FIB_LOOKUP_SKIP_NEIGH = 4 - BPF_FIB_LOOKUP_SRC = 16 - BPF_FIB_LOOKUP_TBID = 8 - BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG = 1 - BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP = 4 - BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL = 2 - BPF_F_ADJ_ROOM_DECAP_L3_IPV4 = 128 - BPF_F_ADJ_ROOM_DECAP_L3_IPV6 = 256 - BPF_F_ADJ_ROOM_ENCAP_L2_ETH = 64 - BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 = 2 - BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 = 4 - BPF_F_ADJ_ROOM_ENCAP_L4_GRE = 8 - BPF_F_ADJ_ROOM_ENCAP_L4_UDP = 16 - BPF_F_ADJ_ROOM_FIXED_GSO = 1 - BPF_F_ADJ_ROOM_NO_CSUM_RESET = 32 - BPF_F_BPRM_SECUREEXEC = 1 - BPF_F_BROADCAST = 8 - BPF_F_CLONE = 512 - BPF_F_CTXLEN_MASK = 4503595332403200 - BPF_F_CURRENT_CPU = 4294967295 - BPF_F_CURRENT_NETNS = 18446744073709551615 - BPF_F_DONT_FRAGMENT = 4 - BPF_F_EXCLUDE_INGRESS = 16 - BPF_F_FAST_STACK_CMP = 512 - BPF_F_GET_BRANCH_RECORDS_SIZE = 1 - BPF_F_HDR_FIELD_MASK = 15 - BPF_F_INDEX_MASK = 4294967295 - BPF_F_INGRESS = 1 - BPF_F_INNER_MAP = 4096 - BPF_F_INVALIDATE_HASH = 2 - BPF_F_KPROBE_MULTI_RETURN = 1 - BPF_F_LINK = 8192 - BPF_F_LOCK = 4 - BPF_F_MARK_ENFORCE = 64 - BPF_F_MARK_MANGLED_0 = 32 - BPF_F_MMAPABLE = 1024 - BPF_F_NEIGH = 2 - BPF_F_NEXTHOP = 8 - BPF_F_NO_COMMON_LRU = 2 - BPF_F_NO_PREALLOC = 1 - BPF_F_NO_TUNNEL_KEY = 16 - BPF_F_NUMA_NODE = 4 - BPF_F_PATH_FD = 16384 - BPF_F_PEER = 4 - BPF_F_PRESERVE_ELEMS = 2048 - BPF_F_PSEUDO_HDR = 16 - BPF_F_RDONLY = 8 - BPF_F_RDONLY_PROG = 128 - BPF_F_RECOMPUTE_CSUM = 1 - BPF_F_REUSE_STACKID = 1024 - BPF_F_SEQ_NUMBER = 8 - BPF_F_SKIP_FIELD_MASK = 255 - BPF_F_STACK_BUILD_ID = 32 - BPF_F_SYSCTL_BASE_NAME = 1 - BPF_F_TIMER_ABS = 1 - BPF_F_TIMER_CPU_PIN = 2 - BPF_F_TUNINFO_FLAGS = 16 - BPF_F_TUNINFO_IPV6 = 1 - BPF_F_UPROBE_MULTI_RETURN = 1 - BPF_F_USER_BUILD_ID = 2048 - BPF_F_USER_STACK = 256 - BPF_F_WRONLY = 16 - BPF_F_WRONLY_PROG = 256 - BPF_F_ZERO_CSUM_TX = 2 - BPF_F_ZERO_SEED = 64 - BPF_LOAD_HDR_OPT_TCP_SYN = 1 - BPF_LOCAL_STORAGE_GET_F_CREATE = 1 - BPF_MAX_LOOPS = 8388608 - BPF_MAX_TRAMP_LINKS = 38 - BPF_NOEXIST = 1 - BPF_RB_AVAIL_DATA = 0 - BPF_RB_CONS_POS = 2 - BPF_RB_FORCE_WAKEUP = 2 - BPF_RB_NO_WAKEUP = 1 - BPF_RB_PROD_POS = 3 - BPF_RB_RING_SIZE = 1 - BPF_REG_0 = 0 - BPF_REG_1 = 1 - BPF_REG_10 = 10 - BPF_REG_2 = 2 - BPF_REG_3 = 3 - BPF_REG_4 = 4 - BPF_REG_5 = 5 - BPF_REG_6 = 6 - BPF_REG_7 = 7 - BPF_REG_8 = 8 - BPF_REG_9 = 9 - BPF_RINGBUF_BUSY_BIT = 2147483648 - BPF_RINGBUF_DISCARD_BIT = 1073741824 - BPF_RINGBUF_HDR_SZ = 8 - BPF_SKB_TSTAMP_DELIVERY_MONO = 1 - BPF_SKB_TSTAMP_UNSPEC = 0 - BPF_SK_LOOKUP_F_NO_REUSEPORT = 2 - BPF_SK_LOOKUP_F_REPLACE = 1 - BPF_SK_STORAGE_GET_F_CREATE = 1 - BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB = 4 - BPF_SOCK_OPS_ALL_CB_FLAGS = 127 - BPF_SOCK_OPS_BASE_RTT = 7 - BPF_SOCK_OPS_HDR_OPT_LEN_CB = 14 - BPF_SOCK_OPS_NEEDS_ECN = 6 - BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG = 16 - BPF_SOCK_OPS_PARSE_HDR_OPT_CB = 13 - BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG = 32 - BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB = 5 - BPF_SOCK_OPS_RETRANS_CB = 9 - BPF_SOCK_OPS_RETRANS_CB_FLAG = 2 - BPF_SOCK_OPS_RTO_CB = 8 - BPF_SOCK_OPS_RTO_CB_FLAG = 1 - BPF_SOCK_OPS_RTT_CB = 12 - BPF_SOCK_OPS_RTT_CB_FLAG = 8 - BPF_SOCK_OPS_RWND_INIT = 2 - BPF_SOCK_OPS_STATE_CB = 10 - BPF_SOCK_OPS_STATE_CB_FLAG = 4 - BPF_SOCK_OPS_TCP_CONNECT_CB = 3 - BPF_SOCK_OPS_TCP_LISTEN_CB = 11 - BPF_SOCK_OPS_TIMEOUT_INIT = 1 - BPF_SOCK_OPS_VOID = 0 - BPF_SOCK_OPS_WRITE_HDR_OPT_CB = 15 - BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG = 64 - BPF_STRUCT_OPS_TYPE_bpf_dummy_ops = 0 - BPF_STRUCT_OPS_TYPE_tcp_congestion_ops = 1 - BPF_TASK_ITER_ALL_PROCS = 0 - BPF_TASK_ITER_ALL_THREADS = 1 - BPF_TASK_ITER_PROC_THREADS = 2 - BPF_TCP_BOUND_INACTIVE = 13 - BPF_TCP_CLOSE = 7 - BPF_TCP_CLOSE_WAIT = 8 - BPF_TCP_CLOSING = 11 - BPF_TCP_ESTABLISHED = 1 - BPF_TCP_FIN_WAIT1 = 4 - BPF_TCP_FIN_WAIT2 = 5 - BPF_TCP_LAST_ACK = 9 - BPF_TCP_LISTEN = 10 - BPF_TCP_MAX_STATES = 14 - BPF_TCP_NEW_SYN_RECV = 12 - BPF_TCP_SYN_RECV = 3 - BPF_TCP_SYN_SENT = 2 - BPF_TCP_TIME_WAIT = 6 - BPF_WRITE_HDR_TCP_CURRENT_MSS = 1 - BPF_WRITE_HDR_TCP_SYNACK_COOKIE = 2 - BPF_XFRM_STATE_OPTS_SZ = 36 -) - type AdjRoomMode uint32 const ( @@ -566,15 +402,6 @@ const ( BPF_MAP_TYPE_CGRP_STORAGE MapType = 32 ) -type ObjType uint32 - -const ( - BPF_TYPE_UNSPEC ObjType = 0 - BPF_TYPE_PROG ObjType = 1 - BPF_TYPE_MAP ObjType = 2 - BPF_TYPE_LINK ObjType = 3 -) - type PerfEventType uint32 const ( @@ -710,7 +537,7 @@ type MapInfo struct { KeySize uint32 ValueSize uint32 MaxEntries uint32 - MapFlags uint32 + MapFlags MapFlags Name ObjName Ifindex uint32 BtfVmlinuxValueTypeId TypeID @@ -729,7 +556,7 @@ type ProgInfo struct { Tag [8]uint8 JitedProgLen uint32 XlatedProgLen uint32 - JitedProgInsns Pointer + JitedProgInsns uint64 XlatedProgInsns Pointer LoadTime uint64 CreatedByUid uint32 @@ -742,15 +569,15 @@ type ProgInfo struct { NetnsIno uint64 NrJitedKsyms uint32 NrJitedFuncLens uint32 - JitedKsyms Pointer - JitedFuncLens Pointer + JitedKsyms uint64 + JitedFuncLens uint64 BtfId BTFID FuncInfoRecSize uint32 FuncInfo Pointer NrFuncInfo uint32 NrLineInfo uint32 LineInfo Pointer - JitedLineInfo Pointer + JitedLineInfo uint64 NrJitedLineInfo uint32 LineInfoRecSize uint32 JitedLineInfoRecSize uint32 @@ -1059,7 +886,7 @@ type MapCreateAttr struct { KeySize uint32 ValueSize uint32 MaxEntries uint32 - MapFlags uint32 + MapFlags MapFlags InnerMapFd uint32 NumaNode uint32 MapName ObjName diff --git a/vendor/github.com/cilium/ebpf/internal/sysenc/buffer.go b/vendor/github.com/cilium/ebpf/internal/sysenc/buffer.go index 1b4f052ee2b..d184ea196ae 100644 --- a/vendor/github.com/cilium/ebpf/internal/sysenc/buffer.go +++ b/vendor/github.com/cilium/ebpf/internal/sysenc/buffer.go @@ -51,12 +51,12 @@ func SyscallOutput(dst any, size int) Buffer { // // Returns the number of copied bytes. func (b Buffer) CopyTo(dst []byte) int { - return copy(dst, b.Bytes()) + return copy(dst, b.unsafeBytes()) } // AppendTo appends the buffer onto dst. func (b Buffer) AppendTo(dst []byte) []byte { - return append(dst, b.Bytes()...) + return append(dst, b.unsafeBytes()...) } // Pointer returns the location where a syscall should write. @@ -72,12 +72,10 @@ func (b Buffer) Unmarshal(data any) error { return nil } - return Unmarshal(data, b.Bytes()) + return Unmarshal(data, b.unsafeBytes()) } -// Bytes returns the buffer as a byte slice. Returns nil if the Buffer was -// created using UnsafeBuffer or by zero-copy unmarshaling. -func (b Buffer) Bytes() []byte { +func (b Buffer) unsafeBytes() []byte { if b.size == syscallPointerOnly { return nil } diff --git a/vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/fd_trace.go b/vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/fd_trace.go deleted file mode 100644 index 562df2cc0c2..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/fd_trace.go +++ /dev/null @@ -1,103 +0,0 @@ -package fdtrace - -import ( - "bytes" - "fmt" - "os" - "runtime" - "sync" - "sync/atomic" -) - -// foundLeak is atomic since the GC may collect objects in parallel. -var foundLeak atomic.Bool - -func onLeakFD(fs *runtime.Frames) { - foundLeak.Store(true) - fmt.Fprintln(os.Stderr, "leaked fd created at:") - fmt.Fprintln(os.Stderr, formatFrames(fs)) -} - -// fds is a registry of all file descriptors wrapped into sys.fds that were -// created while an fd tracer was active. -var fds *sync.Map // map[int]*runtime.Frames - -// TraceFD associates raw with the current execution stack. -// -// skip controls how many entries of the stack the function should skip. -func TraceFD(raw int, skip int) { - if fds == nil { - return - } - - // Attempt to store the caller's stack for the given fd value. - // Panic if fds contains an existing stack for the fd. - old, exist := fds.LoadOrStore(raw, callersFrames(skip)) - if exist { - f := old.(*runtime.Frames) - panic(fmt.Sprintf("found existing stack for fd %d:\n%s", raw, formatFrames(f))) - } -} - -// ForgetFD removes any existing association for raw. -func ForgetFD(raw int) { - if fds != nil { - fds.Delete(raw) - } -} - -// LeakFD indicates that raw was leaked. -// -// Calling the function with a value that was not passed to [TraceFD] before -// is undefined. -func LeakFD(raw int) { - if fds == nil { - return - } - - // Invoke the fd leak callback. Calls LoadAndDelete to guarantee the callback - // is invoked at most once for one sys.FD allocation, runtime.Frames can only - // be unwound once. - f, ok := fds.LoadAndDelete(raw) - if ok { - onLeakFD(f.(*runtime.Frames)) - } -} - -// flushFrames removes all elements from fds and returns them as a slice. This -// deals with the fact that a runtime.Frames can only be unwound once using -// Next(). -func flushFrames() []*runtime.Frames { - var frames []*runtime.Frames - fds.Range(func(key, value any) bool { - frames = append(frames, value.(*runtime.Frames)) - fds.Delete(key) - return true - }) - return frames -} - -func callersFrames(skip int) *runtime.Frames { - c := make([]uintptr, 32) - - // Skip runtime.Callers and this function. - i := runtime.Callers(skip+2, c) - if i == 0 { - return nil - } - - return runtime.CallersFrames(c) -} - -// formatFrames formats a runtime.Frames as a human-readable string. -func formatFrames(fs *runtime.Frames) string { - var b bytes.Buffer - for { - f, more := fs.Next() - b.WriteString(fmt.Sprintf("\t%s+%#x\n\t\t%s:%d\n", f.Function, f.PC-f.Entry, f.File, f.Line)) - if !more { - break - } - } - return b.String() -} diff --git a/vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/main.go b/vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/main.go deleted file mode 100644 index c1f7b42d91d..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/main.go +++ /dev/null @@ -1,31 +0,0 @@ -package fdtrace - -import ( - "os" - "sync" -) - -type testingM interface { - Run() int -} - -// TestMain runs m with fd tracing enabled. -// -// The function calls [os.Exit] and does not return. -func TestMain(m testingM) { - fds = new(sync.Map) - - ret := m.Run() - - if fs := flushFrames(); len(fs) != 0 { - for _, f := range fs { - onLeakFD(f) - } - } - - if foundLeak.Load() { - ret = 99 - } - - os.Exit(ret) -} diff --git a/vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go b/vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go index 062bef9ec37..897740fec0c 100644 --- a/vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go +++ b/vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go @@ -12,7 +12,6 @@ import ( "syscall" "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/linux" "github.com/cilium/ebpf/internal/unix" ) @@ -122,7 +121,7 @@ var getTracefsPath = sync.OnceValues(func() (string, error) { // RHEL/CentOS {"/sys/kernel/debug/tracing", unix.DEBUGFS_MAGIC}, } { - if fsType, err := linux.FSType(p.path); err == nil && fsType == p.fsType { + if fsType, err := internal.FSType(p.path); err == nil && fsType == p.fsType { return p.path, nil } } @@ -214,10 +213,7 @@ func NewEvent(args ProbeArgs) (*Event, error) { if err == nil { return nil, fmt.Errorf("trace event %s/%s: %w", args.Group, eventName, os.ErrExist) } - if errors.Is(err, unix.EINVAL) { - return nil, fmt.Errorf("trace event %s/%s: %w (unknown symbol?)", args.Group, eventName, err) - } - if !errors.Is(err, os.ErrNotExist) { + if err != nil && !errors.Is(err, os.ErrNotExist) { return nil, fmt.Errorf("checking trace event %s/%s: %w", args.Group, eventName, err) } diff --git a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go index 144e608d1c7..d725cfaa394 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go @@ -81,16 +81,15 @@ const ( SO_DETACH_BPF = linux.SO_DETACH_BPF SOL_SOCKET = linux.SOL_SOCKET SIGPROF = linux.SIGPROF - SIGUSR1 = linux.SIGUSR1 SIG_BLOCK = linux.SIG_BLOCK SIG_UNBLOCK = linux.SIG_UNBLOCK + EM_NONE = linux.EM_NONE + EM_BPF = linux.EM_BPF BPF_FS_MAGIC = linux.BPF_FS_MAGIC TRACEFS_MAGIC = linux.TRACEFS_MAGIC DEBUGFS_MAGIC = linux.DEBUGFS_MAGIC BPF_RB_NO_WAKEUP = linux.BPF_RB_NO_WAKEUP BPF_RB_FORCE_WAKEUP = linux.BPF_RB_FORCE_WAKEUP - AF_UNSPEC = linux.AF_UNSPEC - IFF_UP = linux.IFF_UP ) type Statfs_t = linux.Statfs_t diff --git a/vendor/github.com/cilium/ebpf/internal/unix/types_other.go b/vendor/github.com/cilium/ebpf/internal/unix/types_other.go index 06cc3a09663..3ff8962716a 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_other.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_other.go @@ -84,17 +84,16 @@ const ( SO_DETACH_BPF SOL_SOCKET SIGPROF - SIGUSR1 SIG_BLOCK SIG_UNBLOCK + EM_NONE + EM_BPF BPF_FS_MAGIC TRACEFS_MAGIC DEBUGFS_MAGIC BPF_RB_NO_WAKEUP BPF_RB_FORCE_WAKEUP BPF_F_LOCK - AF_UNSPEC - IFF_UP ) type Statfs_t struct { diff --git a/vendor/github.com/cilium/ebpf/internal/linux/vdso.go b/vendor/github.com/cilium/ebpf/internal/vdso.go similarity index 93% rename from vendor/github.com/cilium/ebpf/internal/linux/vdso.go rename to vendor/github.com/cilium/ebpf/internal/vdso.go index 1d8d0ef6b11..1049278554e 100644 --- a/vendor/github.com/cilium/ebpf/internal/linux/vdso.go +++ b/vendor/github.com/cilium/ebpf/internal/vdso.go @@ -1,4 +1,4 @@ -package linux +package internal import ( "debug/elf" @@ -9,7 +9,6 @@ import ( "math" "os" - "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/unix" ) @@ -83,7 +82,7 @@ type elfNoteHeader struct { // vdsoLinuxVersionCode returns the LINUX_VERSION_CODE embedded in // the ELF notes section of the binary provided by the reader. func vdsoLinuxVersionCode(r io.ReaderAt) (uint32, error) { - hdr, err := internal.NewSafeELFFile(r) + hdr, err := NewSafeELFFile(r) if err != nil { return 0, fmt.Errorf("reading vDSO ELF: %w", err) } @@ -111,7 +110,7 @@ func vdsoLinuxVersionCode(r io.ReaderAt) (uint32, error) { var name string if n.NameSize > 0 { // Read the note name, aligned to 4 bytes. - buf := make([]byte, internal.Align(n.NameSize, 4)) + buf := make([]byte, Align(n.NameSize, 4)) if err := binary.Read(sr, hdr.ByteOrder, &buf); err != nil { return 0, fmt.Errorf("reading note name: %w", err) } @@ -133,7 +132,7 @@ func vdsoLinuxVersionCode(r io.ReaderAt) (uint32, error) { } // Discard the note descriptor if it exists but we're not interested in it. - if _, err := io.CopyN(io.Discard, sr, int64(internal.Align(n.DescSize, 4))); err != nil { + if _, err := io.CopyN(io.Discard, sr, int64(Align(n.DescSize, 4))); err != nil { return 0, err } } diff --git a/vendor/github.com/cilium/ebpf/internal/version.go b/vendor/github.com/cilium/ebpf/internal/version.go index a230830b013..acd4650af73 100644 --- a/vendor/github.com/cilium/ebpf/internal/version.go +++ b/vendor/github.com/cilium/ebpf/internal/version.go @@ -2,6 +2,9 @@ package internal import ( "fmt" + "sync" + + "github.com/cilium/ebpf/internal/unix" ) const ( @@ -75,3 +78,30 @@ func (v Version) Kernel() uint32 { // each other when overflowing 8 bits. return uint32(uint8(v[0]))<<16 | uint32(uint8(v[1]))<<8 | uint32(uint8(s)) } + +// KernelVersion returns the version of the currently running kernel. +var KernelVersion = sync.OnceValues(func() (Version, error) { + return detectKernelVersion() +}) + +// detectKernelVersion returns the version of the running kernel. +func detectKernelVersion() (Version, error) { + vc, err := vdsoVersion() + if err != nil { + return Version{}, err + } + return NewVersionFromCode(vc), nil +} + +// KernelRelease returns the release string of the running kernel. +// Its format depends on the Linux distribution and corresponds to directory +// names in /lib/modules by convention. Some examples are 5.15.17-1-lts and +// 4.19.0-16-amd64. +func KernelRelease() (string, error) { + var uname unix.Utsname + if err := unix.Uname(&uname); err != nil { + return "", fmt.Errorf("uname failed: %w", err) + } + + return unix.ByteSliceToString(uname.Release[:]), nil +} diff --git a/vendor/github.com/cilium/ebpf/link/kprobe.go b/vendor/github.com/cilium/ebpf/link/kprobe.go index 6f93a27a254..fe3f17c3717 100644 --- a/vendor/github.com/cilium/ebpf/link/kprobe.go +++ b/vendor/github.com/cilium/ebpf/link/kprobe.go @@ -10,7 +10,6 @@ import ( "github.com/cilium/ebpf" "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/linux" "github.com/cilium/ebpf/internal/sys" "github.com/cilium/ebpf/internal/tracefs" "github.com/cilium/ebpf/internal/unix" @@ -61,9 +60,6 @@ func (ko *KprobeOptions) cookie() uint64 { // platform's syscall prefix (e.g. __x64_) to support attaching to syscalls // in a portable fashion. // -// On kernels 6.11 and later, setting a kprobe on a nonexistent symbol using -// tracefs incorrectly returns [unix.EINVAL] instead of [os.ErrNotExist]. -// // The returned Link may implement [PerfEvent]. func Kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions) (Link, error) { k, err := kprobe(symbol, prog, opts, false) @@ -95,7 +91,7 @@ func Kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions) (Link, error // in a portable fashion. // // On kernels 5.10 and earlier, setting a kretprobe on a nonexistent symbol -// incorrectly returns [unix.EINVAL] instead of [os.ErrNotExist]. +// incorrectly returns unix.EINVAL instead of os.ErrNotExist. // // The returned Link may implement [PerfEvent]. func Kretprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions) (Link, error) { @@ -173,7 +169,7 @@ func kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions, ret bool) (* // Use kprobe PMU if the kernel has it available. tp, err := pmuProbe(args) if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) { - if prefix := linux.PlatformPrefix(); prefix != "" { + if prefix := internal.PlatformPrefix(); prefix != "" { args.Symbol = prefix + symbol tp, err = pmuProbe(args) } @@ -181,7 +177,7 @@ func kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions, ret bool) (* if err == nil { return tp, nil } - if !errors.Is(err, ErrNotSupported) { + if err != nil && !errors.Is(err, ErrNotSupported) { return nil, fmt.Errorf("creating perf_kprobe PMU (arch-specific fallback for %q): %w", symbol, err) } @@ -189,7 +185,7 @@ func kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions, ret bool) (* args.Symbol = symbol tp, err = tracefsProbe(args) if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) { - if prefix := linux.PlatformPrefix(); prefix != "" { + if prefix := internal.PlatformPrefix(); prefix != "" { args.Symbol = prefix + symbol tp, err = tracefsProbe(args) } diff --git a/vendor/github.com/cilium/ebpf/link/kprobe_multi.go b/vendor/github.com/cilium/ebpf/link/kprobe_multi.go index 094cb0538cb..f7a8291f945 100644 --- a/vendor/github.com/cilium/ebpf/link/kprobe_multi.go +++ b/vendor/github.com/cilium/ebpf/link/kprobe_multi.go @@ -60,7 +60,7 @@ func KprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions) (Link, error) { // // Requires at least Linux 5.18. func KretprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions) (Link, error) { - return kprobeMulti(prog, opts, sys.BPF_F_KPROBE_MULTI_RETURN) + return kprobeMulti(prog, opts, unix.BPF_F_KPROBE_MULTI_RETURN) } func kprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions, flags uint32) (Link, error) { @@ -126,7 +126,7 @@ type kprobeMultiLink struct { var _ Link = (*kprobeMultiLink)(nil) -func (kml *kprobeMultiLink) Update(_ *ebpf.Program) error { +func (kml *kprobeMultiLink) Update(prog *ebpf.Program) error { return fmt.Errorf("update kprobe_multi: %w", ErrNotSupported) } @@ -149,7 +149,7 @@ func (kml *kprobeMultiLink) Info() (*Info, error) { }, nil } -var haveBPFLinkKprobeMulti = internal.NewFeatureTest("bpf_link_kprobe_multi", func() error { +var haveBPFLinkKprobeMulti = internal.NewFeatureTest("bpf_link_kprobe_multi", "5.18", func() error { prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ Name: "probe_kpm_link", Type: ebpf.Kprobe, @@ -188,4 +188,4 @@ var haveBPFLinkKprobeMulti = internal.NewFeatureTest("bpf_link_kprobe_multi", fu fd.Close() return nil -}, "5.18") +}) diff --git a/vendor/github.com/cilium/ebpf/link/link.go b/vendor/github.com/cilium/ebpf/link/link.go index 796769f8ea4..9c34616c9a9 100644 --- a/vendor/github.com/cilium/ebpf/link/link.go +++ b/vendor/github.com/cilium/ebpf/link/link.go @@ -78,9 +78,7 @@ func NewFromID(id ID) (Link, error) { return wrapRawLink(&RawLink{fd, ""}) } -// LoadPinnedLink loads a Link from a pin (file) on the BPF virtual filesystem. -// -// Requires at least Linux 5.7. +// LoadPinnedLink loads a link that was persisted into a bpffs. func LoadPinnedLink(fileName string, opts *ebpf.LoadPinOptions) (Link, error) { raw, err := loadPinnedRawLink(fileName, opts) if err != nil { @@ -352,7 +350,7 @@ func AttachRawLink(opts RawLinkOptions) (*RawLink, error) { } func loadPinnedRawLink(fileName string, opts *ebpf.LoadPinOptions) (*RawLink, error) { - fd, typ, err := sys.ObjGetTyped(&sys.ObjGetAttr{ + fd, err := sys.ObjGet(&sys.ObjGetAttr{ Pathname: sys.NewStringPointer(fileName), FileFlags: opts.Marshal(), }) @@ -360,11 +358,6 @@ func loadPinnedRawLink(fileName string, opts *ebpf.LoadPinOptions) (*RawLink, er return nil, fmt.Errorf("load pinned link: %w", err) } - if typ != sys.BPF_TYPE_LINK { - _ = fd.Close() - return nil, fmt.Errorf("%s is not a Link", fileName) - } - return &RawLink{fd, fileName}, nil } @@ -387,7 +380,7 @@ func (l *RawLink) Close() error { // 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 := sys.Pin(l.pinnedPath, fileName, l.fd); err != nil { + if err := internal.Pin(l.pinnedPath, fileName, l.fd); err != nil { return err } l.pinnedPath = fileName @@ -396,7 +389,7 @@ func (l *RawLink) Pin(fileName string) error { // Unpin implements the Link interface. func (l *RawLink) Unpin() error { - if err := sys.Unpin(l.pinnedPath); err != nil { + if err := internal.Unpin(l.pinnedPath); err != nil { return err } l.pinnedPath = "" diff --git a/vendor/github.com/cilium/ebpf/link/netfilter.go b/vendor/github.com/cilium/ebpf/link/netfilter.go index 9436d11df93..34be3908597 100644 --- a/vendor/github.com/cilium/ebpf/link/netfilter.go +++ b/vendor/github.com/cilium/ebpf/link/netfilter.go @@ -63,7 +63,7 @@ func AttachNetfilter(opts NetfilterOptions) (Link, error) { return &netfilterLink{RawLink{fd, ""}}, nil } -func (*netfilterLink) Update(_ *ebpf.Program) error { +func (*netfilterLink) Update(new *ebpf.Program) error { return fmt.Errorf("netfilter update: %w", ErrNotSupported) } diff --git a/vendor/github.com/cilium/ebpf/link/perf_event.go b/vendor/github.com/cilium/ebpf/link/perf_event.go index 7440e8b292a..1d8feb58c1c 100644 --- a/vendor/github.com/cilium/ebpf/link/perf_event.go +++ b/vendor/github.com/cilium/ebpf/link/perf_event.go @@ -115,7 +115,7 @@ func (pl *perfEventLink) Close() error { return nil } -func (pl *perfEventLink) Update(_ *ebpf.Program) error { +func (pl *perfEventLink) Update(prog *ebpf.Program) error { return fmt.Errorf("perf event link update: %w", ErrNotSupported) } @@ -185,7 +185,7 @@ func (pi *perfEventIoctl) isLink() {} // // Detaching a program from a perf event is currently not possible, so a // program replacement mechanism cannot be implemented for perf events. -func (pi *perfEventIoctl) Update(_ *ebpf.Program) error { +func (pi *perfEventIoctl) Update(prog *ebpf.Program) error { return fmt.Errorf("perf event ioctl update: %w", ErrNotSupported) } @@ -303,7 +303,7 @@ func openTracepointPerfEvent(tid uint64, pid int) (*sys.FD, error) { // // https://elixir.bootlin.com/linux/v5.16.8/source/kernel/bpf/syscall.c#L4307 // https://github.com/torvalds/linux/commit/b89fbfbb854c9afc3047e8273cc3a694650b802e -var haveBPFLinkPerfEvent = internal.NewFeatureTest("bpf_link_perf_event", func() error { +var haveBPFLinkPerfEvent = internal.NewFeatureTest("bpf_link_perf_event", "5.15", func() error { prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ Name: "probe_bpf_perf_link", Type: ebpf.Kprobe, @@ -329,4 +329,4 @@ var haveBPFLinkPerfEvent = internal.NewFeatureTest("bpf_link_perf_event", func() return nil } return err -}, "5.15") +}) diff --git a/vendor/github.com/cilium/ebpf/link/syscalls.go b/vendor/github.com/cilium/ebpf/link/syscalls.go index 25951b017dd..d09b5acb0f3 100644 --- a/vendor/github.com/cilium/ebpf/link/syscalls.go +++ b/vendor/github.com/cilium/ebpf/link/syscalls.go @@ -30,7 +30,7 @@ const ( NetkitType = sys.BPF_LINK_TYPE_NETKIT ) -var haveProgAttach = internal.NewFeatureTest("BPF_PROG_ATTACH", func() error { +var haveProgAttach = internal.NewFeatureTest("BPF_PROG_ATTACH", "4.10", func() error { prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ Type: ebpf.CGroupSKB, License: "MIT", @@ -48,9 +48,9 @@ var haveProgAttach = internal.NewFeatureTest("BPF_PROG_ATTACH", func() error { // have the syscall. prog.Close() return nil -}, "4.10") +}) -var haveProgAttachReplace = internal.NewFeatureTest("BPF_PROG_ATTACH atomic replacement of MULTI progs", func() error { +var haveProgAttachReplace = internal.NewFeatureTest("BPF_PROG_ATTACH atomic replacement of MULTI progs", "5.5", func() error { if err := haveProgAttach(); err != nil { return err } @@ -90,9 +90,9 @@ var haveProgAttachReplace = internal.NewFeatureTest("BPF_PROG_ATTACH atomic repl return nil } return err -}, "5.5") +}) -var haveBPFLink = internal.NewFeatureTest("bpf_link", func() error { +var haveBPFLink = internal.NewFeatureTest("bpf_link", "5.7", func() error { attr := sys.LinkCreateAttr{ // This is a hopefully invalid file descriptor, which triggers EBADF. TargetFd: ^uint32(0), @@ -107,9 +107,9 @@ var haveBPFLink = internal.NewFeatureTest("bpf_link", func() error { return nil } return err -}, "5.7") +}) -var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", func() error { +var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", "4.15", func() error { attr := sys.ProgQueryAttr{ // We rely on this being checked during the syscall. // With an otherwise correct payload we expect EBADF here @@ -127,9 +127,9 @@ var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", func() error { return ErrNotSupported } return errors.New("syscall succeeded unexpectedly") -}, "4.15") +}) -var haveTCX = internal.NewFeatureTest("tcx", func() error { +var haveTCX = internal.NewFeatureTest("tcx", "6.6", func() error { prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ Type: ebpf.SchedCLS, License: "MIT", @@ -162,9 +162,9 @@ var haveTCX = internal.NewFeatureTest("tcx", func() error { return ErrNotSupported } return errors.New("syscall succeeded unexpectedly") -}, "6.6") +}) -var haveNetkit = internal.NewFeatureTest("netkit", func() error { +var haveNetkit = internal.NewFeatureTest("netkit", "6.7", func() error { prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ Type: ebpf.SchedCLS, License: "MIT", @@ -197,4 +197,4 @@ var haveNetkit = internal.NewFeatureTest("netkit", func() error { return ErrNotSupported } return errors.New("syscall succeeded unexpectedly") -}, "6.7") +}) diff --git a/vendor/github.com/cilium/ebpf/link/tracing.go b/vendor/github.com/cilium/ebpf/link/tracing.go index a461007f9f5..9e570afc96a 100644 --- a/vendor/github.com/cilium/ebpf/link/tracing.go +++ b/vendor/github.com/cilium/ebpf/link/tracing.go @@ -14,7 +14,7 @@ type tracing struct { RawLink } -func (f *tracing) Update(_ *ebpf.Program) error { +func (f *tracing) Update(new *ebpf.Program) error { return fmt.Errorf("tracing update: %w", ErrNotSupported) } diff --git a/vendor/github.com/cilium/ebpf/link/uprobe.go b/vendor/github.com/cilium/ebpf/link/uprobe.go index 1852a3fadd2..194d1d319a7 100644 --- a/vendor/github.com/cilium/ebpf/link/uprobe.go +++ b/vendor/github.com/cilium/ebpf/link/uprobe.go @@ -16,7 +16,7 @@ var ( uprobeRefCtrOffsetPMUPath = "/sys/bus/event_source/devices/uprobe/format/ref_ctr_offset" // elixir.bootlin.com/linux/v5.15-rc7/source/kernel/events/core.c#L9799 uprobeRefCtrOffsetShift = 32 - haveRefCtrOffsetPMU = internal.NewFeatureTest("RefCtrOffsetPMU", func() error { + haveRefCtrOffsetPMU = internal.NewFeatureTest("RefCtrOffsetPMU", "4.20", func() error { _, err := os.Stat(uprobeRefCtrOffsetPMUPath) if errors.Is(err, os.ErrNotExist) { return internal.ErrNotSupported @@ -25,7 +25,7 @@ var ( return err } return nil - }, "4.20") + }) // ErrNoSymbol indicates that the given symbol was not found // in the ELF symbols table. @@ -321,7 +321,7 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti if err == nil { return tp, nil } - if !errors.Is(err, ErrNotSupported) { + if err != nil && !errors.Is(err, ErrNotSupported) { return nil, fmt.Errorf("creating perf_uprobe PMU: %w", err) } diff --git a/vendor/github.com/cilium/ebpf/link/uprobe_multi.go b/vendor/github.com/cilium/ebpf/link/uprobe_multi.go index 49dc18b4492..aea807b329a 100644 --- a/vendor/github.com/cilium/ebpf/link/uprobe_multi.go +++ b/vendor/github.com/cilium/ebpf/link/uprobe_multi.go @@ -47,7 +47,7 @@ func (ex *Executable) UretprobeMulti(symbols []string, prog *ebpf.Program, opts // The return probe is not limited for symbols entry, so there's no special // setup for return uprobes (other than the extra flag). The symbols, opts.Offsets // and opts.Addresses arrays follow the same logic as for entry uprobes. - return ex.uprobeMulti(symbols, prog, opts, sys.BPF_F_UPROBE_MULTI_RETURN) + return ex.uprobeMulti(symbols, prog, opts, unix.BPF_F_UPROBE_MULTI_RETURN) } func (ex *Executable) uprobeMulti(symbols []string, prog *ebpf.Program, opts *UprobeMultiOptions, flags uint32) (Link, error) { @@ -99,11 +99,8 @@ func (ex *Executable) uprobeMulti(symbols []string, prog *ebpf.Program, opts *Up if errors.Is(err, unix.ESRCH) { return nil, fmt.Errorf("%w (specified pid not found?)", os.ErrNotExist) } - // Since Linux commit 46ba0e49b642 ("bpf: fix multi-uprobe PID filtering - // logic"), if the provided pid overflows MaxInt32 (turning it negative), the - // kernel will return EINVAL instead of ESRCH. if errors.Is(err, unix.EINVAL) { - return nil, fmt.Errorf("%w (invalid pid, missing symbol or prog's AttachType not AttachTraceUprobeMulti?)", err) + return nil, fmt.Errorf("%w (missing symbol or prog's AttachType not AttachTraceUprobeMulti?)", err) } if err != nil { @@ -171,11 +168,11 @@ type uprobeMultiLink struct { var _ Link = (*uprobeMultiLink)(nil) -func (kml *uprobeMultiLink) Update(_ *ebpf.Program) error { +func (kml *uprobeMultiLink) Update(prog *ebpf.Program) error { return fmt.Errorf("update uprobe_multi: %w", ErrNotSupported) } -var haveBPFLinkUprobeMulti = internal.NewFeatureTest("bpf_link_uprobe_multi", func() error { +var haveBPFLinkUprobeMulti = internal.NewFeatureTest("bpf_link_uprobe_multi", "6.6", func() error { prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ Name: "probe_upm_link", Type: ebpf.Kprobe, @@ -216,4 +213,4 @@ var haveBPFLinkUprobeMulti = internal.NewFeatureTest("bpf_link_uprobe_multi", fu // should not happen fd.Close() return errors.New("successfully attached uprobe_multi to /, kernel bug?") -}, "6.6") +}) diff --git a/vendor/github.com/cilium/ebpf/linker.go b/vendor/github.com/cilium/ebpf/linker.go index 6f97af27840..788f21b7b6f 100644 --- a/vendor/github.com/cilium/ebpf/linker.go +++ b/vendor/github.com/cilium/ebpf/linker.go @@ -9,12 +9,10 @@ import ( "io/fs" "math" "slices" - "strings" "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/btf" "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/kallsyms" ) // handles stores handle objects to avoid gc cleanup @@ -459,42 +457,3 @@ func resolveKconfigReferences(insns asm.Instructions) (_ *Map, err error) { return kconfig, nil } - -func resolveKsymReferences(insns asm.Instructions) error { - var missing []string - - iter := insns.Iterate() - for iter.Next() { - ins := iter.Ins - meta, _ := ins.Metadata.Get(ksymMetaKey{}).(*ksymMeta) - if meta == nil { - continue - } - - addr, err := kallsyms.Address(meta.Name) - if err != nil { - return fmt.Errorf("resolve ksym %s: %w", meta.Name, err) - } - if addr != 0 { - ins.Constant = int64(addr) - continue - } - - if meta.Binding == elf.STB_WEAK { - // A weak ksym variable in eBPF C means its resolution is optional. - // Set a zero constant explicitly for clarity. - ins.Constant = 0 - continue - } - - if !slices.Contains(missing, meta.Name) { - missing = append(missing, meta.Name) - } - } - - if len(missing) > 0 { - return fmt.Errorf("kernel is missing symbol: %s", strings.Join(missing, ",")) - } - - return nil -} diff --git a/vendor/github.com/cilium/ebpf/map.go b/vendor/github.com/cilium/ebpf/map.go index e5d8bd78095..0b62101c3cb 100644 --- a/vendor/github.com/cilium/ebpf/map.go +++ b/vendor/github.com/cilium/ebpf/map.go @@ -66,13 +66,16 @@ type MapSpec struct { Pinning PinType // Specify numa node during map creation - // (effective only if sys.BPF_F_NUMA_NODE flag is set, + // (effective only if unix.BPF_F_NUMA_NODE flag is set, // which can be imported from golang.org/x/sys/unix) NumaNode uint32 // The initial contents of the map. May be nil. Contents []MapKV + // Whether to freeze a map after setting its initial contents. + Freeze bool + // InnerMap is used as a template for ArrayOfMaps and HashOfMaps InnerMap *MapSpec @@ -158,17 +161,6 @@ func (spec *MapSpec) fixupMagicFields() (*MapSpec, error) { // behaviour in the past. spec.MaxEntries = n } - - case CPUMap: - n, err := PossibleCPU() - if err != nil { - return nil, fmt.Errorf("fixup cpu map: %w", err) - } - - if n := uint32(n); spec.MaxEntries == 0 || spec.MaxEntries > n { - // Perform clamping similar to PerfEventArray. - spec.MaxEntries = n - } } return spec, nil @@ -198,14 +190,6 @@ func (ms *MapSpec) dataSection() ([]byte, *btf.Datasec, error) { return value, ds, nil } -func (ms *MapSpec) readOnly() bool { - return (ms.Flags & sys.BPF_F_RDONLY_PROG) > 0 -} - -func (ms *MapSpec) writeOnly() bool { - return (ms.Flags & sys.BPF_F_WRONLY_PROG) > 0 -} - // MapKV is used to initialize the contents of a Map. type MapKV struct { Key interface{} @@ -238,7 +222,7 @@ func (ms *MapSpec) Compatible(m *Map) error { // BPF_F_RDONLY_PROG is set unconditionally for devmaps. Explicitly allow this // mismatch. - if !((ms.Type == DevMap || ms.Type == DevMapHash) && m.flags^ms.Flags == sys.BPF_F_RDONLY_PROG) && + if !((ms.Type == DevMap || ms.Type == DevMapHash) && m.flags^ms.Flags == unix.BPF_F_RDONLY_PROG) && m.flags != ms.Flags { diffs = append(diffs, fmt.Sprintf("Flags: %d changed to %d", m.flags, ms.Flags)) } @@ -270,8 +254,6 @@ type Map struct { pinnedPath string // Per CPU maps return values larger than the size in the spec fullValueSize int - - memory *Memory } // NewMapFromFD creates a map from a raw fd. @@ -377,7 +359,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions) (_ *Map, err error) { return nil, errors.New("inner maps cannot be pinned") } - template, err := spec.InnerMap.createMap(nil) + template, err := spec.InnerMap.createMap(nil, opts) if err != nil { return nil, fmt.Errorf("inner map: %w", err) } @@ -389,7 +371,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions) (_ *Map, err error) { innerFd = template.fd } - m, err := spec.createMap(innerFd) + m, err := spec.createMap(innerFd, opts) if err != nil { return nil, err } @@ -405,54 +387,9 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions) (_ *Map, err error) { return m, nil } -// Memory returns a memory-mapped region for the Map. The Map must have been -// created with the BPF_F_MMAPABLE flag. Repeated calls to Memory return the -// same mapping. Callers are responsible for coordinating access to Memory. -func (m *Map) Memory() (*Memory, error) { - if m.memory != nil { - return m.memory, nil - } - - if m.flags&sys.BPF_F_MMAPABLE == 0 { - return nil, fmt.Errorf("Map was not created with the BPF_F_MMAPABLE flag: %w", ErrNotSupported) - } - - size, err := m.memorySize() - if err != nil { - return nil, err - } - - mm, err := newMemory(m.FD(), size) - if err != nil { - return nil, fmt.Errorf("creating new Memory: %w", err) - } - - m.memory = mm - - return mm, nil -} - -func (m *Map) memorySize() (int, error) { - switch m.Type() { - case Array: - // In Arrays, values are always laid out on 8-byte boundaries regardless of - // architecture. Multiply by MaxEntries and align the result to the host's - // page size. - size := int(internal.Align(m.ValueSize(), 8) * m.MaxEntries()) - size = internal.Align(size, os.Getpagesize()) - return size, nil - case Arena: - // For Arenas, MaxEntries denotes the maximum number of pages available to - // the arena. - return int(m.MaxEntries()) * os.Getpagesize(), nil - } - - return 0, fmt.Errorf("determine memory size of map type %s: %w", m.Type(), ErrNotSupported) -} - // createMap validates the spec's properties and creates the map in the kernel // using the given opts. It does not populate or freeze the map. -func (spec *MapSpec) createMap(inner *sys.FD) (_ *Map, err error) { +func (spec *MapSpec) createMap(inner *sys.FD, opts MapOptions) (_ *Map, err error) { closeOnError := func(closer io.Closer) { if err != nil { closer.Close() @@ -479,7 +416,7 @@ func (spec *MapSpec) createMap(inner *sys.FD) (_ *Map, err error) { KeySize: spec.KeySize, ValueSize: spec.ValueSize, MaxEntries: spec.MaxEntries, - MapFlags: spec.Flags, + MapFlags: sys.MapFlags(spec.Flags), NumaNode: spec.NumaNode, } @@ -537,32 +474,32 @@ func handleMapCreateError(attr sys.MapCreateAttr, spec *MapSpec, err error) erro if errors.Is(err, unix.EINVAL) && spec.Type == UnspecifiedMap { return fmt.Errorf("map create: cannot use type %s", UnspecifiedMap) } - if errors.Is(err, unix.EINVAL) && spec.Flags&sys.BPF_F_NO_PREALLOC > 0 { + if errors.Is(err, unix.EINVAL) && spec.Flags&unix.BPF_F_NO_PREALLOC > 0 { return fmt.Errorf("map create: %w (noPrealloc flag may be incompatible with map type %s)", err, spec.Type) } - if spec.Type.canStoreMap() { + switch spec.Type { + case ArrayOfMaps, HashOfMaps: if haveFeatErr := haveNestedMaps(); haveFeatErr != nil { return fmt.Errorf("map create: %w", haveFeatErr) } } - - if spec.readOnly() || spec.writeOnly() { + if spec.Flags&(unix.BPF_F_RDONLY_PROG|unix.BPF_F_WRONLY_PROG) > 0 || spec.Freeze { if haveFeatErr := haveMapMutabilityModifiers(); haveFeatErr != nil { return fmt.Errorf("map create: %w", haveFeatErr) } } - if spec.Flags&sys.BPF_F_MMAPABLE > 0 { + if spec.Flags&unix.BPF_F_MMAPABLE > 0 { if haveFeatErr := haveMmapableMaps(); haveFeatErr != nil { return fmt.Errorf("map create: %w", haveFeatErr) } } - if spec.Flags&sys.BPF_F_INNER_MAP > 0 { + if spec.Flags&unix.BPF_F_INNER_MAP > 0 { if haveFeatErr := haveInnerMaps(); haveFeatErr != nil { return fmt.Errorf("map create: %w", haveFeatErr) } } - if spec.Flags&sys.BPF_F_NO_PREALLOC > 0 { + if spec.Flags&unix.BPF_F_NO_PREALLOC > 0 { if haveFeatErr := haveNoPreallocMaps(); haveFeatErr != nil { return fmt.Errorf("map create: %w", haveFeatErr) } @@ -593,7 +530,6 @@ func newMap(fd *sys.FD, name string, typ MapType, keySize, valueSize, maxEntries flags, "", int(valueSize), - nil, } if !typ.hasPerCPUValue() { @@ -641,12 +577,7 @@ func (m *Map) Flags() uint32 { return m.flags } -// Info returns metadata about the map. This was first introduced in Linux 4.5, -// but newer kernels support more MapInfo fields with the introduction of more -// features. See [MapInfo] and its methods for more details. -// -// Returns an error wrapping ErrNotSupported if the kernel supports neither -// BPF_OBJ_GET_INFO_BY_FD nor reading map information from /proc/self/fdinfo. +// Info returns metadata about the map. func (m *Map) Info() (*MapInfo, error) { return newMapInfoFromFd(m.fd) } @@ -673,7 +604,7 @@ func (m *Map) Handle() (*btf.Handle, error) { type MapLookupFlags uint64 // LookupLock look up the value of a spin-locked map. -const LookupLock MapLookupFlags = sys.BPF_F_LOCK +const LookupLock MapLookupFlags = unix.BPF_F_LOCK // Lookup retrieves a value from a Map. // @@ -1405,7 +1336,6 @@ func (m *Map) Clone() (*Map, error) { m.flags, "", m.fullValueSize, - nil, }, nil } @@ -1419,7 +1349,7 @@ func (m *Map) Clone() (*Map, error) { // This requires bpffs to be mounted above fileName. // See https://docs.cilium.io/en/stable/network/kubernetes/configuration/#mounting-bpffs-with-systemd func (m *Map) Pin(fileName string) error { - if err := sys.Pin(m.pinnedPath, fileName, m.fd); err != nil { + if err := internal.Pin(m.pinnedPath, fileName, m.fd); err != nil { return err } m.pinnedPath = fileName @@ -1432,7 +1362,7 @@ func (m *Map) Pin(fileName string) error { // // Unpinning an unpinned Map returns nil. func (m *Map) Unpin() error { - if err := sys.Unpin(m.pinnedPath); err != nil { + if err := internal.Unpin(m.pinnedPath); err != nil { return err } m.pinnedPath = "" @@ -1470,7 +1400,7 @@ func (m *Map) finalize(spec *MapSpec) error { } } - if isConstantDataSection(spec.Name) || isKconfigSection(spec.Name) { + if spec.Freeze { if err := m.Freeze(); err != nil { return fmt.Errorf("freezing map: %w", err) } @@ -1571,11 +1501,9 @@ func (m *Map) unmarshalValue(value any, buf sysenc.Buffer) error { return buf.Unmarshal(value) } -// LoadPinnedMap opens a Map from a pin (file) on the BPF virtual filesystem. -// -// Requires at least Linux 4.5. +// LoadPinnedMap loads a Map from a BPF file. func LoadPinnedMap(fileName string, opts *LoadPinOptions) (*Map, error) { - fd, typ, err := sys.ObjGetTyped(&sys.ObjGetAttr{ + fd, err := sys.ObjGet(&sys.ObjGetAttr{ Pathname: sys.NewStringPointer(fileName), FileFlags: opts.Marshal(), }) @@ -1583,11 +1511,6 @@ func LoadPinnedMap(fileName string, opts *LoadPinOptions) (*Map, error) { return nil, err } - if typ != sys.BPF_TYPE_MAP { - _ = fd.Close() - return nil, fmt.Errorf("%s is not a Map", fileName) - } - m, err := newMapFromFD(fd) if err == nil { m.pinnedPath = fileName @@ -1607,10 +1530,6 @@ func unmarshalMap(buf sysenc.Buffer) (*Map, error) { // marshalMap marshals the fd of a map into a buffer in host endianness. func marshalMap(m *Map, length int) ([]byte, error) { - if m == nil { - return nil, errors.New("can't marshal a nil Map") - } - if length != 4 { return nil, fmt.Errorf("can't marshal map to %d bytes", length) } diff --git a/vendor/github.com/cilium/ebpf/memory.go b/vendor/github.com/cilium/ebpf/memory.go deleted file mode 100644 index 312c967131a..00000000000 --- a/vendor/github.com/cilium/ebpf/memory.go +++ /dev/null @@ -1,145 +0,0 @@ -package ebpf - -import ( - "errors" - "fmt" - "io" - "runtime" - - "github.com/cilium/ebpf/internal/unix" -) - -// Memory is the building block for accessing the memory of specific bpf map -// types (Array and Arena at the time of writing) without going through the bpf -// syscall interface. -// -// Given the fd of a bpf map created with the BPF_F_MMAPABLE flag, a shared -// 'file'-based memory-mapped region can be allocated in the process' address -// space, exposing the bpf map's memory by simply accessing a memory location. - -var ErrReadOnly = errors.New("resource is read-only") - -// Memory implements accessing a Map's memory without making any syscalls. -// Pay attention to the difference between Go and C struct alignment rules. Use -// [structs.HostLayout] on supported Go versions to help with alignment. -// -// Note on memory coherence: avoid using packed structs in memory shared between -// user space and eBPF C programs. This drops a struct's memory alignment to 1, -// forcing the compiler to use single-byte loads and stores for field accesses. -// This may lead to partially-written data to be observed from user space. -// -// On most architectures, the memmove implementation used by Go's copy() will -// access data in word-sized chunks. If paired with a matching access pattern on -// the eBPF C side (and if using default memory alignment), accessing shared -// memory without atomics or other synchronization primitives should be sound -// for individual values. For accesses beyond a single value, the usual -// concurrent programming rules apply. -type Memory struct { - b []byte - ro bool -} - -func newMemory(fd, size int) (*Memory, error) { - // Typically, maps created with BPF_F_RDONLY_PROG remain writable from user - // space until frozen. As a security precaution, the kernel doesn't allow - // mapping bpf map memory as read-write into user space if the bpf map was - // frozen, or if it was created using the RDONLY_PROG flag. - // - // The user would be able to write to the map after freezing (since the kernel - // can't change the protection mode of an already-mapped page), while the - // verifier assumes the contents to be immutable. - b, err := unix.Mmap(fd, 0, size, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED) - - // If the map is frozen when an rw mapping is requested, expect EPERM. If the - // map was created with BPF_F_RDONLY_PROG, expect EACCES. - var ro bool - if errors.Is(err, unix.EPERM) || errors.Is(err, unix.EACCES) { - ro = true - b, err = unix.Mmap(fd, 0, size, unix.PROT_READ, unix.MAP_SHARED) - } - if err != nil { - return nil, fmt.Errorf("setting up memory-mapped region: %w", err) - } - - mm := &Memory{ - b, - ro, - } - runtime.SetFinalizer(mm, (*Memory).close) - - return mm, nil -} - -func (mm *Memory) close() { - if err := unix.Munmap(mm.b); err != nil { - panic(fmt.Errorf("unmapping memory: %w", err)) - } - mm.b = nil -} - -// Size returns the size of the memory-mapped region in bytes. -func (mm *Memory) Size() int { - return len(mm.b) -} - -// ReadOnly returns true if the memory-mapped region is read-only. -func (mm *Memory) ReadOnly() bool { - return mm.ro -} - -// bounds returns true if an access at off of the given size is within bounds. -func (mm *Memory) bounds(off uint64, size uint64) bool { - return off+size < uint64(len(mm.b)) -} - -// ReadAt implements [io.ReaderAt]. Useful for creating a new [io.OffsetWriter]. -// -// See [Memory] for details around memory coherence. -func (mm *Memory) ReadAt(p []byte, off int64) (int, error) { - if mm.b == nil { - return 0, fmt.Errorf("memory-mapped region closed") - } - - if p == nil { - return 0, fmt.Errorf("input buffer p is nil") - } - - if off < 0 || off >= int64(len(mm.b)) { - return 0, fmt.Errorf("read offset out of range") - } - - n := copy(p, mm.b[off:]) - if n < len(p) { - return n, io.EOF - } - - return n, nil -} - -// WriteAt implements [io.WriterAt]. Useful for creating a new -// [io.SectionReader]. -// -// See [Memory] for details around memory coherence. -func (mm *Memory) WriteAt(p []byte, off int64) (int, error) { - if mm.b == nil { - return 0, fmt.Errorf("memory-mapped region closed") - } - if mm.ro { - return 0, fmt.Errorf("memory-mapped region not writable: %w", ErrReadOnly) - } - - if p == nil { - return 0, fmt.Errorf("output buffer p is nil") - } - - if off < 0 || off >= int64(len(mm.b)) { - return 0, fmt.Errorf("write offset out of range") - } - - n := copy(mm.b[off:], p) - if n < len(p) { - return n, io.EOF - } - - return n, nil -} diff --git a/vendor/github.com/cilium/ebpf/prog.go b/vendor/github.com/cilium/ebpf/prog.go index 4f3ce43bfae..9bc6325f887 100644 --- a/vendor/github.com/cilium/ebpf/prog.go +++ b/vendor/github.com/cilium/ebpf/prog.go @@ -16,7 +16,6 @@ import ( "github.com/cilium/ebpf/btf" "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/kallsyms" - "github.com/cilium/ebpf/internal/linux" "github.com/cilium/ebpf/internal/sys" "github.com/cilium/ebpf/internal/sysenc" "github.com/cilium/ebpf/internal/unix" @@ -47,15 +46,14 @@ const ( outputPad = 256 + 2 ) +// Deprecated: the correct log size is now detected automatically and this +// constant is unused. +const DefaultVerifierLogSize = 64 * 1024 + // minVerifierLogSize is the default number of bytes allocated for the // verifier log. const minVerifierLogSize = 64 * 1024 -// maxVerifierLogSize is the maximum size of verifier log buffer the kernel -// will accept before returning EINVAL. May be increased to MaxUint32 in the -// future, but avoid the unnecessary EINVAL for now. -const maxVerifierLogSize = math.MaxUint32 >> 2 - // ProgramOptions control loading a program into the kernel. type ProgramOptions struct { // Bitmap controlling the detail emitted by the kernel's eBPF verifier log. @@ -75,10 +73,9 @@ type ProgramOptions struct { // attempt at loading the program. LogLevel LogLevel - // Starting size of the verifier log buffer. If the verifier log is larger - // than this size, the buffer will be grown to fit the entire log. Leave at - // its default value unless troubleshooting. - LogSizeStart uint32 + // Deprecated: the correct log buffer size is determined automatically + // and this field is ignored. + LogSize int // Disables the verifier log completely, regardless of other options. LogDisabled bool @@ -165,35 +162,26 @@ func (ps *ProgramSpec) Tag() (string, error) { return ps.Instructions.Tag(internal.NativeEndian) } -// kernelModule returns the kernel module providing the symbol in -// ProgramSpec.AttachTo, if any. Returns an empty string if the symbol is not -// present or not part of a kernel module. -func (ps *ProgramSpec) kernelModule() (string, error) { - if ps.AttachTo == "" && ps.targetsKernelModule() { - return kallsyms.Module(ps.AttachTo) - } - - return "", nil -} - -// targetsKernelModule returns true if the program supports being attached to a -// symbol provided by a kernel module. -func (ps *ProgramSpec) targetsKernelModule() bool { +// KernelModule returns the kernel module, if any, the AttachTo function is contained in. +func (ps *ProgramSpec) KernelModule() (string, error) { if ps.AttachTo == "" { - return false + return "", nil } switch ps.Type { + default: + return "", nil case Tracing: switch ps.AttachType { - case AttachTraceFEntry, AttachTraceFExit: - return true + default: + return "", nil + case AttachTraceFEntry: + case AttachTraceFExit: } + fallthrough case Kprobe: - return true + return kallsyms.KernelModule(ps.AttachTo) } - - return false } // VerifierError is returned by [NewProgram] and [NewProgramWithOptions] if a @@ -273,7 +261,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er // Overwrite Kprobe program version if set to zero or the magic version constant. kv := spec.KernelVersion if spec.Type == Kprobe && (kv == 0 || kv == internal.MagicKernelVersion) { - v, err := linux.KernelVersion() + v, err := internal.KernelVersion() if err != nil { return nil, fmt.Errorf("detecting kernel version: %w", err) } @@ -295,7 +283,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er insns := make(asm.Instructions, len(spec.Instructions)) copy(insns, spec.Instructions) - kmodName, err := spec.kernelModule() + kmodName, err := spec.KernelModule() if err != nil { return nil, fmt.Errorf("kernel module search: %w", err) } @@ -356,10 +344,6 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er } defer kconfig.Close() - if err := resolveKsymReferences(insns); err != nil { - return nil, fmt.Errorf("resolve .ksyms: %w", err) - } - if err := fixupAndValidate(insns); err != nil { return nil, err } @@ -411,10 +395,9 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er // The caller requested a specific verifier log level. Set up the log buffer // so that there is a chance of loading the program in a single shot. - logSize := internal.Between(opts.LogSizeStart, minVerifierLogSize, maxVerifierLogSize) var logBuf []byte if !opts.LogDisabled && opts.LogLevel != 0 { - logBuf = make([]byte, logSize) + logBuf = make([]byte, minVerifierLogSize) attr.LogLevel = opts.LogLevel attr.LogSize = uint32(len(logBuf)) attr.LogBuf = sys.NewSlicePointer(logBuf) @@ -448,11 +431,12 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er attr.LogLevel = LogLevelBranch } - // Make an educated guess how large the buffer should be by multiplying. - // Ensure the size doesn't overflow. - const factor = 2 - logSize = internal.Between(logSize, minVerifierLogSize, maxVerifierLogSize/factor) - logSize *= factor + // Make an educated guess how large the buffer should be. Start + // at minVerifierLogSize and then double the size. + logSize := uint32(max(len(logBuf)*2, minVerifierLogSize)) + if int(logSize) < len(logBuf) { + return nil, errors.New("overflow while probing log buffer size") + } if attr.LogTrueSize != 0 { // The kernel has given us a hint how large the log buffer has to be. @@ -478,12 +462,6 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er return nil, fmt.Errorf("load program: %w (MEMLOCK may be too low, consider rlimit.RemoveMemlock)", err) } - case errors.Is(err, unix.EFAULT): - // EFAULT is returned when the kernel hits a verifier bug, and always - // overrides ENOSPC, defeating the buffer growth strategy. Warn the user - // that they may need to increase the buffer size manually. - return nil, fmt.Errorf("load program: %w (hit verifier bug, increase LogSizeStart to fit the log and check dmesg)", err) - case errors.Is(err, unix.EINVAL): if bytes.Contains(tail, coreBadCall) { err = errBadRelocation @@ -620,7 +598,7 @@ func (p *Program) Clone() (*Program, error) { // This requires bpffs to be mounted above fileName. // See https://docs.cilium.io/en/stable/network/kubernetes/configuration/#mounting-bpffs-with-systemd func (p *Program) Pin(fileName string) error { - if err := sys.Pin(p.pinnedPath, fileName, p.fd); err != nil { + if err := internal.Pin(p.pinnedPath, fileName, p.fd); err != nil { return err } p.pinnedPath = fileName @@ -633,7 +611,7 @@ func (p *Program) Pin(fileName string) error { // // Unpinning an unpinned Program returns nil. func (p *Program) Unpin() error { - if err := sys.Unpin(p.pinnedPath); err != nil { + if err := internal.Unpin(p.pinnedPath); err != nil { return err } p.pinnedPath = "" @@ -721,10 +699,6 @@ func (p *Program) Test(in []byte) (uint32, []byte, error) { // // Note: the same restrictions from Test apply. func (p *Program) Run(opts *RunOptions) (uint32, error) { - if opts == nil { - opts = &RunOptions{} - } - ret, _, err := p.run(opts) if err != nil { return ret, fmt.Errorf("run program: %w", err) @@ -758,7 +732,7 @@ func (p *Program) Benchmark(in []byte, repeat int, reset func()) (uint32, time.D return ret, total, nil } -var haveProgRun = internal.NewFeatureTest("BPF_PROG_RUN", func() error { +var haveProgRun = internal.NewFeatureTest("BPF_PROG_RUN", "4.12", func() error { prog, err := NewProgram(&ProgramSpec{ // SocketFilter does not require privileges on newer kernels. Type: SocketFilter, @@ -800,7 +774,7 @@ var haveProgRun = internal.NewFeatureTest("BPF_PROG_RUN", func() error { } return err -}, "4.12") +}) func (p *Program) run(opts *RunOptions) (uint32, time.Duration, error) { if uint(len(opts.Data)) > math.MaxUint32 { @@ -909,10 +883,6 @@ func unmarshalProgram(buf sysenc.Buffer) (*Program, error) { } func marshalProgram(p *Program, length int) ([]byte, error) { - if p == nil { - return nil, errors.New("can't marshal a nil Program") - } - if length != 4 { return nil, fmt.Errorf("can't marshal program to %d bytes", length) } @@ -922,12 +892,11 @@ func marshalProgram(p *Program, length int) ([]byte, error) { return buf, nil } -// LoadPinnedProgram loads a Program from a pin (file) on the BPF virtual -// filesystem. +// LoadPinnedProgram loads a Program from a BPF file. // // Requires at least Linux 4.11. func LoadPinnedProgram(fileName string, opts *LoadPinOptions) (*Program, error) { - fd, typ, err := sys.ObjGetTyped(&sys.ObjGetAttr{ + fd, err := sys.ObjGet(&sys.ObjGetAttr{ Pathname: sys.NewStringPointer(fileName), FileFlags: opts.Marshal(), }) @@ -935,11 +904,6 @@ func LoadPinnedProgram(fileName string, opts *LoadPinOptions) (*Program, error) return nil, err } - if typ != sys.BPF_TYPE_PROG { - _ = fd.Close() - return nil, fmt.Errorf("%s is not a Program", fileName) - } - info, err := newProgramInfoFromFd(fd) if err != nil { _ = fd.Close() diff --git a/vendor/github.com/cilium/ebpf/syscalls.go b/vendor/github.com/cilium/ebpf/syscalls.go index 25c84c3c5c1..4aef7faebc8 100644 --- a/vendor/github.com/cilium/ebpf/syscalls.go +++ b/vendor/github.com/cilium/ebpf/syscalls.go @@ -10,7 +10,6 @@ import ( "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/linux" "github.com/cilium/ebpf/internal/sys" "github.com/cilium/ebpf/internal/tracefs" "github.com/cilium/ebpf/internal/unix" @@ -61,7 +60,7 @@ func progLoad(insns asm.Instructions, typ ProgramType, license string) (*sys.FD, }) } -var haveNestedMaps = internal.NewFeatureTest("nested maps", func() error { +var haveNestedMaps = internal.NewFeatureTest("nested maps", "4.12", func() error { _, err := sys.MapCreate(&sys.MapCreateAttr{ MapType: sys.MapType(ArrayOfMaps), KeySize: 4, @@ -77,9 +76,9 @@ var haveNestedMaps = internal.NewFeatureTest("nested maps", func() error { return nil } return err -}, "4.12") +}) -var haveMapMutabilityModifiers = internal.NewFeatureTest("read- and write-only maps", func() error { +var haveMapMutabilityModifiers = internal.NewFeatureTest("read- and write-only maps", "5.2", func() error { // This checks BPF_F_RDONLY_PROG and BPF_F_WRONLY_PROG. Since // BPF_MAP_FREEZE appeared in 5.2 as well we don't do a separate check. m, err := sys.MapCreate(&sys.MapCreateAttr{ @@ -87,39 +86,39 @@ var haveMapMutabilityModifiers = internal.NewFeatureTest("read- and write-only m KeySize: 4, ValueSize: 4, MaxEntries: 1, - MapFlags: sys.BPF_F_RDONLY_PROG, + MapFlags: unix.BPF_F_RDONLY_PROG, }) if err != nil { return internal.ErrNotSupported } _ = m.Close() return nil -}, "5.2") +}) -var haveMmapableMaps = internal.NewFeatureTest("mmapable maps", func() error { +var haveMmapableMaps = internal.NewFeatureTest("mmapable maps", "5.5", func() error { // This checks BPF_F_MMAPABLE, which appeared in 5.5 for array maps. m, err := sys.MapCreate(&sys.MapCreateAttr{ MapType: sys.MapType(Array), KeySize: 4, ValueSize: 4, MaxEntries: 1, - MapFlags: sys.BPF_F_MMAPABLE, + MapFlags: unix.BPF_F_MMAPABLE, }) if err != nil { return internal.ErrNotSupported } _ = m.Close() return nil -}, "5.5") +}) -var haveInnerMaps = internal.NewFeatureTest("inner maps", func() error { +var haveInnerMaps = internal.NewFeatureTest("inner maps", "5.10", func() error { // This checks BPF_F_INNER_MAP, which appeared in 5.10. m, err := sys.MapCreate(&sys.MapCreateAttr{ MapType: sys.MapType(Array), KeySize: 4, ValueSize: 4, MaxEntries: 1, - MapFlags: sys.BPF_F_INNER_MAP, + MapFlags: unix.BPF_F_INNER_MAP, }) if err != nil { @@ -127,16 +126,16 @@ var haveInnerMaps = internal.NewFeatureTest("inner maps", func() error { } _ = m.Close() return nil -}, "5.10") +}) -var haveNoPreallocMaps = internal.NewFeatureTest("prealloc maps", func() error { +var haveNoPreallocMaps = internal.NewFeatureTest("prealloc maps", "4.6", func() error { // This checks BPF_F_NO_PREALLOC, which appeared in 4.6. m, err := sys.MapCreate(&sys.MapCreateAttr{ MapType: sys.MapType(Hash), KeySize: 4, ValueSize: 4, MaxEntries: 1, - MapFlags: sys.BPF_F_NO_PREALLOC, + MapFlags: unix.BPF_F_NO_PREALLOC, }) if err != nil { @@ -144,7 +143,7 @@ var haveNoPreallocMaps = internal.NewFeatureTest("prealloc maps", func() error { } _ = m.Close() return nil -}, "4.6") +}) func wrapMapError(err error) error { if err == nil { @@ -170,7 +169,7 @@ func wrapMapError(err error) error { return err } -var haveObjName = internal.NewFeatureTest("object names", func() error { +var haveObjName = internal.NewFeatureTest("object names", "4.15", func() error { attr := sys.MapCreateAttr{ MapType: sys.MapType(Array), KeySize: 4, @@ -179,24 +178,16 @@ var haveObjName = internal.NewFeatureTest("object names", func() error { MapName: sys.NewObjName("feature_test"), } - // Tolerate EPERM as this runs during ELF loading which is potentially - // unprivileged. Only EINVAL is conclusive, thrown from CHECK_ATTR. fd, err := sys.MapCreate(&attr) - if errors.Is(err, unix.EPERM) { - return nil - } - if errors.Is(err, unix.EINVAL) { - return internal.ErrNotSupported - } if err != nil { - return err + return internal.ErrNotSupported } _ = fd.Close() return nil -}, "4.15") +}) -var objNameAllowsDot = internal.NewFeatureTest("dot in object names", func() error { +var objNameAllowsDot = internal.NewFeatureTest("dot in object names", "5.2", func() error { if err := haveObjName(); err != nil { return err } @@ -209,25 +200,16 @@ var objNameAllowsDot = internal.NewFeatureTest("dot in object names", func() err MapName: sys.NewObjName(".test"), } - // Tolerate EPERM, otherwise MapSpec.Name has its dots removed when run by - // unprivileged tools. (bpf2go, other code gen). Only EINVAL is conclusive, - // thrown from bpf_obj_name_cpy(). fd, err := sys.MapCreate(&attr) - if errors.Is(err, unix.EPERM) { - return nil - } - if errors.Is(err, unix.EINVAL) { - return internal.ErrNotSupported - } if err != nil { - return err + return internal.ErrNotSupported } _ = fd.Close() return nil -}, "5.2") +}) -var haveBatchAPI = internal.NewFeatureTest("map batch api", func() error { +var haveBatchAPI = internal.NewFeatureTest("map batch api", "5.6", func() error { var maxEntries uint32 = 2 attr := sys.MapCreateAttr{ MapType: sys.MapType(Hash), @@ -257,9 +239,9 @@ var haveBatchAPI = internal.NewFeatureTest("map batch api", func() error { return internal.ErrNotSupported } return nil -}, "5.6") +}) -var haveProbeReadKernel = internal.NewFeatureTest("bpf_probe_read_kernel", func() error { +var haveProbeReadKernel = internal.NewFeatureTest("bpf_probe_read_kernel", "5.5", func() error { insns := asm.Instructions{ asm.Mov.Reg(asm.R1, asm.R10), asm.Add.Imm(asm.R1, -8), @@ -275,9 +257,9 @@ var haveProbeReadKernel = internal.NewFeatureTest("bpf_probe_read_kernel", func( } _ = fd.Close() return nil -}, "5.5") +}) -var haveBPFToBPFCalls = internal.NewFeatureTest("bpf2bpf calls", func() error { +var haveBPFToBPFCalls = internal.NewFeatureTest("bpf2bpf calls", "4.16", func() error { insns := asm.Instructions{ asm.Call.Label("prog2").WithSymbol("prog1"), asm.Return(), @@ -291,10 +273,10 @@ var haveBPFToBPFCalls = internal.NewFeatureTest("bpf2bpf calls", func() error { } _ = fd.Close() return nil -}, "4.16") +}) -var haveSyscallWrapper = internal.NewFeatureTest("syscall wrapper", func() error { - prefix := linux.PlatformPrefix() +var haveSyscallWrapper = internal.NewFeatureTest("syscall wrapper", "4.17", func() error { + prefix := internal.PlatformPrefix() if prefix == "" { return fmt.Errorf("unable to find the platform prefix for (%s)", runtime.GOARCH) } @@ -320,9 +302,9 @@ var haveSyscallWrapper = internal.NewFeatureTest("syscall wrapper", func() error } return evt.Close() -}, "4.17") +}) -var haveProgramExtInfos = internal.NewFeatureTest("program ext_infos", func() error { +var haveProgramExtInfos = internal.NewFeatureTest("program ext_infos", "5.0", func() error { insns := asm.Instructions{ asm.Mov.Imm(asm.R0, 0), asm.Return(), @@ -352,4 +334,4 @@ var haveProgramExtInfos = internal.NewFeatureTest("program ext_infos", func() er } return err -}, "5.0") +}) diff --git a/vendor/github.com/cilium/ebpf/types.go b/vendor/github.com/cilium/ebpf/types.go index 211b308bbc7..542c2397cab 100644 --- a/vendor/github.com/cilium/ebpf/types.go +++ b/vendor/github.com/cilium/ebpf/types.go @@ -2,6 +2,7 @@ package ebpf import ( "github.com/cilium/ebpf/internal/sys" + "github.com/cilium/ebpf/internal/unix" ) //go:generate go run golang.org/x/tools/cmd/stringer@latest -output types_string.go -type=MapType,ProgramType,PinType @@ -94,14 +95,6 @@ const ( InodeStorage // TaskStorage - Specialized local storage map for task_struct. TaskStorage - // BloomFilter - Space-efficient data structure to quickly test whether an element exists in a set. - BloomFilter - // UserRingbuf - The reverse of RingBuf, used to send messages from user space to BPF programs. - UserRingbuf - // CgroupStorage - Store data keyed on a cgroup. If the cgroup disappears, the key is automatically removed. - CgroupStorage - // Arena - Sparse shared memory region between a BPF program and user space. - Arena ) // hasPerCPUValue returns true if the Map stores a value per CPU. @@ -127,21 +120,6 @@ func (mt MapType) canStoreProgram() bool { return mt == ProgramArray } -// canHaveValueSize returns true if the map type supports setting a value size. -func (mt MapType) canHaveValueSize() bool { - switch mt { - case RingBuf, Arena: - return false - - // Special-case perf events since they require a value size of either 0 or 4 - // for historical reasons. Let the library fix this up later. - case PerfEventArray: - return false - } - - return true -} - // ProgramType of the eBPF program type ProgramType uint32 @@ -285,10 +263,10 @@ func (lpo *LoadPinOptions) Marshal() uint32 { flags := lpo.Flags if lpo.ReadOnly { - flags |= sys.BPF_F_RDONLY + flags |= unix.BPF_F_RDONLY } if lpo.WriteOnly { - flags |= sys.BPF_F_WRONLY + flags |= unix.BPF_F_WRONLY } return flags } diff --git a/vendor/github.com/cilium/ebpf/types_string.go b/vendor/github.com/cilium/ebpf/types_string.go index f06685112c2..ee60b5be5b6 100644 --- a/vendor/github.com/cilium/ebpf/types_string.go +++ b/vendor/github.com/cilium/ebpf/types_string.go @@ -38,15 +38,11 @@ func _() { _ = x[RingBuf-27] _ = x[InodeStorage-28] _ = x[TaskStorage-29] - _ = x[BloomFilter-30] - _ = x[UserRingbuf-31] - _ = x[CgroupStorage-32] - _ = x[Arena-33] } -const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOpsMapRingBufInodeStorageTaskStorageBloomFilterUserRingbufCgroupStorageArena" +const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOpsMapRingBufInodeStorageTaskStorage" -var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 260, 267, 279, 290, 301, 312, 325, 330} +var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 260, 267, 279, 290} func (i MapType) String() string { if i >= MapType(len(_MapType_index)-1) { diff --git a/vendor/github.com/cilium/ebpf/variable.go b/vendor/github.com/cilium/ebpf/variable.go deleted file mode 100644 index 288b173a115..00000000000 --- a/vendor/github.com/cilium/ebpf/variable.go +++ /dev/null @@ -1,230 +0,0 @@ -package ebpf - -import ( - "fmt" - "io" - - "github.com/cilium/ebpf/btf" - "github.com/cilium/ebpf/internal/sysenc" -) - -// VariableSpec is a convenience wrapper for modifying global variables of a -// CollectionSpec before loading it into the kernel. -// -// All operations on a VariableSpec's underlying MapSpec are performed in the -// host's native endianness. -type VariableSpec struct { - name string - offset uint64 - size uint64 - - m *MapSpec - t *btf.Var -} - -// Set sets the value of the VariableSpec to the provided input using the host's -// native endianness. -func (s *VariableSpec) Set(in any) error { - buf, err := sysenc.Marshal(in, int(s.size)) - if err != nil { - return fmt.Errorf("marshaling value %s: %w", s.name, err) - } - - b, _, err := s.m.dataSection() - if err != nil { - return fmt.Errorf("getting data section of map %s: %w", s.m.Name, err) - } - - if int(s.offset+s.size) > len(b) { - return fmt.Errorf("offset %d(+%d) for variable %s is out of bounds", s.offset, s.size, s.name) - } - - // MapSpec.Copy() performs a shallow copy. Fully copy the byte slice - // to avoid any changes affecting other copies of the MapSpec. - cpy := make([]byte, len(b)) - copy(cpy, b) - - buf.CopyTo(cpy[s.offset : s.offset+s.size]) - - s.m.Contents[0] = MapKV{Key: uint32(0), Value: cpy} - - return nil -} - -// Get writes the value of the VariableSpec to the provided output using the -// host's native endianness. -func (s *VariableSpec) Get(out any) error { - b, _, err := s.m.dataSection() - if err != nil { - return fmt.Errorf("getting data section of map %s: %w", s.m.Name, err) - } - - if int(s.offset+s.size) > len(b) { - return fmt.Errorf("offset %d(+%d) for variable %s is out of bounds", s.offset, s.size, s.name) - } - - if err := sysenc.Unmarshal(out, b[s.offset:s.offset+s.size]); err != nil { - return fmt.Errorf("unmarshaling value: %w", err) - } - - return nil -} - -// Size returns the size of the variable in bytes. -func (s *VariableSpec) Size() uint64 { - return s.size -} - -// MapName returns the name of the underlying MapSpec. -func (s *VariableSpec) MapName() string { - return s.m.Name -} - -// Offset returns the offset of the variable in the underlying MapSpec. -func (s *VariableSpec) Offset() uint64 { - return s.offset -} - -// Constant returns true if the VariableSpec represents a variable that is -// read-only from the perspective of the BPF program. -func (s *VariableSpec) Constant() bool { - return s.m.readOnly() -} - -// Type returns the [btf.Var] representing the variable in its data section. -// This is useful for inspecting the variable's decl tags and the type -// information of the inner type. -// -// Returns nil if the original ELF object did not contain BTF information. -func (s *VariableSpec) Type() *btf.Var { - return s.t -} - -func (s *VariableSpec) String() string { - return fmt.Sprintf("%s (type=%v, map=%s, offset=%d, size=%d)", s.name, s.t, s.m.Name, s.offset, s.size) -} - -// copy returns a new VariableSpec with the same values as the original, -// but with a different underlying MapSpec. This is useful when copying a -// CollectionSpec. Returns nil if a MapSpec with the same name is not found. -func (s *VariableSpec) copy(cpy *CollectionSpec) *VariableSpec { - out := &VariableSpec{ - name: s.name, - offset: s.offset, - size: s.size, - } - if s.t != nil { - out.t = btf.Copy(s.t).(*btf.Var) - } - - // Attempt to find a MapSpec with the same name in the copied CollectionSpec. - for _, m := range cpy.Maps { - if m.Name == s.m.Name { - out.m = m - return out - } - } - - return nil -} - -// Variable is a convenience wrapper for modifying global variables of a -// Collection after loading it into the kernel. Operations on a Variable are -// performed using direct memory access, bypassing the BPF map syscall API. -// -// On kernels older than 5.5, most interactions with Variable return -// [ErrNotSupported]. -type Variable struct { - name string - offset uint64 - size uint64 - t *btf.Var - - mm *Memory -} - -func newVariable(name string, offset, size uint64, t *btf.Var, mm *Memory) (*Variable, error) { - if mm != nil { - if int(offset+size) > mm.Size() { - return nil, fmt.Errorf("offset %d(+%d) is out of bounds", offset, size) - } - } - - return &Variable{ - name: name, - offset: offset, - size: size, - t: t, - mm: mm, - }, nil -} - -// Size returns the size of the variable. -func (v *Variable) Size() uint64 { - return v.size -} - -// ReadOnly returns true if the Variable represents a variable that is read-only -// after loading the Collection into the kernel. -// -// On systems without BPF_F_MMAPABLE support, ReadOnly always returns true. -func (v *Variable) ReadOnly() bool { - if v.mm == nil { - return true - } - return v.mm.ReadOnly() -} - -// Type returns the [btf.Var] representing the variable in its data section. -// This is useful for inspecting the variable's decl tags and the type -// information of the inner type. -// -// Returns nil if the original ELF object did not contain BTF information. -func (v *Variable) Type() *btf.Var { - return v.t -} - -func (v *Variable) String() string { - return fmt.Sprintf("%s (type=%v)", v.name, v.t) -} - -// Set the value of the Variable to the provided input. The input must marshal -// to the same length as the size of the Variable. -func (v *Variable) Set(in any) error { - if v.mm == nil { - return fmt.Errorf("variable %s: direct access requires Linux 5.5 or later: %w", v.name, ErrNotSupported) - } - - if v.ReadOnly() { - return fmt.Errorf("variable %s: %w", v.name, ErrReadOnly) - } - - buf, err := sysenc.Marshal(in, int(v.size)) - if err != nil { - return fmt.Errorf("marshaling value %s: %w", v.name, err) - } - - if _, err := v.mm.WriteAt(buf.Bytes(), int64(v.offset)); err != nil { - return fmt.Errorf("writing value to %s: %w", v.name, err) - } - - return nil -} - -// Get writes the value of the Variable to the provided output. The output must -// be a pointer to a value whose size matches the Variable. -func (v *Variable) Get(out any) error { - if v.mm == nil { - return fmt.Errorf("variable %s: direct access requires Linux 5.5 or later: %w", v.name, ErrNotSupported) - } - - if !v.mm.bounds(v.offset, v.size) { - return fmt.Errorf("variable %s: access out of bounds: %w", v.name, io.EOF) - } - - if err := sysenc.Unmarshal(out, v.mm.b[v.offset:v.offset+v.size]); err != nil { - return fmt.Errorf("unmarshaling value %s: %w", v.name, err) - } - - return nil -} diff --git a/vendor/golang.org/x/exp/LICENSE b/vendor/golang.org/x/exp/LICENSE new file mode 100644 index 00000000000..6a66aea5eaf --- /dev/null +++ b/vendor/golang.org/x/exp/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/exp/PATENTS b/vendor/golang.org/x/exp/PATENTS new file mode 100644 index 00000000000..733099041f8 --- /dev/null +++ b/vendor/golang.org/x/exp/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/exp/constraints/constraints.go b/vendor/golang.org/x/exp/constraints/constraints.go new file mode 100644 index 00000000000..2c033dff47e --- /dev/null +++ b/vendor/golang.org/x/exp/constraints/constraints.go @@ -0,0 +1,50 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package constraints defines a set of useful constraints to be used +// with type parameters. +package constraints + +// Signed is a constraint that permits any signed integer type. +// If future releases of Go add new predeclared signed integer types, +// this constraint will be modified to include them. +type Signed interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} + +// Unsigned is a constraint that permits any unsigned integer type. +// If future releases of Go add new predeclared unsigned integer types, +// this constraint will be modified to include them. +type Unsigned interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +// Integer is a constraint that permits any integer type. +// If future releases of Go add new predeclared integer types, +// this constraint will be modified to include them. +type Integer interface { + Signed | Unsigned +} + +// Float is a constraint that permits any floating-point type. +// If future releases of Go add new predeclared floating-point types, +// this constraint will be modified to include them. +type Float interface { + ~float32 | ~float64 +} + +// Complex is a constraint that permits any complex numeric type. +// If future releases of Go add new predeclared complex numeric types, +// this constraint will be modified to include them. +type Complex interface { + ~complex64 | ~complex128 +} + +// Ordered is a constraint that permits any ordered type: any type +// that supports the operators < <= >= >. +// If future releases of Go add new ordered types, +// this constraint will be modified to include them. +type Ordered interface { + Integer | Float | ~string +} diff --git a/vendor/modules.txt b/vendor/modules.txt index e514f0cee48..7037df9a4ef 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2,18 +2,16 @@ ## explicit; go 1.16 github.com/checkpoint-restore/go-criu/v6 github.com/checkpoint-restore/go-criu/v6/rpc -# github.com/cilium/ebpf v0.17.1 -## explicit; go 1.22 +# github.com/cilium/ebpf v0.16.0 +## explicit; go 1.21 github.com/cilium/ebpf github.com/cilium/ebpf/asm github.com/cilium/ebpf/btf github.com/cilium/ebpf/internal github.com/cilium/ebpf/internal/kallsyms github.com/cilium/ebpf/internal/kconfig -github.com/cilium/ebpf/internal/linux github.com/cilium/ebpf/internal/sys github.com/cilium/ebpf/internal/sysenc -github.com/cilium/ebpf/internal/testutils/fdtrace github.com/cilium/ebpf/internal/tracefs github.com/cilium/ebpf/internal/unix github.com/cilium/ebpf/link @@ -80,6 +78,9 @@ github.com/vishvananda/netlink/nl # github.com/vishvananda/netns v0.0.4 ## explicit; go 1.17 github.com/vishvananda/netns +# golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 +## explicit; go 1.18 +golang.org/x/exp/constraints # golang.org/x/net v0.34.0 ## explicit; go 1.18 golang.org/x/net/bpf