From c655a5b6369c203da01ca1c9b46aa614aba2e8fc Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 9 Jul 2020 09:37:05 +0200 Subject: [PATCH 1/2] vendor: update github.com/opencontainers/runc when the systemd cgroup manager is used, controllers not handled by systemd are created manually afterwards. libcontainer didn't correctly cleanup these cgroups that were leaked on cgroup v1. Closes: https://github.com/kubernetes/kubernetes/issues/92766 Signed-off-by: Giuseppe Scrivano --- go.mod | 6 +- go.sum | 9 +- vendor/github.com/cilium/ebpf/BUILD | 1 - vendor/github.com/cilium/ebpf/abi.go | 15 +- vendor/github.com/cilium/ebpf/asm/BUILD | 1 - .../github.com/cilium/ebpf/asm/instruction.go | 37 +- vendor/github.com/cilium/ebpf/collection.go | 29 +- vendor/github.com/cilium/ebpf/elf_reader.go | 364 ++++++++++-------- vendor/github.com/cilium/ebpf/go.mod | 7 +- vendor/github.com/cilium/ebpf/go.sum | 4 - vendor/github.com/cilium/ebpf/internal/BUILD | 6 +- .../github.com/cilium/ebpf/internal/btf/BUILD | 1 - .../cilium/ebpf/internal/btf/btf.go | 261 +++++++++---- .../cilium/ebpf/internal/btf/btf_types.go | 26 +- .../cilium/ebpf/internal/btf/ext_info.go | 44 +-- .../cilium/ebpf/internal/btf/strings.go | 20 +- .../cilium/ebpf/internal/btf/types.go | 37 +- .../github.com/cilium/ebpf/internal/errors.go | 4 +- vendor/github.com/cilium/ebpf/internal/fd.go | 14 +- .../cilium/ebpf/internal/feature.go | 67 +++- vendor/github.com/cilium/ebpf/internal/io.go | 4 +- .../cilium/ebpf/internal/syscall.go | 118 +++++- .../cilium/ebpf/internal/syscall_string.go | 56 +++ .../cilium/ebpf/internal/unix/types_linux.go | 1 + .../cilium/ebpf/internal/unix/types_other.go | 1 + vendor/github.com/cilium/ebpf/linker.go | 8 +- vendor/github.com/cilium/ebpf/map.go | 105 +++-- vendor/github.com/cilium/ebpf/marshalers.go | 28 +- vendor/github.com/cilium/ebpf/prog.go | 168 +++++--- vendor/github.com/cilium/ebpf/run-tests.sh | 32 +- vendor/github.com/cilium/ebpf/syscalls.go | 135 +++---- vendor/github.com/cilium/ebpf/types.go | 34 +- vendor/github.com/cilium/ebpf/types_string.go | 48 ++- .../runc/libcontainer/cgroups/fs/devices.go | 5 +- .../runc/libcontainer/cgroups/fs/fs.go | 35 +- .../runc/libcontainer/cgroups/fs2/devices.go | 3 + .../libcontainer/cgroups/systemd/common.go | 13 +- .../runc/libcontainer/cgroups/systemd/v1.go | 48 +-- .../runc/libcontainer/cgroups/systemd/v2.go | 27 +- .../runc/libcontainer/configs/cgroup_linux.go | 7 + .../runc/libcontainer/container_linux.go | 3 + .../runc/libcontainer/init_linux.go | 6 +- .../runc/libcontainer/user/user.go | 2 +- vendor/modules.txt | 4 +- 44 files changed, 1122 insertions(+), 722 deletions(-) create mode 100644 vendor/github.com/cilium/ebpf/internal/syscall_string.go diff --git a/go.mod b/go.mod index 88623e5a73d..5ce0e7deb2d 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,7 @@ require ( github.com/onsi/ginkgo v1.11.0 github.com/onsi/gomega v1.7.0 github.com/opencontainers/go-digest v1.0.0-rc1 - github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657 + github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb github.com/opencontainers/selinux v1.5.2 github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 @@ -195,7 +195,7 @@ replace ( github.com/chzyer/logex => github.com/chzyer/logex v1.1.10 github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/chzyer/test => github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 - github.com/cilium/ebpf => github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574 + github.com/cilium/ebpf => github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 github.com/clusterhq/flocker-go => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 github.com/cockroachdb/datadriven => github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa github.com/codegangsta/negroni => github.com/codegangsta/negroni v1.0.0 @@ -362,7 +362,7 @@ replace ( github.com/onsi/gomega => github.com/onsi/gomega v1.7.0 github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.1 - github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657 + github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.5.2 github.com/pelletier/go-toml => github.com/pelletier/go-toml v1.2.0 diff --git a/go.sum b/go.sum index b0d54203f42..f08a6755296 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574 h1:G4qUgaciePbY+xCMxxseQhAet478x7qDMdYj3yJgsps= -github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 h1:cHzBGGVew0ezFsq2grfy2RsB8hO/eNyBgOLHBCqfR1U= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 h1:eIHD9GNM3Hp7kcRW5mvcz7WTR3ETeoYYKwpgA04kaXE= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= @@ -370,8 +370,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2i github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657 h1:MIcmh4kMszKK3ub+n11fdkhlqF2vrNKMR0a+/zLm+Xs= -github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657/go.mod h1:3Sm6Dt7OT8z88EbdQqqcRN2oCT54jbi72tT/HqgflT8= +github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb h1:LcPVE5u4oaqw8ffPbJew0lUxZC7faM5t52PgU4px1xY= +github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb/go.mod h1:ZuXhqlr4EiRYgDrBDNfSbE4+n9JX4+V107NwAmF7sZA= github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 h1:9mv9SC7GWmRWE0J/+oD8w3GsN2KYGKtg6uwLN7hfP5E= github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.5.2 h1:F6DgIsjgBIcDksLW4D5RG9bXok6oqZ3nvMwj4ZoFu/Q= @@ -449,6 +449,7 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= diff --git a/vendor/github.com/cilium/ebpf/BUILD b/vendor/github.com/cilium/ebpf/BUILD index 7fd0e0a12bb..bc8c774c3b3 100644 --- a/vendor/github.com/cilium/ebpf/BUILD +++ b/vendor/github.com/cilium/ebpf/BUILD @@ -23,7 +23,6 @@ go_library( "//vendor/github.com/cilium/ebpf/internal:go_default_library", "//vendor/github.com/cilium/ebpf/internal/btf:go_default_library", "//vendor/github.com/cilium/ebpf/internal/unix:go_default_library", - "//vendor/golang.org/x/xerrors:go_default_library", ], ) diff --git a/vendor/github.com/cilium/ebpf/abi.go b/vendor/github.com/cilium/ebpf/abi.go index fd6139c5973..d432eb46f42 100644 --- a/vendor/github.com/cilium/ebpf/abi.go +++ b/vendor/github.com/cilium/ebpf/abi.go @@ -3,14 +3,13 @@ package ebpf import ( "bufio" "bytes" + "errors" "fmt" "io" "os" "syscall" "github.com/cilium/ebpf/internal" - - "golang.org/x/xerrors" ) // MapABI are the attributes of a Map which are available across all supported kernels. @@ -35,7 +34,7 @@ func newMapABIFromSpec(spec *MapSpec) *MapABI { func newMapABIFromFd(fd *internal.FD) (string, *MapABI, error) { info, err := bpfGetMapInfoByFD(fd) if err != nil { - if xerrors.Is(err, syscall.EINVAL) { + if errors.Is(err, syscall.EINVAL) { abi, err := newMapABIFromProc(fd) return "", abi, err } @@ -98,7 +97,7 @@ func newProgramABIFromSpec(spec *ProgramSpec) *ProgramABI { func newProgramABIFromFd(fd *internal.FD) (string, *ProgramABI, error) { info, err := bpfGetProgInfoByFD(fd) if err != nil { - if xerrors.Is(err, syscall.EINVAL) { + if errors.Is(err, syscall.EINVAL) { return newProgramABIFromProc(fd) } @@ -127,7 +126,7 @@ func newProgramABIFromProc(fd *internal.FD) (string, *ProgramABI, error) { "prog_type": &abi.Type, "prog_tag": &name, }) - if xerrors.Is(err, errMissingFields) { + if errors.Is(err, errMissingFields) { return "", nil, &internal.UnsupportedFeatureError{ Name: "reading ABI from /proc/self/fdinfo", MinimumVersion: internal.Version{4, 11, 0}, @@ -153,12 +152,12 @@ func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error { defer fh.Close() if err := scanFdInfoReader(fh, fields); err != nil { - return xerrors.Errorf("%s: %w", fh.Name(), err) + return fmt.Errorf("%s: %w", fh.Name(), err) } return nil } -var errMissingFields = xerrors.New("missing fields") +var errMissingFields = errors.New("missing fields") func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error { var ( @@ -179,7 +178,7 @@ func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error { } if n, err := fmt.Fscanln(bytes.NewReader(parts[1]), field); err != nil || n != 1 { - return xerrors.Errorf("can't parse field %s: %v", name, err) + return fmt.Errorf("can't parse field %s: %v", name, err) } scanned++ diff --git a/vendor/github.com/cilium/ebpf/asm/BUILD b/vendor/github.com/cilium/ebpf/asm/BUILD index d4e6e0e7315..826f0a873d3 100644 --- a/vendor/github.com/cilium/ebpf/asm/BUILD +++ b/vendor/github.com/cilium/ebpf/asm/BUILD @@ -20,7 +20,6 @@ go_library( importmap = "k8s.io/kubernetes/vendor/github.com/cilium/ebpf/asm", importpath = "github.com/cilium/ebpf/asm", visibility = ["//visibility:public"], - deps = ["//vendor/golang.org/x/xerrors:go_default_library"], ) filegroup( diff --git a/vendor/github.com/cilium/ebpf/asm/instruction.go b/vendor/github.com/cilium/ebpf/asm/instruction.go index 02ed6c6afe8..8fbcf56647c 100644 --- a/vendor/github.com/cilium/ebpf/asm/instruction.go +++ b/vendor/github.com/cilium/ebpf/asm/instruction.go @@ -2,12 +2,11 @@ package asm import ( "encoding/binary" + "errors" "fmt" "io" "math" "strings" - - "golang.org/x/xerrors" ) // InstructionSize is the size of a BPF instruction in bytes @@ -43,7 +42,7 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err ins.Constant = int64(bi.Constant) ins.Dst, ins.Src, err = bi.Registers.Unmarshal(bo) if err != nil { - return 0, xerrors.Errorf("can't unmarshal registers: %s", err) + return 0, fmt.Errorf("can't unmarshal registers: %s", err) } if !bi.OpCode.isDWordLoad() { @@ -53,10 +52,10 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err var bi2 bpfInstruction if err := binary.Read(r, bo, &bi2); err != nil { // No Wrap, to avoid io.EOF clash - return 0, xerrors.New("64bit immediate is missing second half") + return 0, errors.New("64bit immediate is missing second half") } if bi2.OpCode != 0 || bi2.Offset != 0 || bi2.Registers != 0 { - return 0, xerrors.New("64bit immediate has non-zero fields") + return 0, errors.New("64bit immediate has non-zero fields") } ins.Constant = int64(uint64(uint32(bi2.Constant))<<32 | uint64(uint32(bi.Constant))) @@ -66,7 +65,7 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err // Marshal encodes a BPF instruction. func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error) { if ins.OpCode == InvalidOpCode { - return 0, xerrors.New("invalid opcode") + return 0, errors.New("invalid opcode") } isDWordLoad := ins.OpCode.isDWordLoad() @@ -79,7 +78,7 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error) regs, err := newBPFRegisters(ins.Dst, ins.Src, bo) if err != nil { - return 0, xerrors.Errorf("can't marshal registers: %s", err) + return 0, fmt.Errorf("can't marshal registers: %s", err) } bpfi := bpfInstruction{ @@ -113,11 +112,11 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error) // Returns an error if the instruction doesn't load a map. func (ins *Instruction) RewriteMapPtr(fd int) error { if !ins.OpCode.isDWordLoad() { - return xerrors.Errorf("%s is not a 64 bit load", ins.OpCode) + return fmt.Errorf("%s is not a 64 bit load", ins.OpCode) } if ins.Src != PseudoMapFD && ins.Src != PseudoMapValue { - return xerrors.New("not a load from a map") + return errors.New("not a load from a map") } // Preserve the offset value for direct map loads. @@ -136,11 +135,11 @@ func (ins *Instruction) mapPtr() uint32 { // Returns an error if the instruction is not a direct load. func (ins *Instruction) RewriteMapOffset(offset uint32) error { if !ins.OpCode.isDWordLoad() { - return xerrors.Errorf("%s is not a 64 bit load", ins.OpCode) + return fmt.Errorf("%s is not a 64 bit load", ins.OpCode) } if ins.Src != PseudoMapValue { - return xerrors.New("not a direct load from a map") + return errors.New("not a direct load from a map") } fd := uint64(ins.Constant) & math.MaxUint32 @@ -251,7 +250,7 @@ func (insns Instructions) String() string { // Returns an error if the symbol isn't used, see IsUnreferencedSymbol. func (insns Instructions) RewriteMapPtr(symbol string, fd int) error { if symbol == "" { - return xerrors.New("empty symbol") + return errors.New("empty symbol") } found := false @@ -286,7 +285,7 @@ func (insns Instructions) SymbolOffsets() (map[string]int, error) { } if _, ok := offsets[ins.Symbol]; ok { - return nil, xerrors.Errorf("duplicate symbol %s", ins.Symbol) + return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol) } offsets[ins.Symbol] = i @@ -324,7 +323,7 @@ func (insns Instructions) marshalledOffsets() (map[string]int, error) { } if _, ok := symbols[ins.Symbol]; ok { - return nil, xerrors.Errorf("duplicate symbol %s", ins.Symbol) + return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol) } symbols[ins.Symbol] = currentPos @@ -405,7 +404,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error { // Rewrite bpf to bpf call offset, ok := absoluteOffsets[ins.Reference] if !ok { - return xerrors.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference) + return fmt.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference) } ins.Constant = int64(offset - num - 1) @@ -414,7 +413,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error { // Rewrite jump to label offset, ok := absoluteOffsets[ins.Reference] if !ok { - return xerrors.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference) + return fmt.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference) } ins.Offset = int16(offset - num - 1) @@ -422,7 +421,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error { n, err := ins.Marshal(w, bo) if err != nil { - return xerrors.Errorf("instruction %d: %w", i, err) + return fmt.Errorf("instruction %d: %w", i, err) } num += int(n / InstructionSize) @@ -446,7 +445,7 @@ func newBPFRegisters(dst, src Register, bo binary.ByteOrder) (bpfRegisters, erro case binary.BigEndian: return bpfRegisters((dst << 4) | (src & 0xF)), nil default: - return 0, xerrors.Errorf("unrecognized ByteOrder %T", bo) + return 0, fmt.Errorf("unrecognized ByteOrder %T", bo) } } @@ -457,7 +456,7 @@ func (r bpfRegisters) Unmarshal(bo binary.ByteOrder) (dst, src Register, err err case binary.BigEndian: return Register(r >> 4), Register(r & 0xf), nil default: - return 0, 0, xerrors.Errorf("unrecognized ByteOrder %T", bo) + return 0, 0, fmt.Errorf("unrecognized ByteOrder %T", bo) } } diff --git a/vendor/github.com/cilium/ebpf/collection.go b/vendor/github.com/cilium/ebpf/collection.go index 5b3ed58f166..0c8b65d94de 100644 --- a/vendor/github.com/cilium/ebpf/collection.go +++ b/vendor/github.com/cilium/ebpf/collection.go @@ -1,12 +1,13 @@ package ebpf import ( + "errors" + "fmt" "math" "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/btf" - "golang.org/x/xerrors" ) // CollectionOptions control loading a collection into the kernel. @@ -64,12 +65,12 @@ func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error { // Not all programs need to use the map default: - return xerrors.Errorf("program %s: %w", progName, err) + return fmt.Errorf("program %s: %w", progName, err) } } if !seen { - return xerrors.Errorf("map %s not referenced by any programs", symbol) + return fmt.Errorf("map %s not referenced by any programs", symbol) } // Prevent NewCollection from creating rewritten maps @@ -96,21 +97,21 @@ func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error { func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error { rodata := cs.Maps[".rodata"] if rodata == nil { - return xerrors.New("missing .rodata section") + return errors.New("missing .rodata section") } if rodata.BTF == nil { - return xerrors.New(".rodata section has no BTF") + return errors.New(".rodata section has no BTF") } if n := len(rodata.Contents); n != 1 { - return xerrors.Errorf("expected one key in .rodata, found %d", n) + return fmt.Errorf("expected one key in .rodata, found %d", n) } kv := rodata.Contents[0] value, ok := kv.Value.([]byte) if !ok { - return xerrors.Errorf("first value in .rodata is %T not []byte", kv.Value) + return fmt.Errorf("first value in .rodata is %T not []byte", kv.Value) } buf := make([]byte, len(value)) @@ -185,14 +186,14 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (col var handle *btf.Handle if mapSpec.BTF != nil { handle, err = loadBTF(btf.MapSpec(mapSpec.BTF)) - if err != nil && !xerrors.Is(err, btf.ErrNotSupported) { + if err != nil && !errors.Is(err, btf.ErrNotSupported) { return nil, err } } m, err := newMapWithBTF(mapSpec, handle) if err != nil { - return nil, xerrors.Errorf("map %s: %w", mapName, err) + return nil, fmt.Errorf("map %s: %w", mapName, err) } maps[mapName] = m } @@ -216,29 +217,29 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (col m := maps[ins.Reference] if m == nil { - return nil, xerrors.Errorf("program %s: missing map %s", progName, ins.Reference) + return nil, fmt.Errorf("program %s: missing map %s", progName, ins.Reference) } fd := m.FD() if fd < 0 { - return nil, xerrors.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd) + return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd) } if err := ins.RewriteMapPtr(m.FD()); err != nil { - return nil, xerrors.Errorf("progam %s: map %s: %w", progName, ins.Reference, err) + return nil, fmt.Errorf("progam %s: map %s: %w", progName, ins.Reference, err) } } var handle *btf.Handle if progSpec.BTF != nil { handle, err = loadBTF(btf.ProgramSpec(progSpec.BTF)) - if err != nil && !xerrors.Is(err, btf.ErrNotSupported) { + if err != nil && !errors.Is(err, btf.ErrNotSupported) { return nil, err } } prog, err := newProgramWithBTF(progSpec, handle, opts.Programs) if err != nil { - return nil, xerrors.Errorf("program %s: %w", progName, err) + return nil, fmt.Errorf("program %s: %w", progName, err) } progs[progName] = prog } diff --git a/vendor/github.com/cilium/ebpf/elf_reader.go b/vendor/github.com/cilium/ebpf/elf_reader.go index 1d35c8fe675..77acaed8d96 100644 --- a/vendor/github.com/cilium/ebpf/elf_reader.go +++ b/vendor/github.com/cilium/ebpf/elf_reader.go @@ -4,6 +4,8 @@ import ( "bytes" "debug/elf" "encoding/binary" + "errors" + "fmt" "io" "math" "os" @@ -13,8 +15,6 @@ import ( "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/btf" "github.com/cilium/ebpf/internal/unix" - - "golang.org/x/xerrors" ) type elfCode struct { @@ -35,7 +35,7 @@ func LoadCollectionSpec(file string) (*CollectionSpec, error) { spec, err := LoadCollectionSpecFromReader(f) if err != nil { - return nil, xerrors.Errorf("file %s: %w", file, err) + return nil, fmt.Errorf("file %s: %w", file, err) } return spec, nil } @@ -50,7 +50,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { symbols, err := f.Symbols() if err != nil { - return nil, xerrors.Errorf("load symbols: %v", err) + return nil, fmt.Errorf("load symbols: %v", err) } ec := &elfCode{f, symbols, symbolsPerSection(symbols), "", 0} @@ -79,13 +79,13 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { dataSections[elf.SectionIndex(i)] = sec case sec.Type == elf.SHT_REL: if int(sec.Info) >= len(ec.Sections) { - return nil, xerrors.Errorf("found relocation section %v for missing section %v", i, sec.Info) + return nil, fmt.Errorf("found relocation section %v for missing section %v", i, sec.Info) } // Store relocations under the section index of the target idx := elf.SectionIndex(sec.Info) if relSections[idx] != nil { - return nil, xerrors.Errorf("section %d has multiple relocation sections", sec.Info) + return nil, fmt.Errorf("section %d has multiple relocation sections", sec.Info) } relSections[idx] = sec case sec.Type == elf.SHT_PROGBITS && (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0: @@ -95,44 +95,52 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { ec.license, err = loadLicense(licenseSection) if err != nil { - return nil, xerrors.Errorf("load license: %w", err) + return nil, fmt.Errorf("load license: %w", err) } ec.version, err = loadVersion(versionSection, ec.ByteOrder) if err != nil { - return nil, xerrors.Errorf("load version: %w", err) + return nil, fmt.Errorf("load version: %w", err) } btfSpec, err := btf.LoadSpecFromReader(rd) if err != nil { - return nil, xerrors.Errorf("load BTF: %w", err) + return nil, fmt.Errorf("load BTF: %w", err) + } + + relocations, referencedSections, err := ec.loadRelocations(relSections) + if err != nil { + return nil, fmt.Errorf("load relocations: %w", err) } maps := make(map[string]*MapSpec) if err := ec.loadMaps(maps, mapSections); err != nil { - return nil, xerrors.Errorf("load maps: %w", err) + return nil, fmt.Errorf("load maps: %w", err) } if len(btfMaps) > 0 { if err := ec.loadBTFMaps(maps, btfMaps, btfSpec); err != nil { - return nil, xerrors.Errorf("load BTF maps: %w", err) + return nil, fmt.Errorf("load BTF maps: %w", err) } } if len(dataSections) > 0 { - if err := ec.loadDataSections(maps, dataSections, btfSpec); err != nil { - return nil, xerrors.Errorf("load data sections: %w", err) + for idx := range dataSections { + if !referencedSections[idx] { + // Prune data sections which are not referenced by any + // instructions. + delete(dataSections, idx) + } } - } - relocations, err := ec.loadRelocations(relSections) - if err != nil { - return nil, xerrors.Errorf("load relocations: %w", err) + if err := ec.loadDataSections(maps, dataSections, btfSpec); err != nil { + return nil, fmt.Errorf("load data sections: %w", err) + } } progs, err := ec.loadPrograms(progSections, relocations, btfSpec) if err != nil { - return nil, xerrors.Errorf("load programs: %w", err) + return nil, fmt.Errorf("load programs: %w", err) } return &CollectionSpec{maps, progs}, nil @@ -140,11 +148,12 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { func loadLicense(sec *elf.Section) (string, error) { if sec == nil { - return "", xerrors.New("missing license section") + return "", nil } + data, err := sec.Data() if err != nil { - return "", xerrors.Errorf("section %s: %v", sec.Name, err) + return "", fmt.Errorf("section %s: %v", sec.Name, err) } return string(bytes.TrimRight(data, "\000")), nil } @@ -156,12 +165,12 @@ func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) { var version uint32 if err := binary.Read(sec.Open(), bo, &version); err != nil { - return 0, xerrors.Errorf("section %s: %v", sec.Name, err) + return 0, fmt.Errorf("section %s: %v", sec.Name, err) } return version, nil } -func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section, relocations map[elf.SectionIndex]map[uint64]elf.Symbol, btf *btf.Spec) (map[string]*ProgramSpec, error) { +func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section, relocations map[elf.SectionIndex]map[uint64]elf.Symbol, btfSpec *btf.Spec) (map[string]*ProgramSpec, error) { var ( progs []*ProgramSpec libs []*ProgramSpec @@ -170,35 +179,36 @@ func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section, for idx, sec := range progSections { syms := ec.symbolsPerSection[idx] if len(syms) == 0 { - return nil, xerrors.Errorf("section %v: missing symbols", sec.Name) + return nil, fmt.Errorf("section %v: missing symbols", sec.Name) } funcSym, ok := syms[0] if !ok { - return nil, xerrors.Errorf("section %v: no label at start", sec.Name) + return nil, fmt.Errorf("section %v: no label at start", sec.Name) } insns, length, err := ec.loadInstructions(sec, syms, relocations[idx]) if err != nil { - return nil, xerrors.Errorf("program %s: can't unmarshal instructions: %w", funcSym.Name, err) + return nil, fmt.Errorf("program %s: can't unmarshal instructions: %w", funcSym.Name, err) } - progType, attachType := getProgType(sec.Name) + progType, attachType, attachTo := getProgType(sec.Name) spec := &ProgramSpec{ Name: funcSym.Name, Type: progType, AttachType: attachType, + AttachTo: attachTo, License: ec.license, KernelVersion: ec.version, Instructions: insns, ByteOrder: ec.ByteOrder, } - if btf != nil { - spec.BTF, err = btf.Program(sec.Name, length) - if err != nil { - return nil, xerrors.Errorf("BTF for section %s (program %s): %w", sec.Name, funcSym.Name, err) + if btfSpec != nil { + spec.BTF, err = btfSpec.Program(sec.Name, length) + if err != nil && !errors.Is(err, btf.ErrNoExtendedInfo) { + return nil, fmt.Errorf("program %s: %w", funcSym.Name, err) } } @@ -216,7 +226,7 @@ func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section, for _, prog := range progs { err := link(prog, libs) if err != nil { - return nil, xerrors.Errorf("program %s: %w", prog.Name, err) + return nil, fmt.Errorf("program %s: %w", prog.Name, err) } res[prog.Name] = prog } @@ -237,14 +247,14 @@ func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations m return insns, offset, nil } if err != nil { - return nil, 0, xerrors.Errorf("offset %d: %w", offset, err) + return nil, 0, fmt.Errorf("offset %d: %w", offset, err) } ins.Symbol = symbols[offset].Name if rel, ok := relocations[offset]; ok { if err = ec.relocateInstruction(&ins, rel); err != nil { - return nil, 0, xerrors.Errorf("offset %d: can't relocate instruction: %w", offset, err) + return nil, 0, fmt.Errorf("offset %d: can't relocate instruction: %w", offset, err) } } @@ -265,7 +275,7 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err // from the section itself. idx := int(rel.Section) if idx > len(ec.Sections) { - return xerrors.New("out-of-bounds section index") + return errors.New("out-of-bounds section index") } name = ec.Sections[idx].Name @@ -285,7 +295,7 @@ outer: // section. Weirdly, the offset of the real symbol in the // section is encoded in the instruction stream. if bind != elf.STB_LOCAL { - return xerrors.Errorf("direct load: %s: unsupported relocation %s", name, bind) + return fmt.Errorf("direct load: %s: unsupported relocation %s", name, bind) } // For some reason, clang encodes the offset of the symbol its @@ -307,13 +317,13 @@ outer: case elf.STT_OBJECT: if bind != elf.STB_GLOBAL { - return xerrors.Errorf("load: %s: unsupported binding: %s", name, bind) + return fmt.Errorf("load: %s: unsupported binding: %s", name, bind) } ins.Src = asm.PseudoMapFD default: - return xerrors.Errorf("load: %s: unsupported relocation: %s", name, typ) + return fmt.Errorf("load: %s: unsupported relocation: %s", name, typ) } // Mark the instruction as needing an update when creating the @@ -324,18 +334,18 @@ outer: case ins.OpCode.JumpOp() == asm.Call: if ins.Src != asm.PseudoCall { - return xerrors.Errorf("call: %s: incorrect source register", name) + return fmt.Errorf("call: %s: incorrect source register", name) } switch typ { case elf.STT_NOTYPE, elf.STT_FUNC: if bind != elf.STB_GLOBAL { - return xerrors.Errorf("call: %s: unsupported binding: %s", name, bind) + return fmt.Errorf("call: %s: unsupported binding: %s", name, bind) } case elf.STT_SECTION: if bind != elf.STB_LOCAL { - return xerrors.Errorf("call: %s: unsupported binding: %s", name, bind) + return fmt.Errorf("call: %s: unsupported binding: %s", name, bind) } // The function we want to call is in the indicated section, @@ -344,23 +354,23 @@ outer: // A value of -1 references the first instruction in the section. offset := int64(int32(ins.Constant)+1) * asm.InstructionSize if offset < 0 { - return xerrors.Errorf("call: %s: invalid offset %d", name, offset) + return fmt.Errorf("call: %s: invalid offset %d", name, offset) } sym, ok := ec.symbolsPerSection[rel.Section][uint64(offset)] if !ok { - return xerrors.Errorf("call: %s: no symbol at offset %d", name, offset) + return fmt.Errorf("call: %s: no symbol at offset %d", name, offset) } ins.Constant = -1 name = sym.Name default: - return xerrors.Errorf("call: %s: invalid symbol type %s", name, typ) + return fmt.Errorf("call: %s: invalid symbol type %s", name, typ) } default: - return xerrors.Errorf("relocation for unsupported instruction: %s", ins.OpCode) + return fmt.Errorf("relocation for unsupported instruction: %s", ins.OpCode) } ins.Reference = name @@ -371,11 +381,11 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio for idx, sec := range mapSections { syms := ec.symbolsPerSection[idx] if len(syms) == 0 { - return xerrors.Errorf("section %v: no symbols", sec.Name) + return fmt.Errorf("section %v: no symbols", sec.Name) } if sec.Size%uint64(len(syms)) != 0 { - return xerrors.Errorf("section %v: map descriptors are not of equal size", sec.Name) + return fmt.Errorf("section %v: map descriptors are not of equal size", sec.Name) } var ( @@ -385,11 +395,11 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio for i, offset := 0, uint64(0); i < len(syms); i, offset = i+1, offset+size { mapSym, ok := syms[offset] if !ok { - return xerrors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset) + return fmt.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset) } if maps[mapSym.Name] != nil { - return xerrors.Errorf("section %v: map %v already exists", sec.Name, mapSym) + return fmt.Errorf("section %v: map %v already exists", sec.Name, mapSym) } lr := io.LimitReader(r, int64(size)) @@ -399,19 +409,19 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio } switch { case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil: - return xerrors.Errorf("map %v: missing type", mapSym) + return fmt.Errorf("map %v: missing type", mapSym) case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil: - return xerrors.Errorf("map %v: missing key size", mapSym) + return fmt.Errorf("map %v: missing key size", mapSym) case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil: - return xerrors.Errorf("map %v: missing value size", mapSym) + return fmt.Errorf("map %v: missing value size", mapSym) case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil: - return xerrors.Errorf("map %v: missing max entries", mapSym) + return fmt.Errorf("map %v: missing max entries", mapSym) case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil: - return xerrors.Errorf("map %v: missing flags", mapSym) + return fmt.Errorf("map %v: missing flags", mapSym) } if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil { - return xerrors.Errorf("map %v: unknown and non-zero fields in definition", mapSym) + return fmt.Errorf("map %v: unknown and non-zero fields in definition", mapSym) } maps[mapSym.Name] = &spec @@ -423,84 +433,116 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error { if spec == nil { - return xerrors.Errorf("missing BTF") + return fmt.Errorf("missing BTF") } for idx, sec := range mapSections { syms := ec.symbolsPerSection[idx] if len(syms) == 0 { - return xerrors.Errorf("section %v: no symbols", sec.Name) + return fmt.Errorf("section %v: no symbols", sec.Name) } for _, sym := range syms { name := sym.Name if maps[name] != nil { - return xerrors.Errorf("section %v: map %v already exists", sec.Name, sym) + return fmt.Errorf("section %v: map %v already exists", sec.Name, sym) } - btfMap, btfMapMembers, err := spec.Map(name) + mapSpec, err := mapSpecFromBTF(spec, name) if err != nil { - return xerrors.Errorf("map %v: can't get BTF: %w", name, err) + return fmt.Errorf("map %v: %w", name, err) } - spec, err := mapSpecFromBTF(btfMap, btfMapMembers) - if err != nil { - return xerrors.Errorf("map %v: %w", name, err) - } - - maps[name] = spec + maps[name] = mapSpec } } return nil } -func mapSpecFromBTF(btfMap *btf.Map, btfMapMembers []btf.Member) (*MapSpec, error) { +func mapSpecFromBTF(spec *btf.Spec, name string) (*MapSpec, error) { + btfMap, btfMapMembers, err := spec.Map(name) + if err != nil { + return nil, fmt.Errorf("can't get BTF: %w", err) + } + + keyType := btf.MapKey(btfMap) + size, err := btf.Sizeof(keyType) + if err != nil { + return nil, fmt.Errorf("can't get size of BTF key: %w", err) + } + keySize := uint32(size) + + valueType := btf.MapValue(btfMap) + size, err = btf.Sizeof(valueType) + if err != nil { + return nil, fmt.Errorf("can't get size of BTF value: %w", err) + } + valueSize := uint32(size) + var ( mapType, flags, maxEntries uint32 - err error ) for _, member := range btfMapMembers { switch member.Name { case "type": mapType, err = uintFromBTF(member.Type) if err != nil { - return nil, xerrors.Errorf("can't get type: %w", err) + return nil, fmt.Errorf("can't get type: %w", err) } case "map_flags": flags, err = uintFromBTF(member.Type) if err != nil { - return nil, xerrors.Errorf("can't get BTF map flags: %w", err) + return nil, fmt.Errorf("can't get BTF map flags: %w", err) } case "max_entries": maxEntries, err = uintFromBTF(member.Type) if err != nil { - return nil, xerrors.Errorf("can't get BTF map max entries: %w", err) + return nil, fmt.Errorf("can't get BTF map max entries: %w", err) } - case "key": - case "value": + case "key_size": + if _, isVoid := keyType.(*btf.Void); !isVoid { + return nil, errors.New("both key and key_size given") + } + + keySize, err = uintFromBTF(member.Type) + if err != nil { + return nil, fmt.Errorf("can't get BTF key size: %w", err) + } + + case "value_size": + if _, isVoid := valueType.(*btf.Void); !isVoid { + return nil, errors.New("both value and value_size given") + } + + valueSize, err = uintFromBTF(member.Type) + if err != nil { + return nil, fmt.Errorf("can't get BTF value size: %w", err) + } + + case "pinning": + pinning, err := uintFromBTF(member.Type) + if err != nil { + return nil, fmt.Errorf("can't get pinning: %w", err) + } + + if pinning != 0 { + return nil, fmt.Errorf("'pinning' attribute not supported: %w", ErrNotSupported) + } + + case "key", "value": default: - return nil, xerrors.Errorf("unrecognized field %s in BTF map definition", member.Name) + return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name) } } - keySize, err := btf.Sizeof(btf.MapKey(btfMap)) - if err != nil { - return nil, xerrors.Errorf("can't get size of BTF key: %w", err) - } - - valueSize, err := btf.Sizeof(btf.MapValue(btfMap)) - if err != nil { - return nil, xerrors.Errorf("can't get size of BTF value: %w", err) - } - return &MapSpec{ Type: MapType(mapType), - KeySize: uint32(keySize), - ValueSize: uint32(valueSize), + KeySize: keySize, + ValueSize: valueSize, MaxEntries: maxEntries, Flags: flags, BTF: btfMap, @@ -512,12 +554,12 @@ func mapSpecFromBTF(btfMap *btf.Map, btfMapMembers []btf.Member) (*MapSpec, erro func uintFromBTF(typ btf.Type) (uint32, error) { ptr, ok := typ.(*btf.Pointer) if !ok { - return 0, xerrors.Errorf("not a pointer: %v", typ) + return 0, fmt.Errorf("not a pointer: %v", typ) } arr, ok := ptr.Target.(*btf.Array) if !ok { - return 0, xerrors.Errorf("not a pointer to array: %v", typ) + return 0, fmt.Errorf("not a pointer to array: %v", typ) } return arr.Nelems, nil @@ -525,7 +567,7 @@ func uintFromBTF(typ btf.Type) (uint32, error) { func (ec *elfCode) loadDataSections(maps map[string]*MapSpec, dataSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error { if spec == nil { - return xerrors.New("data sections require BTF, make sure all consts are marked as static") + return errors.New("data sections require BTF, make sure all consts are marked as static") } for _, sec := range dataSections { @@ -536,11 +578,11 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec, dataSections map[e data, err := sec.Data() if err != nil { - return xerrors.Errorf("data section %s: can't get contents: %w", sec.Name, err) + return fmt.Errorf("data section %s: can't get contents: %w", sec.Name, err) } if uint64(len(data)) > math.MaxUint32 { - return xerrors.Errorf("data section %s: contents exceed maximum size", sec.Name) + return fmt.Errorf("data section %s: contents exceed maximum size", sec.Name) } mapSpec := &MapSpec{ @@ -567,91 +609,79 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec, dataSections map[e return nil } -func getProgType(v string) (ProgramType, AttachType) { - types := map[string]ProgramType{ - // From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c#n3568 - "socket": SocketFilter, - "seccomp": SocketFilter, - "kprobe/": Kprobe, - "uprobe/": Kprobe, - "kretprobe/": Kprobe, - "uretprobe/": Kprobe, - "tracepoint/": TracePoint, - "raw_tracepoint/": RawTracepoint, - "xdp": XDP, - "perf_event": PerfEvent, - "lwt_in": LWTIn, - "lwt_out": LWTOut, - "lwt_xmit": LWTXmit, - "lwt_seg6local": LWTSeg6Local, - "sockops": SockOps, - "sk_skb": SkSKB, - "sk_msg": SkMsg, - "lirc_mode2": LircMode2, - "flow_dissector": FlowDissector, +func getProgType(sectionName string) (ProgramType, AttachType, string) { + types := map[string]struct { + progType ProgramType + attachType AttachType + }{ + // From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c + "socket": {SocketFilter, AttachNone}, + "seccomp": {SocketFilter, AttachNone}, + "kprobe/": {Kprobe, AttachNone}, + "uprobe/": {Kprobe, AttachNone}, + "kretprobe/": {Kprobe, AttachNone}, + "uretprobe/": {Kprobe, AttachNone}, + "tracepoint/": {TracePoint, AttachNone}, + "raw_tracepoint/": {RawTracepoint, AttachNone}, + "xdp": {XDP, AttachNone}, + "perf_event": {PerfEvent, AttachNone}, + "lwt_in": {LWTIn, AttachNone}, + "lwt_out": {LWTOut, AttachNone}, + "lwt_xmit": {LWTXmit, AttachNone}, + "lwt_seg6local": {LWTSeg6Local, AttachNone}, + "sockops": {SockOps, AttachCGroupSockOps}, + "sk_skb/stream_parser": {SkSKB, AttachSkSKBStreamParser}, + "sk_skb/stream_verdict": {SkSKB, AttachSkSKBStreamParser}, + "sk_msg": {SkMsg, AttachSkSKBStreamVerdict}, + "lirc_mode2": {LircMode2, AttachLircMode2}, + "flow_dissector": {FlowDissector, AttachFlowDissector}, + "iter/": {Tracing, AttachTraceIter}, - "cgroup_skb/": CGroupSKB, - "cgroup/dev": CGroupDevice, - "cgroup/skb": CGroupSKB, - "cgroup/sock": CGroupSock, - "cgroup/post_bind": CGroupSock, - "cgroup/bind": CGroupSockAddr, - "cgroup/connect": CGroupSockAddr, - "cgroup/sendmsg": CGroupSockAddr, - "cgroup/recvmsg": CGroupSockAddr, - "cgroup/sysctl": CGroupSysctl, - "cgroup/getsockopt": CGroupSockopt, - "cgroup/setsockopt": CGroupSockopt, - "classifier": SchedCLS, - "action": SchedACT, - } - attachTypes := map[string]AttachType{ - "cgroup_skb/ingress": AttachCGroupInetIngress, - "cgroup_skb/egress": AttachCGroupInetEgress, - "cgroup/sock": AttachCGroupInetSockCreate, - "cgroup/post_bind4": AttachCGroupInet4PostBind, - "cgroup/post_bind6": AttachCGroupInet6PostBind, - "cgroup/dev": AttachCGroupDevice, - "sockops": AttachCGroupSockOps, - "sk_skb/stream_parser": AttachSkSKBStreamParser, - "sk_skb/stream_verdict": AttachSkSKBStreamVerdict, - "sk_msg": AttachSkSKBStreamVerdict, - "lirc_mode2": AttachLircMode2, - "flow_dissector": AttachFlowDissector, - "cgroup/bind4": AttachCGroupInet4Bind, - "cgroup/bind6": AttachCGroupInet6Bind, - "cgroup/connect4": AttachCGroupInet4Connect, - "cgroup/connect6": AttachCGroupInet6Connect, - "cgroup/sendmsg4": AttachCGroupUDP4Sendmsg, - "cgroup/sendmsg6": AttachCGroupUDP6Sendmsg, - "cgroup/recvmsg4": AttachCGroupUDP4Recvmsg, - "cgroup/recvmsg6": AttachCGroupUDP6Recvmsg, - "cgroup/sysctl": AttachCGroupSysctl, - "cgroup/getsockopt": AttachCGroupGetsockopt, - "cgroup/setsockopt": AttachCGroupSetsockopt, - } - attachType := AttachNone - for k, t := range attachTypes { - if strings.HasPrefix(v, k) { - attachType = t - } + "cgroup_skb/ingress": {CGroupSKB, AttachCGroupInetIngress}, + "cgroup_skb/egress": {CGroupSKB, AttachCGroupInetEgress}, + "cgroup/dev": {CGroupDevice, AttachCGroupDevice}, + "cgroup/skb": {CGroupSKB, AttachNone}, + "cgroup/sock": {CGroupSock, AttachCGroupInetSockCreate}, + "cgroup/post_bind4": {CGroupSock, AttachCGroupInet4PostBind}, + "cgroup/post_bind6": {CGroupSock, AttachCGroupInet6PostBind}, + "cgroup/bind4": {CGroupSockAddr, AttachCGroupInet4Bind}, + "cgroup/bind6": {CGroupSockAddr, AttachCGroupInet6Bind}, + "cgroup/connect4": {CGroupSockAddr, AttachCGroupInet4Connect}, + "cgroup/connect6": {CGroupSockAddr, AttachCGroupInet6Connect}, + "cgroup/sendmsg4": {CGroupSockAddr, AttachCGroupUDP4Sendmsg}, + "cgroup/sendmsg6": {CGroupSockAddr, AttachCGroupUDP6Sendmsg}, + "cgroup/recvmsg4": {CGroupSockAddr, AttachCGroupUDP4Recvmsg}, + "cgroup/recvmsg6": {CGroupSockAddr, AttachCGroupUDP6Recvmsg}, + "cgroup/sysctl": {CGroupSysctl, AttachCGroupSysctl}, + "cgroup/getsockopt": {CGroupSockopt, AttachCGroupGetsockopt}, + "cgroup/setsockopt": {CGroupSockopt, AttachCGroupSetsockopt}, + "classifier": {SchedCLS, AttachNone}, + "action": {SchedACT, AttachNone}, } - for k, t := range types { - if strings.HasPrefix(v, k) { - return t, attachType + for prefix, t := range types { + if !strings.HasPrefix(sectionName, prefix) { + continue } + + if !strings.HasSuffix(prefix, "/") { + return t.progType, t.attachType, "" + } + + return t.progType, t.attachType, sectionName[len(prefix):] } - return UnspecifiedProgram, AttachNone + + return UnspecifiedProgram, AttachNone, "" } -func (ec *elfCode) loadRelocations(sections map[elf.SectionIndex]*elf.Section) (map[elf.SectionIndex]map[uint64]elf.Symbol, error) { +func (ec *elfCode) loadRelocations(sections map[elf.SectionIndex]*elf.Section) (map[elf.SectionIndex]map[uint64]elf.Symbol, map[elf.SectionIndex]bool, error) { result := make(map[elf.SectionIndex]map[uint64]elf.Symbol) + targets := make(map[elf.SectionIndex]bool) for idx, sec := range sections { rels := make(map[uint64]elf.Symbol) if sec.Entsize < 16 { - return nil, xerrors.Errorf("section %s: relocations are less than 16 bytes", sec.Name) + return nil, nil, fmt.Errorf("section %s: relocations are less than 16 bytes", sec.Name) } r := sec.Open() @@ -660,20 +690,22 @@ func (ec *elfCode) loadRelocations(sections map[elf.SectionIndex]*elf.Section) ( var rel elf.Rel64 if binary.Read(ent, ec.ByteOrder, &rel) != nil { - return nil, xerrors.Errorf("can't parse relocation at offset %v", off) + return nil, nil, fmt.Errorf("can't parse relocation at offset %v", off) } symNo := int(elf.R_SYM64(rel.Info) - 1) if symNo >= len(ec.symbols) { - return nil, xerrors.Errorf("relocation at offset %d: symbol %v doesnt exist", off, symNo) + return nil, nil, fmt.Errorf("relocation at offset %d: symbol %v doesnt exist", off, symNo) } + symbol := ec.symbols[symNo] + targets[symbol.Section] = true rels[rel.Off] = ec.symbols[symNo] } result[idx] = rels } - return result, nil + return result, targets, nil } func symbolsPerSection(symbols []elf.Symbol) map[elf.SectionIndex]map[uint64]elf.Symbol { diff --git a/vendor/github.com/cilium/ebpf/go.mod b/vendor/github.com/cilium/ebpf/go.mod index 1d3420b8595..a05cf85eddd 100644 --- a/vendor/github.com/cilium/ebpf/go.mod +++ b/vendor/github.com/cilium/ebpf/go.mod @@ -1,8 +1,5 @@ module github.com/cilium/ebpf -go 1.12 +go 1.13 -require ( - golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 -) +require golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 diff --git a/vendor/github.com/cilium/ebpf/go.sum b/vendor/github.com/cilium/ebpf/go.sum index c4e24f505cb..e8b62417e81 100644 --- a/vendor/github.com/cilium/ebpf/go.sum +++ b/vendor/github.com/cilium/ebpf/go.sum @@ -1,6 +1,2 @@ -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/cilium/ebpf/internal/BUILD b/vendor/github.com/cilium/ebpf/internal/BUILD index 1a5c66aeec9..5eacb314fe2 100644 --- a/vendor/github.com/cilium/ebpf/internal/BUILD +++ b/vendor/github.com/cilium/ebpf/internal/BUILD @@ -14,14 +14,12 @@ go_library( "ptr_32_le.go", "ptr_64.go", "syscall.go", + "syscall_string.go", ], importmap = "k8s.io/kubernetes/vendor/github.com/cilium/ebpf/internal", importpath = "github.com/cilium/ebpf/internal", visibility = ["//vendor/github.com/cilium/ebpf:__subpackages__"], - deps = [ - "//vendor/github.com/cilium/ebpf/internal/unix:go_default_library", - "//vendor/golang.org/x/xerrors:go_default_library", - ], + deps = ["//vendor/github.com/cilium/ebpf/internal/unix:go_default_library"], ) filegroup( diff --git a/vendor/github.com/cilium/ebpf/internal/btf/BUILD b/vendor/github.com/cilium/ebpf/internal/btf/BUILD index 913d5ef87fc..b25e83c0f46 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/BUILD +++ b/vendor/github.com/cilium/ebpf/internal/btf/BUILD @@ -17,7 +17,6 @@ go_library( "//vendor/github.com/cilium/ebpf/asm:go_default_library", "//vendor/github.com/cilium/ebpf/internal:go_default_library", "//vendor/github.com/cilium/ebpf/internal/unix:go_default_library", - "//vendor/golang.org/x/xerrors:go_default_library", ], ) diff --git a/vendor/github.com/cilium/ebpf/internal/btf/btf.go b/vendor/github.com/cilium/ebpf/internal/btf/btf.go index 85968cfcb04..3dd000a284e 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/btf.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/btf.go @@ -4,23 +4,27 @@ import ( "bytes" "debug/elf" "encoding/binary" + "errors" + "fmt" "io" "io/ioutil" "math" + "os" "reflect" + "sync" "unsafe" "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/unix" - - "golang.org/x/xerrors" ) const btfMagic = 0xeB9F // Errors returned by BTF functions. var ( - ErrNotSupported = internal.ErrNotSupported + ErrNotSupported = internal.ErrNotSupported + ErrNotFound = errors.New("not found") + ErrNoExtendedInfo = errors.New("no extended info") ) // Spec represents decoded BTF. @@ -73,7 +77,7 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { } if sec.Size > math.MaxUint32 { - return nil, xerrors.Errorf("section %s exceeds maximum size", sec.Name) + return nil, fmt.Errorf("section %s exceeds maximum size", sec.Name) } sectionSizes[sec.Name] = uint32(sec.Size) @@ -86,7 +90,7 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { symbols, err := file.Symbols() if err != nil { - return nil, xerrors.Errorf("can't read symbols: %v", err) + return nil, fmt.Errorf("can't read symbols: %v", err) } variableOffsets := make(map[variable]uint32) @@ -102,13 +106,31 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { } if symbol.Value > math.MaxUint32 { - return nil, xerrors.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name) + return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name) } variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value) } - rawTypes, rawStrings, err := parseBTF(btfSection.Open(), file.ByteOrder) + spec, err := loadNakedSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets) + if err != nil { + return nil, err + } + + if btfExtSection == nil { + return spec, nil + } + + spec.funcInfos, spec.lineInfos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings) + if err != nil { + return nil, fmt.Errorf("can't read ext info: %w", err) + } + + return spec, nil +} + +func loadNakedSpec(btf io.ReadSeeker, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) { + rawTypes, rawStrings, err := parseBTF(btf, bo) if err != nil { return nil, err } @@ -123,77 +145,99 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { return nil, err } - var ( - funcInfos = make(map[string]extInfo) - lineInfos = make(map[string]extInfo) - ) - if btfExtSection != nil { - funcInfos, lineInfos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, rawStrings) - if err != nil { - return nil, xerrors.Errorf("can't read ext info: %w", err) - } - } - return &Spec{ rawTypes: rawTypes, types: types, strings: rawStrings, - funcInfos: funcInfos, - lineInfos: lineInfos, - byteOrder: file.ByteOrder, + byteOrder: bo, }, nil } +var kernelBTF struct { + sync.Mutex + *Spec +} + +// LoadKernelSpec returns the current kernel's BTF information. +// +// Requires a >= 5.5 kernel with CONFIG_DEBUG_INFO_BTF enabled. Returns +// ErrNotSupported if BTF is not enabled. +func LoadKernelSpec() (*Spec, error) { + kernelBTF.Lock() + defer kernelBTF.Unlock() + + if kernelBTF.Spec != nil { + return kernelBTF.Spec, nil + } + + var err error + kernelBTF.Spec, err = loadKernelSpec() + return kernelBTF.Spec, err +} + +func loadKernelSpec() (*Spec, error) { + fh, err := os.Open("/sys/kernel/btf/vmlinux") + if os.IsNotExist(err) { + return nil, fmt.Errorf("can't open kernel BTF at /sys/kernel/btf/vmlinux: %w", ErrNotFound) + } + if err != nil { + return nil, fmt.Errorf("can't read kernel BTF: %s", err) + } + defer fh.Close() + + return loadNakedSpec(fh, internal.NativeEndian, nil, nil) +} + func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) ([]rawType, stringTable, error) { rawBTF, err := ioutil.ReadAll(btf) if err != nil { - return nil, nil, xerrors.Errorf("can't read BTF: %v", err) + return nil, nil, fmt.Errorf("can't read BTF: %v", err) } rd := bytes.NewReader(rawBTF) var header btfHeader if err := binary.Read(rd, bo, &header); err != nil { - return nil, nil, xerrors.Errorf("can't read header: %v", err) + return nil, nil, fmt.Errorf("can't read header: %v", err) } if header.Magic != btfMagic { - return nil, nil, xerrors.Errorf("incorrect magic value %v", header.Magic) + return nil, nil, fmt.Errorf("incorrect magic value %v", header.Magic) } if header.Version != 1 { - return nil, nil, xerrors.Errorf("unexpected version %v", header.Version) + return nil, nil, fmt.Errorf("unexpected version %v", header.Version) } if header.Flags != 0 { - return nil, nil, xerrors.Errorf("unsupported flags %v", header.Flags) + return nil, nil, fmt.Errorf("unsupported flags %v", header.Flags) } remainder := int64(header.HdrLen) - int64(binary.Size(&header)) if remainder < 0 { - return nil, nil, xerrors.New("header is too short") + return nil, nil, errors.New("header is too short") } if _, err := io.CopyN(internal.DiscardZeroes{}, rd, remainder); err != nil { - return nil, nil, xerrors.Errorf("header padding: %v", err) + return nil, nil, fmt.Errorf("header padding: %v", err) } if _, err := rd.Seek(int64(header.HdrLen+header.StringOff), io.SeekStart); err != nil { - return nil, nil, xerrors.Errorf("can't seek to start of string section: %v", err) + return nil, nil, fmt.Errorf("can't seek to start of string section: %v", err) } rawStrings, err := readStringTable(io.LimitReader(rd, int64(header.StringLen))) if err != nil { - return nil, nil, xerrors.Errorf("can't read type names: %w", err) + return nil, nil, fmt.Errorf("can't read type names: %w", err) } if _, err := rd.Seek(int64(header.HdrLen+header.TypeOff), io.SeekStart); err != nil { - return nil, nil, xerrors.Errorf("can't seek to start of type section: %v", err) + return nil, nil, fmt.Errorf("can't seek to start of type section: %v", err) } rawTypes, err := readTypes(io.LimitReader(rd, int64(header.TypeLen)), bo) if err != nil { - return nil, nil, xerrors.Errorf("can't read types: %w", err) + return nil, nil, fmt.Errorf("can't read types: %w", err) } return rawTypes, rawStrings, nil @@ -215,9 +259,13 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s return err } + if name == ".kconfig" || name == ".ksym" { + return fmt.Errorf("reference to %s: %w", name, ErrNotSupported) + } + size, ok := sectionSizes[name] if !ok { - return xerrors.Errorf("data section %s: missing size", name) + return fmt.Errorf("data section %s: missing size", name) } rawTypes[i].SizeType = size @@ -226,17 +274,17 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s for j, secInfo := range secinfos { id := int(secInfo.Type - 1) if id >= len(rawTypes) { - return xerrors.Errorf("data section %s: invalid type id %d for variable %d", name, id, j) + return fmt.Errorf("data section %s: invalid type id %d for variable %d", name, id, j) } varName, err := rawStrings.Lookup(rawTypes[id].NameOff) if err != nil { - return xerrors.Errorf("data section %s: can't get name for type %d: %w", name, id, err) + return fmt.Errorf("data section %s: can't get name for type %d: %w", name, id, err) } offset, ok := variableOffsets[variable{name, varName}] if !ok { - return xerrors.Errorf("data section %s: missing offset for variable %s", name, varName) + return fmt.Errorf("data section %s: missing offset for variable %s", name, varName) } secinfos[j].Offset = offset @@ -246,7 +294,12 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s return nil } -func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) { +type marshalOpts struct { + ByteOrder binary.ByteOrder + StripFuncLinkage bool +} + +func (s *Spec) marshal(opts marshalOpts) ([]byte, error) { var ( buf bytes.Buffer header = new(btfHeader) @@ -258,9 +311,14 @@ func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) { _, _ = buf.Write(make([]byte, headerLen)) // Write type section, just after the header. - for _, typ := range s.rawTypes { - if err := typ.Marshal(&buf, bo); err != nil { - return nil, xerrors.Errorf("can't marshal BTF: %w", err) + for _, raw := range s.rawTypes { + switch { + case opts.StripFuncLinkage && raw.Kind() == kindFunc: + raw.SetLinkage(linkageStatic) + } + + if err := raw.Marshal(&buf, opts.ByteOrder); err != nil { + return nil, fmt.Errorf("can't marshal BTF: %w", err) } } @@ -282,9 +340,9 @@ func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) { } raw := buf.Bytes() - err := binary.Write(sliceWriter(raw[:headerLen]), bo, header) + err := binary.Write(sliceWriter(raw[:headerLen]), opts.ByteOrder, header) if err != nil { - return nil, xerrors.Errorf("can't write header: %v", err) + return nil, fmt.Errorf("can't write header: %v", err) } return raw, nil @@ -294,7 +352,7 @@ type sliceWriter []byte func (sw sliceWriter) Write(p []byte) (int, error) { if len(p) != len(sw) { - return 0, xerrors.New("size doesn't match") + return 0, errors.New("size doesn't match") } return copy(sw, p), nil @@ -304,17 +362,22 @@ func (sw sliceWriter) Write(p []byte) (int, error) { // // Length is the number of bytes in the raw BPF instruction stream. // -// Returns an error if there is no BTF. +// Returns an error which may wrap ErrNoExtendedInfo if the Spec doesn't +// contain extended BTF info. func (s *Spec) Program(name string, length uint64) (*Program, error) { if length == 0 { - return nil, xerrors.New("length musn't be zero") + return nil, errors.New("length musn't be zero") + } + + if s.funcInfos == nil && s.lineInfos == nil { + return nil, fmt.Errorf("BTF for section %s: %w", name, ErrNoExtendedInfo) } funcInfos, funcOK := s.funcInfos[name] lineInfos, lineOK := s.lineInfos[name] if !funcOK && !lineOK { - return nil, xerrors.Errorf("no BTF for program %s", name) + return nil, fmt.Errorf("no extended BTF info for section %s", name) } return &Program{s, length, funcInfos, lineInfos}, nil @@ -331,7 +394,7 @@ func (s *Spec) Map(name string) (*Map, []Member, error) { mapStruct, ok := mapVar.Type.(*Struct) if !ok { - return nil, nil, xerrors.Errorf("expected struct, have %s", mapVar.Type) + return nil, nil, fmt.Errorf("expected struct, have %s", mapVar.Type) } var key, value Type @@ -346,11 +409,11 @@ func (s *Spec) Map(name string) (*Map, []Member, error) { } if key == nil { - return nil, nil, xerrors.Errorf("map %s: missing 'key' in type", name) + key = (*Void)(nil) } if value == nil { - return nil, nil, xerrors.Errorf("map %s: missing 'value' in type", name) + value = (*Void)(nil) } return &Map{s, key, value}, mapStruct.Members, nil @@ -360,19 +423,18 @@ func (s *Spec) Map(name string) (*Map, []Member, error) { func (s *Spec) Datasec(name string) (*Map, error) { var datasec Datasec if err := s.FindType(name, &datasec); err != nil { - return nil, xerrors.Errorf("data section %s: can't get BTF: %w", name, err) + return nil, fmt.Errorf("data section %s: can't get BTF: %w", name, err) } return &Map{s, &Void{}, &datasec}, nil } -var errNotFound = xerrors.New("not found") - // FindType searches for a type with a specific name. // // hint determines the type of the returned Type. // -// Returns an error if there is no or multiple matches. +// Returns an error wrapping ErrNotFound if no matching +// type exists in spec. func (s *Spec) FindType(name string, typ Type) error { var ( wanted = reflect.TypeOf(typ) @@ -385,14 +447,14 @@ func (s *Spec) FindType(name string, typ Type) error { } if candidate != nil { - return xerrors.Errorf("type %s: multiple candidates for %T", name, typ) + return fmt.Errorf("type %s: multiple candidates for %T", name, typ) } candidate = typ } if candidate == nil { - return xerrors.Errorf("type %s: %w", name, errNotFound) + return fmt.Errorf("type %s: %w", name, ErrNotFound) } value := reflect.Indirect(reflect.ValueOf(copyType(candidate))) @@ -414,16 +476,19 @@ func NewHandle(spec *Spec) (*Handle, error) { } if spec.byteOrder != internal.NativeEndian { - return nil, xerrors.Errorf("can't load %s BTF on %s", spec.byteOrder, internal.NativeEndian) + return nil, fmt.Errorf("can't load %s BTF on %s", spec.byteOrder, internal.NativeEndian) } - btf, err := spec.marshal(internal.NativeEndian) + btf, err := spec.marshal(marshalOpts{ + ByteOrder: internal.NativeEndian, + StripFuncLinkage: haveFuncLinkage() != nil, + }) if err != nil { - return nil, xerrors.Errorf("can't marshal BTF: %w", err) + return nil, fmt.Errorf("can't marshal BTF: %w", err) } if uint64(len(btf)) > math.MaxUint32 { - return nil, xerrors.New("BTF exceeds the maximum size") + return nil, errors.New("BTF exceeds the maximum size") } attr := &bpfLoadBTFAttr{ @@ -507,12 +572,12 @@ func ProgramSpec(s *Program) *Spec { func ProgramAppend(s, other *Program) error { funcInfos, err := s.funcInfos.append(other.funcInfos, s.length) if err != nil { - return xerrors.Errorf("func infos: %w", err) + return fmt.Errorf("func infos: %w", err) } lineInfos, err := s.lineInfos.append(other.lineInfos, s.length) if err != nil { - return xerrors.Errorf("line infos: %w", err) + return fmt.Errorf("line infos: %w", err) } s.length += other.length @@ -566,26 +631,36 @@ func bpfLoadBTF(attr *bpfLoadBTFAttr) (*internal.FD, error) { return internal.NewFD(uint32(fd)), nil } -func minimalBTF(bo binary.ByteOrder) []byte { +func marshalBTF(types interface{}, strings []byte, bo binary.ByteOrder) []byte { const minHeaderLength = 24 + typesLen := uint32(binary.Size(types)) + header := btfHeader{ + Magic: btfMagic, + Version: 1, + HdrLen: minHeaderLength, + TypeOff: 0, + TypeLen: typesLen, + StringOff: typesLen, + StringLen: uint32(len(strings)), + } + + buf := new(bytes.Buffer) + _ = binary.Write(buf, bo, &header) + _ = binary.Write(buf, bo, types) + buf.Write(strings) + + return buf.Bytes() +} + +var haveBTF = internal.FeatureTest("BTF", "5.1", func() (bool, error) { var ( types struct { Integer btfType Var btfType btfVar struct{ Linkage uint32 } } - typLen = uint32(binary.Size(&types)) strings = []byte{0, 'a', 0} - header = btfHeader{ - Magic: btfMagic, - Version: 1, - HdrLen: minHeaderLength, - TypeOff: 0, - TypeLen: typLen, - StringOff: typLen, - StringLen: uint32(len(strings)), - } ) // We use a BTF_KIND_VAR here, to make sure that @@ -596,16 +671,8 @@ func minimalBTF(bo binary.ByteOrder) []byte { types.Var.SetKind(kindVar) types.Var.SizeType = 1 - buf := new(bytes.Buffer) - _ = binary.Write(buf, bo, &header) - _ = binary.Write(buf, bo, &types) - buf.Write(strings) + btf := marshalBTF(&types, strings, internal.NativeEndian) - return buf.Bytes() -} - -var haveBTF = internal.FeatureTest("BTF", "5.1", func() bool { - btf := minimalBTF(internal.NativeEndian) fd, err := bpfLoadBTF(&bpfLoadBTFAttr{ btf: internal.NewSlicePointer(btf), btfSize: uint32(len(btf)), @@ -615,5 +682,35 @@ var haveBTF = internal.FeatureTest("BTF", "5.1", func() bool { } // Check for EINVAL specifically, rather than err != nil since we // otherwise misdetect due to insufficient permissions. - return !xerrors.Is(err, unix.EINVAL) + return !errors.Is(err, unix.EINVAL), nil +}) + +var haveFuncLinkage = internal.FeatureTest("BTF func linkage", "5.6", func() (bool, error) { + var ( + types struct { + FuncProto btfType + Func btfType + } + strings = []byte{0, 'a', 0} + ) + + types.FuncProto.SetKind(kindFuncProto) + types.Func.SetKind(kindFunc) + types.Func.SizeType = 1 // aka FuncProto + types.Func.NameOff = 1 + types.Func.SetLinkage(linkageGlobal) + + btf := marshalBTF(&types, strings, internal.NativeEndian) + + fd, err := bpfLoadBTF(&bpfLoadBTFAttr{ + btf: internal.NewSlicePointer(btf), + btfSize: uint32(len(btf)), + }) + if err == nil { + fd.Close() + } + + // Check for EINVAL specifically, rather than err != nil since we + // otherwise misdetect due to insufficient permissions. + return !errors.Is(err, unix.EINVAL), nil }) diff --git a/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go b/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go index d11240d24cc..e34a87ecb45 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go @@ -4,8 +4,6 @@ import ( "encoding/binary" "fmt" "io" - - "golang.org/x/xerrors" ) // btfKind describes a Type. @@ -33,6 +31,14 @@ const ( kindDatasec ) +type btfFuncLinkage uint8 + +const ( + linkageStatic btfFuncLinkage = iota + linkageGlobal + linkageExtern +) + const ( btfTypeKindShift = 24 btfTypeKindLen = 4 @@ -44,7 +50,7 @@ const ( type btfType struct { NameOff uint32 /* "info" bits arrangement - * bits 0-15: vlen (e.g. # of struct's members) + * bits 0-15: vlen (e.g. # of struct's members), linkage * bits 16-23: unused * bits 24-27: kind (e.g. int, ptr, array...etc) * bits 28-30: unused @@ -130,6 +136,14 @@ func (bt *btfType) SetVlen(vlen int) { bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift) } +func (bt *btfType) Linkage() btfFuncLinkage { + return btfFuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift)) +} + +func (bt *btfType) SetLinkage(linkage btfFuncLinkage) { + bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift) +} + func (bt *btfType) Type() TypeID { // TODO: Panic here if wrong kind? return TypeID(bt.SizeType) @@ -199,7 +213,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) { if err := binary.Read(r, bo, &header); err == io.EOF { return types, nil } else if err != nil { - return nil, xerrors.Errorf("can't read type info for id %v: %v", id, err) + return nil, fmt.Errorf("can't read type info for id %v: %v", id, err) } var data interface{} @@ -228,7 +242,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) { case kindDatasec: data = make([]btfVarSecinfo, header.Vlen()) default: - return nil, xerrors.Errorf("type id %v: unknown kind: %v", id, header.Kind()) + return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind()) } if data == nil { @@ -237,7 +251,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) { } if err := binary.Read(r, bo, data); err != nil { - return nil, xerrors.Errorf("type id %d: kind %v: can't read %T: %v", id, header.Kind(), data, err) + return nil, fmt.Errorf("type id %d: kind %v: can't read %T: %v", id, header.Kind(), data, err) } types = append(types, rawType{header, data}) diff --git a/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go b/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go index 1b1e33c4d42..28918ae9e0c 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go @@ -3,13 +3,13 @@ package btf import ( "bytes" "encoding/binary" + "errors" + "fmt" "io" "io/ioutil" "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/internal" - - "golang.org/x/xerrors" ) type btfExtHeader struct { @@ -27,49 +27,49 @@ type btfExtHeader struct { func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, err error) { var header btfExtHeader if err := binary.Read(r, bo, &header); err != nil { - return nil, nil, xerrors.Errorf("can't read header: %v", err) + return nil, nil, fmt.Errorf("can't read header: %v", err) } if header.Magic != btfMagic { - return nil, nil, xerrors.Errorf("incorrect magic value %v", header.Magic) + return nil, nil, fmt.Errorf("incorrect magic value %v", header.Magic) } if header.Version != 1 { - return nil, nil, xerrors.Errorf("unexpected version %v", header.Version) + return nil, nil, fmt.Errorf("unexpected version %v", header.Version) } if header.Flags != 0 { - return nil, nil, xerrors.Errorf("unsupported flags %v", header.Flags) + return nil, nil, fmt.Errorf("unsupported flags %v", header.Flags) } remainder := int64(header.HdrLen) - int64(binary.Size(&header)) if remainder < 0 { - return nil, nil, xerrors.New("header is too short") + return nil, nil, errors.New("header is too short") } // Of course, the .BTF.ext header has different semantics than the // .BTF ext header. We need to ignore non-null values. _, err = io.CopyN(ioutil.Discard, r, remainder) if err != nil { - return nil, nil, xerrors.Errorf("header padding: %v", err) + return nil, nil, fmt.Errorf("header padding: %v", err) } if _, err := r.Seek(int64(header.HdrLen+header.FuncInfoOff), io.SeekStart); err != nil { - return nil, nil, xerrors.Errorf("can't seek to function info section: %v", err) + return nil, nil, fmt.Errorf("can't seek to function info section: %v", err) } funcInfo, err = parseExtInfo(io.LimitReader(r, int64(header.FuncInfoLen)), bo, strings) if err != nil { - return nil, nil, xerrors.Errorf("function info: %w", err) + return nil, nil, fmt.Errorf("function info: %w", err) } if _, err := r.Seek(int64(header.HdrLen+header.LineInfoOff), io.SeekStart); err != nil { - return nil, nil, xerrors.Errorf("can't seek to line info section: %v", err) + return nil, nil, fmt.Errorf("can't seek to line info section: %v", err) } lineInfo, err = parseExtInfo(io.LimitReader(r, int64(header.LineInfoLen)), bo, strings) if err != nil { - return nil, nil, xerrors.Errorf("line info: %w", err) + return nil, nil, fmt.Errorf("line info: %w", err) } return funcInfo, lineInfo, nil @@ -92,7 +92,7 @@ type extInfo struct { func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) { if other.recordSize != ei.recordSize { - return extInfo{}, xerrors.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize) + return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize) } records := make([]extInfoRecord, 0, len(ei.records)+len(other.records)) @@ -117,7 +117,7 @@ func (ei extInfo) MarshalBinary() ([]byte, error) { // while the ELF tracks it in bytes. insnOff := uint32(info.InsnOff / asm.InstructionSize) if err := binary.Write(buf, internal.NativeEndian, insnOff); err != nil { - return nil, xerrors.Errorf("can't write instruction offset: %v", err) + return nil, fmt.Errorf("can't write instruction offset: %v", err) } buf.Write(info.Opaque) @@ -129,12 +129,12 @@ func (ei extInfo) MarshalBinary() ([]byte, error) { func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]extInfo, error) { var recordSize uint32 if err := binary.Read(r, bo, &recordSize); err != nil { - return nil, xerrors.Errorf("can't read record size: %v", err) + return nil, fmt.Errorf("can't read record size: %v", err) } if recordSize < 4 { // Need at least insnOff - return nil, xerrors.New("record size too short") + return nil, errors.New("record size too short") } result := make(map[string]extInfo) @@ -143,32 +143,32 @@ func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[st if err := binary.Read(r, bo, &infoHeader); err == io.EOF { return result, nil } else if err != nil { - return nil, xerrors.Errorf("can't read ext info header: %v", err) + return nil, fmt.Errorf("can't read ext info header: %v", err) } secName, err := strings.Lookup(infoHeader.SecNameOff) if err != nil { - return nil, xerrors.Errorf("can't get section name: %w", err) + return nil, fmt.Errorf("can't get section name: %w", err) } if infoHeader.NumInfo == 0 { - return nil, xerrors.Errorf("section %s has invalid number of records", secName) + return nil, fmt.Errorf("section %s has invalid number of records", secName) } var records []extInfoRecord for i := uint32(0); i < infoHeader.NumInfo; i++ { var byteOff uint32 if err := binary.Read(r, bo, &byteOff); err != nil { - return nil, xerrors.Errorf("section %v: can't read extended info offset: %v", secName, err) + return nil, fmt.Errorf("section %v: can't read extended info offset: %v", secName, err) } buf := make([]byte, int(recordSize-4)) if _, err := io.ReadFull(r, buf); err != nil { - return nil, xerrors.Errorf("section %v: can't read record: %v", secName, err) + return nil, fmt.Errorf("section %v: can't read record: %v", secName, err) } if byteOff%asm.InstructionSize != 0 { - return nil, xerrors.Errorf("section %v: offset %v is not aligned with instruction size", secName, byteOff) + return nil, fmt.Errorf("section %v: offset %v is not aligned with instruction size", secName, byteOff) } records = append(records, extInfoRecord{uint64(byteOff), buf}) diff --git a/vendor/github.com/cilium/ebpf/internal/btf/strings.go b/vendor/github.com/cilium/ebpf/internal/btf/strings.go index a5f905f5676..8782643a043 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/strings.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/strings.go @@ -2,10 +2,10 @@ package btf import ( "bytes" + "errors" + "fmt" "io" "io/ioutil" - - "golang.org/x/xerrors" ) type stringTable []byte @@ -13,19 +13,19 @@ type stringTable []byte func readStringTable(r io.Reader) (stringTable, error) { contents, err := ioutil.ReadAll(r) if err != nil { - return nil, xerrors.Errorf("can't read string table: %v", err) + return nil, fmt.Errorf("can't read string table: %v", err) } if len(contents) < 1 { - return nil, xerrors.New("string table is empty") + return nil, errors.New("string table is empty") } if contents[0] != '\x00' { - return nil, xerrors.New("first item in string table is non-empty") + return nil, errors.New("first item in string table is non-empty") } if contents[len(contents)-1] != '\x00' { - return nil, xerrors.New("string table isn't null terminated") + return nil, errors.New("string table isn't null terminated") } return stringTable(contents), nil @@ -33,22 +33,22 @@ func readStringTable(r io.Reader) (stringTable, error) { func (st stringTable) Lookup(offset uint32) (string, error) { if int64(offset) > int64(^uint(0)>>1) { - return "", xerrors.Errorf("offset %d overflows int", offset) + return "", fmt.Errorf("offset %d overflows int", offset) } pos := int(offset) if pos >= len(st) { - return "", xerrors.Errorf("offset %d is out of bounds", offset) + return "", fmt.Errorf("offset %d is out of bounds", offset) } if pos > 0 && st[pos-1] != '\x00' { - return "", xerrors.Errorf("offset %d isn't start of a string", offset) + return "", fmt.Errorf("offset %d isn't start of a string", offset) } str := st[pos:] end := bytes.IndexByte(str, '\x00') if end == -1 { - return "", xerrors.Errorf("offset %d isn't null terminated", offset) + return "", fmt.Errorf("offset %d isn't null terminated", offset) } return string(str[:end]), nil diff --git a/vendor/github.com/cilium/ebpf/internal/btf/types.go b/vendor/github.com/cilium/ebpf/internal/btf/types.go index 101a40f3213..264142abc0a 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/types.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/types.go @@ -1,9 +1,9 @@ package btf import ( + "errors" + "fmt" "math" - - "golang.org/x/xerrors" ) const maxTypeDepth = 32 @@ -38,9 +38,10 @@ func (n Name) name() string { // Void is the unit type of BTF. type Void struct{} -func (v Void) ID() TypeID { return 0 } -func (v Void) copy() Type { return Void{} } -func (v Void) walk(*copyStack) {} +func (v *Void) ID() TypeID { return 0 } +func (v *Void) size() uint32 { return 0 } +func (v *Void) copy() Type { return (*Void)(nil) } +func (v *Void) walk(*copyStack) {} // Int is an integer of a given length. type Int struct { @@ -310,7 +311,7 @@ func Sizeof(typ Type) (int, error) { switch v := typ.(type) { case *Array: if n > 0 && int64(v.Nelems) > math.MaxInt64/n { - return 0, xerrors.New("overflow") + return 0, errors.New("overflow") } // Arrays may be of zero length, which allows @@ -336,22 +337,22 @@ func Sizeof(typ Type) (int, error) { continue default: - return 0, xerrors.Errorf("unrecognized type %T", typ) + return 0, fmt.Errorf("unrecognized type %T", typ) } if n > 0 && elem > math.MaxInt64/n { - return 0, xerrors.New("overflow") + return 0, errors.New("overflow") } size := n * elem if int64(int(size)) != size { - return 0, xerrors.New("overflow") + return 0, errors.New("overflow") } return int(size), nil } - return 0, xerrors.New("exceeded type depth") + return 0, errors.New("exceeded type depth") } // copy a Type recursively. @@ -433,7 +434,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map for i, btfMember := range raw { name, err := rawStrings.LookupName(btfMember.NameOff) if err != nil { - return nil, xerrors.Errorf("can't get name for member %d: %w", i, err) + return nil, fmt.Errorf("can't get name for member %d: %w", i, err) } members = append(members, Member{ Name: name, @@ -447,7 +448,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map } types := make([]Type, 0, len(rawTypes)) - types = append(types, Void{}) + types = append(types, (*Void)(nil)) namedTypes = make(map[string][]Type) for i, raw := range rawTypes { @@ -460,7 +461,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map name, err := rawStrings.LookupName(raw.NameOff) if err != nil { - return nil, xerrors.Errorf("can't get name for type id %d: %w", id, err) + return nil, fmt.Errorf("can't get name for type id %d: %w", id, err) } switch raw.Kind() { @@ -484,14 +485,14 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map case kindStruct: members, err := convertMembers(raw.data.([]btfMember)) if err != nil { - return nil, xerrors.Errorf("struct %s (id %d): %w", name, id, err) + return nil, fmt.Errorf("struct %s (id %d): %w", name, id, err) } typ = &Struct{id, name, raw.Size(), members} case kindUnion: members, err := convertMembers(raw.data.([]btfMember)) if err != nil { - return nil, xerrors.Errorf("union %s (id %d): %w", name, id, err) + return nil, fmt.Errorf("union %s (id %d): %w", name, id, err) } typ = &Union{id, name, raw.Size(), members} @@ -551,7 +552,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map typ = &Datasec{id, name, raw.SizeType, vars} default: - return nil, xerrors.Errorf("type id %d: unknown kind: %v", id, raw.Kind()) + return nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind()) } types = append(types, typ) @@ -566,7 +567,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map for _, fixup := range fixups { i := int(fixup.id) if i >= len(types) { - return nil, xerrors.Errorf("reference to invalid type id: %d", fixup.id) + return nil, fmt.Errorf("reference to invalid type id: %d", fixup.id) } // Default void (id 0) to unknown @@ -576,7 +577,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map } if expected := fixup.expectedKind; expected != kindUnknown && rawKind != expected { - return nil, xerrors.Errorf("expected type id %d to have kind %s, found %s", fixup.id, expected, rawKind) + return nil, fmt.Errorf("expected type id %d to have kind %s, found %s", fixup.id, expected, rawKind) } *fixup.typ = types[i] diff --git a/vendor/github.com/cilium/ebpf/internal/errors.go b/vendor/github.com/cilium/ebpf/internal/errors.go index 72dedb47772..b6aee81f7de 100644 --- a/vendor/github.com/cilium/ebpf/internal/errors.go +++ b/vendor/github.com/cilium/ebpf/internal/errors.go @@ -2,11 +2,11 @@ package internal import ( "bytes" + "errors" "fmt" "strings" "github.com/cilium/ebpf/internal/unix" - "golang.org/x/xerrors" ) // ErrorWithLog returns an error that includes logs from the @@ -16,7 +16,7 @@ import ( // the log. It is used to check for truncation of the output. func ErrorWithLog(err error, log []byte, logErr error) error { logStr := strings.Trim(CString(log), "\t\r\n ") - if xerrors.Is(logErr, unix.ENOSPC) { + if errors.Is(logErr, unix.ENOSPC) { logStr += " (truncated...)" } diff --git a/vendor/github.com/cilium/ebpf/internal/fd.go b/vendor/github.com/cilium/ebpf/internal/fd.go index f27a1f260ba..af04955bd53 100644 --- a/vendor/github.com/cilium/ebpf/internal/fd.go +++ b/vendor/github.com/cilium/ebpf/internal/fd.go @@ -1,15 +1,16 @@ package internal import ( + "errors" + "fmt" + "os" "runtime" "strconv" "github.com/cilium/ebpf/internal/unix" - - "golang.org/x/xerrors" ) -var ErrClosedFd = xerrors.New("use of closed file descriptor") +var ErrClosedFd = errors.New("use of closed file descriptor") type FD struct { raw int64 @@ -56,8 +57,13 @@ func (fd *FD) Dup() (*FD, error) { dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0) if err != nil { - return nil, xerrors.Errorf("can't dup fd: %v", err) + return nil, fmt.Errorf("can't dup fd: %v", err) } return NewFD(uint32(dup)), nil } + +func (fd *FD) File(name string) *os.File { + fd.Forget() + return os.NewFile(uintptr(fd.raw), name) +} diff --git a/vendor/github.com/cilium/ebpf/internal/feature.go b/vendor/github.com/cilium/ebpf/internal/feature.go index 5ecf954773e..7375b21ef98 100644 --- a/vendor/github.com/cilium/ebpf/internal/feature.go +++ b/vendor/github.com/cilium/ebpf/internal/feature.go @@ -1,14 +1,13 @@ package internal import ( + "errors" "fmt" "sync" - - "golang.org/x/xerrors" ) // ErrNotSupported indicates that a feature is not supported by the current kernel. -var ErrNotSupported = xerrors.New("not supported") +var ErrNotSupported = errors.New("not supported") // UnsupportedFeatureError is returned by FeatureTest() functions. type UnsupportedFeatureError struct { @@ -29,33 +28,63 @@ func (ufe *UnsupportedFeatureError) Is(target error) bool { return target == ErrNotSupported } +type featureTest struct { + sync.Mutex + successful bool + result error +} + +// FeatureTestFn is used to determine whether the kernel supports +// a certain feature. +// +// The return values have the following semantics: +// +// err != nil: the test couldn't be executed +// err == nil && available: the feature is available +// err == nil && !available: the feature isn't available +type FeatureTestFn func() (available bool, err error) + // FeatureTest wraps a function so that it is run at most once. // // name should identify the tested feature, while version must be in the // form Major.Minor[.Patch]. // -// Returns a descriptive UnsupportedFeatureError if the feature is not available. -func FeatureTest(name, version string, fn func() bool) func() error { +// Returns an error wrapping ErrNotSupported if the feature is not supported. +func FeatureTest(name, version string, fn FeatureTestFn) func() error { v, err := NewVersion(version) if err != nil { return func() error { return err } } - var ( - once sync.Once - result error - ) - + ft := new(featureTest) return func() error { - once.Do(func() { - if !fn() { - result = &UnsupportedFeatureError{ - MinimumVersion: v, - Name: name, - } + ft.Lock() + defer ft.Unlock() + + if ft.successful { + return ft.result + } + + available, err := fn() + if errors.Is(err, ErrNotSupported) { + // The feature test aborted because a dependent feature + // is missing, which we should cache. + available = false + } else if err != nil { + // We couldn't execute the feature test to a point + // where it could make a determination. + // Don't cache the result, just return it. + return fmt.Errorf("can't detect support for %s: %w", name, err) + } + + ft.successful = true + if !available { + ft.result = &UnsupportedFeatureError{ + MinimumVersion: v, + Name: name, } - }) - return result + } + return ft.result } } @@ -69,7 +98,7 @@ func NewVersion(ver string) (Version, error) { var major, minor, patch uint16 n, _ := fmt.Sscanf(ver, "%d.%d.%d", &major, &minor, &patch) if n < 2 { - return Version{}, xerrors.Errorf("invalid version: %s", ver) + return Version{}, fmt.Errorf("invalid version: %s", ver) } return Version{major, minor, patch}, nil } diff --git a/vendor/github.com/cilium/ebpf/internal/io.go b/vendor/github.com/cilium/ebpf/internal/io.go index f364f2110a2..fa7402782d7 100644 --- a/vendor/github.com/cilium/ebpf/internal/io.go +++ b/vendor/github.com/cilium/ebpf/internal/io.go @@ -1,6 +1,6 @@ package internal -import "golang.org/x/xerrors" +import "errors" // DiscardZeroes makes sure that all written bytes are zero // before discarding them. @@ -9,7 +9,7 @@ type DiscardZeroes struct{} func (DiscardZeroes) Write(p []byte) (int, error) { for _, b := range p { if b != 0 { - return 0, xerrors.New("encountered non-zero byte") + return 0, errors.New("encountered non-zero byte") } } return len(p), nil diff --git a/vendor/github.com/cilium/ebpf/internal/syscall.go b/vendor/github.com/cilium/ebpf/internal/syscall.go index b32cf3bceb3..efbf40327c6 100644 --- a/vendor/github.com/cilium/ebpf/internal/syscall.go +++ b/vendor/github.com/cilium/ebpf/internal/syscall.go @@ -1,16 +1,61 @@ package internal import ( + "fmt" + "path/filepath" "runtime" "unsafe" "github.com/cilium/ebpf/internal/unix" ) +//go:generate stringer -output syscall_string.go -type=BPFCmd + +// BPFCmd identifies a subcommand of the bpf syscall. +type BPFCmd int + +// Well known BPF commands. +const ( + BPF_MAP_CREATE BPFCmd = iota + BPF_MAP_LOOKUP_ELEM + BPF_MAP_UPDATE_ELEM + BPF_MAP_DELETE_ELEM + BPF_MAP_GET_NEXT_KEY + BPF_PROG_LOAD + BPF_OBJ_PIN + BPF_OBJ_GET + BPF_PROG_ATTACH + BPF_PROG_DETACH + BPF_PROG_TEST_RUN + BPF_PROG_GET_NEXT_ID + BPF_MAP_GET_NEXT_ID + BPF_PROG_GET_FD_BY_ID + BPF_MAP_GET_FD_BY_ID + BPF_OBJ_GET_INFO_BY_FD + BPF_PROG_QUERY + BPF_RAW_TRACEPOINT_OPEN + BPF_BTF_LOAD + BPF_BTF_GET_FD_BY_ID + BPF_TASK_FD_QUERY + BPF_MAP_LOOKUP_AND_DELETE_ELEM + BPF_MAP_FREEZE + BPF_BTF_GET_NEXT_ID + BPF_MAP_LOOKUP_BATCH + BPF_MAP_LOOKUP_AND_DELETE_BATCH + BPF_MAP_UPDATE_BATCH + BPF_MAP_DELETE_BATCH + BPF_LINK_CREATE + BPF_LINK_UPDATE + BPF_LINK_GET_FD_BY_ID + BPF_LINK_GET_NEXT_ID + BPF_ENABLE_STATS + BPF_ITER_CREATE +) + // BPF wraps SYS_BPF. // // Any pointers contained in attr must use the Pointer type from this package. -func BPF(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) { +func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) { r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size) runtime.KeepAlive(attr) @@ -21,3 +66,74 @@ func BPF(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) { return r1, err } + +type BPFProgAttachAttr struct { + TargetFd uint32 + AttachBpfFd uint32 + AttachType uint32 + AttachFlags uint32 + ReplaceBpfFd uint32 +} + +func BPFProgAttach(attr *BPFProgAttachAttr) error { + _, err := BPF(BPF_PROG_ATTACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) + return err +} + +type BPFProgDetachAttr struct { + TargetFd uint32 + AttachBpfFd uint32 + AttachType uint32 +} + +func BPFProgDetach(attr *BPFProgDetachAttr) error { + _, err := BPF(BPF_PROG_DETACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) + return err +} + +type bpfObjAttr struct { + fileName Pointer + fd uint32 + fileFlags uint32 +} + +const bpfFSType = 0xcafe4a11 + +// BPFObjPin wraps BPF_OBJ_PIN. +func BPFObjPin(fileName string, fd *FD) error { + dirName := filepath.Dir(fileName) + var statfs unix.Statfs_t + if err := unix.Statfs(dirName, &statfs); err != nil { + return err + } + if uint64(statfs.Type) != bpfFSType { + return fmt.Errorf("%s is not on a bpf filesystem", fileName) + } + + value, err := fd.Value() + if err != nil { + return err + } + + attr := bpfObjAttr{ + fileName: NewStringPointer(fileName), + fd: value, + } + _, err = BPF(BPF_OBJ_PIN, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + if err != nil { + return fmt.Errorf("pin object %s: %w", fileName, err) + } + return nil +} + +// BPFObjGet wraps BPF_OBJ_GET. +func BPFObjGet(fileName string) (*FD, error) { + attr := bpfObjAttr{ + fileName: NewStringPointer(fileName), + } + ptr, err := BPF(BPF_OBJ_GET, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + if err != nil { + return nil, fmt.Errorf("get object %s: %w", fileName, err) + } + return NewFD(uint32(ptr)), nil +} diff --git a/vendor/github.com/cilium/ebpf/internal/syscall_string.go b/vendor/github.com/cilium/ebpf/internal/syscall_string.go new file mode 100644 index 00000000000..85df0477973 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/syscall_string.go @@ -0,0 +1,56 @@ +// Code generated by "stringer -output syscall_string.go -type=BPFCmd"; DO NOT EDIT. + +package internal + +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_MAP_CREATE-0] + _ = x[BPF_MAP_LOOKUP_ELEM-1] + _ = x[BPF_MAP_UPDATE_ELEM-2] + _ = x[BPF_MAP_DELETE_ELEM-3] + _ = x[BPF_MAP_GET_NEXT_KEY-4] + _ = x[BPF_PROG_LOAD-5] + _ = x[BPF_OBJ_PIN-6] + _ = x[BPF_OBJ_GET-7] + _ = x[BPF_PROG_ATTACH-8] + _ = x[BPF_PROG_DETACH-9] + _ = x[BPF_PROG_TEST_RUN-10] + _ = x[BPF_PROG_GET_NEXT_ID-11] + _ = x[BPF_MAP_GET_NEXT_ID-12] + _ = x[BPF_PROG_GET_FD_BY_ID-13] + _ = x[BPF_MAP_GET_FD_BY_ID-14] + _ = x[BPF_OBJ_GET_INFO_BY_FD-15] + _ = x[BPF_PROG_QUERY-16] + _ = x[BPF_RAW_TRACEPOINT_OPEN-17] + _ = x[BPF_BTF_LOAD-18] + _ = x[BPF_BTF_GET_FD_BY_ID-19] + _ = x[BPF_TASK_FD_QUERY-20] + _ = x[BPF_MAP_LOOKUP_AND_DELETE_ELEM-21] + _ = x[BPF_MAP_FREEZE-22] + _ = x[BPF_BTF_GET_NEXT_ID-23] + _ = x[BPF_MAP_LOOKUP_BATCH-24] + _ = x[BPF_MAP_LOOKUP_AND_DELETE_BATCH-25] + _ = x[BPF_MAP_UPDATE_BATCH-26] + _ = x[BPF_MAP_DELETE_BATCH-27] + _ = x[BPF_LINK_CREATE-28] + _ = x[BPF_LINK_UPDATE-29] + _ = x[BPF_LINK_GET_FD_BY_ID-30] + _ = x[BPF_LINK_GET_NEXT_ID-31] + _ = x[BPF_ENABLE_STATS-32] + _ = x[BPF_ITER_CREATE-33] +} + +const _BPFCmd_name = "BPF_MAP_CREATEBPF_MAP_LOOKUP_ELEMBPF_MAP_UPDATE_ELEMBPF_MAP_DELETE_ELEMBPF_MAP_GET_NEXT_KEYBPF_PROG_LOADBPF_OBJ_PINBPF_OBJ_GETBPF_PROG_ATTACHBPF_PROG_DETACHBPF_PROG_TEST_RUNBPF_PROG_GET_NEXT_IDBPF_MAP_GET_NEXT_IDBPF_PROG_GET_FD_BY_IDBPF_MAP_GET_FD_BY_IDBPF_OBJ_GET_INFO_BY_FDBPF_PROG_QUERYBPF_RAW_TRACEPOINT_OPENBPF_BTF_LOADBPF_BTF_GET_FD_BY_IDBPF_TASK_FD_QUERYBPF_MAP_LOOKUP_AND_DELETE_ELEMBPF_MAP_FREEZEBPF_BTF_GET_NEXT_IDBPF_MAP_LOOKUP_BATCHBPF_MAP_LOOKUP_AND_DELETE_BATCHBPF_MAP_UPDATE_BATCHBPF_MAP_DELETE_BATCHBPF_LINK_CREATEBPF_LINK_UPDATEBPF_LINK_GET_FD_BY_IDBPF_LINK_GET_NEXT_IDBPF_ENABLE_STATSBPF_ITER_CREATE" + +var _BPFCmd_index = [...]uint16{0, 14, 33, 52, 71, 91, 104, 115, 126, 141, 156, 173, 193, 212, 233, 253, 275, 289, 312, 324, 344, 361, 391, 405, 424, 444, 475, 495, 515, 530, 545, 566, 586, 602, 617} + +func (i BPFCmd) String() string { + if i < 0 || i >= BPFCmd(len(_BPFCmd_index)-1) { + return "BPFCmd(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _BPFCmd_name[_BPFCmd_index[i]:_BPFCmd_index[i+1]] +} 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 0545fe94542..9363d0be81c 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go @@ -16,6 +16,7 @@ const ( EINVAL = linux.EINVAL EPOLLIN = linux.EPOLLIN EINTR = linux.EINTR + EPERM = linux.EPERM ESRCH = linux.ESRCH ENODEV = linux.ENODEV BPF_F_RDONLY_PROG = linux.BPF_F_RDONLY_PROG 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 555a5ce358f..2dea950f888 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_other.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_other.go @@ -17,6 +17,7 @@ const ( ENOSPC = syscall.ENOSPC EINVAL = syscall.EINVAL EINTR = syscall.EINTR + EPERM = syscall.EPERM ESRCH = syscall.ESRCH ENODEV = syscall.ENODEV BPF_F_RDONLY_PROG = 0 diff --git a/vendor/github.com/cilium/ebpf/linker.go b/vendor/github.com/cilium/ebpf/linker.go index b9a54daec82..1bb8f61c25a 100644 --- a/vendor/github.com/cilium/ebpf/linker.go +++ b/vendor/github.com/cilium/ebpf/linker.go @@ -1,10 +1,10 @@ package ebpf import ( + "fmt" + "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/internal/btf" - - "golang.org/x/xerrors" ) // link resolves bpf-to-bpf calls. @@ -28,7 +28,7 @@ func link(prog *ProgramSpec, libs []*ProgramSpec) error { needed, err := needSection(insns, lib.Instructions) if err != nil { - return xerrors.Errorf("linking %s: %w", lib.Name, err) + return fmt.Errorf("linking %s: %w", lib.Name, err) } if !needed { @@ -41,7 +41,7 @@ func link(prog *ProgramSpec, libs []*ProgramSpec) error { if prog.BTF != nil && lib.BTF != nil { if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil { - return xerrors.Errorf("linking BTF of %s: %w", lib.Name, err) + return fmt.Errorf("linking BTF of %s: %w", lib.Name, err) } } } diff --git a/vendor/github.com/cilium/ebpf/map.go b/vendor/github.com/cilium/ebpf/map.go index a09e85ed473..461b995a54b 100644 --- a/vendor/github.com/cilium/ebpf/map.go +++ b/vendor/github.com/cilium/ebpf/map.go @@ -1,21 +1,20 @@ package ebpf import ( + "errors" "fmt" "strings" "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/btf" "github.com/cilium/ebpf/internal/unix" - - "golang.org/x/xerrors" ) // Errors returned by Map and MapIterator methods. var ( - ErrKeyNotExist = xerrors.New("key does not exist") - ErrKeyExist = xerrors.New("key already exists") - ErrIterationAborted = xerrors.New("iteration aborted") + ErrKeyNotExist = errors.New("key does not exist") + ErrKeyExist = errors.New("key already exists") + ErrIterationAborted = errors.New("iteration aborted") ) // MapID represents the unique ID of an eBPF map @@ -92,7 +91,7 @@ type Map struct { // You should not use fd after calling this function. func NewMapFromFD(fd int) (*Map, error) { if fd < 0 { - return nil, xerrors.New("invalid fd") + return nil, errors.New("invalid fd") } bpfFd := internal.NewFD(uint32(fd)) @@ -118,8 +117,8 @@ func NewMap(spec *MapSpec) (*Map, error) { } handle, err := btf.NewHandle(btf.MapSpec(spec.BTF)) - if err != nil && !xerrors.Is(err, btf.ErrNotSupported) { - return nil, xerrors.Errorf("can't load BTF: %w", err) + if err != nil && !errors.Is(err, btf.ErrNotSupported) { + return nil, fmt.Errorf("can't load BTF: %w", err) } return newMapWithBTF(spec, handle) @@ -131,7 +130,7 @@ func newMapWithBTF(spec *MapSpec, handle *btf.Handle) (*Map, error) { } if spec.InnerMap == nil { - return nil, xerrors.Errorf("%s requires InnerMap", spec.Type) + return nil, fmt.Errorf("%s requires InnerMap", spec.Type) } template, err := createMap(spec.InnerMap, nil, handle) @@ -155,25 +154,25 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err } if abi.ValueSize != 0 && abi.ValueSize != 4 { - return nil, xerrors.New("ValueSize must be zero or four for map of map") + return nil, errors.New("ValueSize must be zero or four for map of map") } abi.ValueSize = 4 case PerfEventArray: if abi.KeySize != 0 && abi.KeySize != 4 { - return nil, xerrors.New("KeySize must be zero or four for perf event array") + return nil, errors.New("KeySize must be zero or four for perf event array") } abi.KeySize = 4 if abi.ValueSize != 0 && abi.ValueSize != 4 { - return nil, xerrors.New("ValueSize must be zero or four for perf event array") + return nil, errors.New("ValueSize must be zero or four for perf event array") } abi.ValueSize = 4 if abi.MaxEntries == 0 { n, err := internal.PossibleCPUs() if err != nil { - return nil, xerrors.Errorf("perf event array: %w", err) + return nil, fmt.Errorf("perf event array: %w", err) } abi.MaxEntries = uint32(n) } @@ -181,7 +180,7 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err if abi.Flags&(unix.BPF_F_RDONLY_PROG|unix.BPF_F_WRONLY_PROG) > 0 || spec.Freeze { if err := haveMapMutabilityModifiers(); err != nil { - return nil, xerrors.Errorf("map create: %w", err) + return nil, fmt.Errorf("map create: %w", err) } } @@ -197,7 +196,7 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err var err error attr.innerMapFd, err = inner.Value() if err != nil { - return nil, xerrors.Errorf("map create: %w", err) + return nil, fmt.Errorf("map create: %w", err) } } @@ -213,7 +212,7 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err fd, err := bpfMapCreate(&attr) if err != nil { - return nil, xerrors.Errorf("map create: %w", err) + return nil, fmt.Errorf("map create: %w", err) } m, err := newMap(fd, spec.Name, abi) @@ -223,13 +222,13 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err if err := m.populate(spec.Contents); err != nil { m.Close() - return nil, xerrors.Errorf("map create: can't set initial contents: %w", err) + return nil, fmt.Errorf("map create: can't set initial contents: %w", err) } if spec.Freeze { if err := m.Freeze(); err != nil { m.Close() - return nil, xerrors.Errorf("can't freeze map: %w", err) + return nil, fmt.Errorf("can't freeze map: %w", err) } } @@ -301,9 +300,9 @@ func (m *Map) Lookup(key, valueOut interface{}) error { *value = m return nil case *Map: - return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil)) + return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil)) case Map: - return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil)) + return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil)) case **Program: p, err := unmarshalProgram(valueBytes) @@ -315,9 +314,9 @@ func (m *Map) Lookup(key, valueOut interface{}) error { *value = p return nil case *Program: - return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil)) + return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil)) case Program: - return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil)) + return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil)) default: return unmarshalBytes(valueOut, valueBytes) @@ -332,11 +331,11 @@ func (m *Map) LookupAndDelete(key, valueOut interface{}) error { keyPtr, err := marshalPtr(key, int(m.abi.KeySize)) if err != nil { - return xerrors.Errorf("can't marshal key: %w", err) + return fmt.Errorf("can't marshal key: %w", err) } if err := bpfMapLookupAndDelete(m.fd, keyPtr, valuePtr); err != nil { - return xerrors.Errorf("lookup and delete failed: %w", err) + return fmt.Errorf("lookup and delete failed: %w", err) } return unmarshalBytes(valueOut, valueBytes) @@ -350,7 +349,7 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) { valuePtr := internal.NewSlicePointer(valueBytes) err := m.lookup(key, valuePtr) - if xerrors.Is(err, ErrKeyNotExist) { + if errors.Is(err, ErrKeyNotExist) { return nil, nil } @@ -360,11 +359,11 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) { func (m *Map) lookup(key interface{}, valueOut internal.Pointer) error { keyPtr, err := marshalPtr(key, int(m.abi.KeySize)) if err != nil { - return xerrors.Errorf("can't marshal key: %w", err) + return fmt.Errorf("can't marshal key: %w", err) } if err = bpfMapLookupElem(m.fd, keyPtr, valueOut); err != nil { - return xerrors.Errorf("lookup failed: %w", err) + return fmt.Errorf("lookup failed: %w", err) } return nil } @@ -394,7 +393,7 @@ func (m *Map) Put(key, value interface{}) error { func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error { keyPtr, err := marshalPtr(key, int(m.abi.KeySize)) if err != nil { - return xerrors.Errorf("can't marshal key: %w", err) + return fmt.Errorf("can't marshal key: %w", err) } var valuePtr internal.Pointer @@ -404,11 +403,11 @@ func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error { valuePtr, err = marshalPtr(value, int(m.abi.ValueSize)) } if err != nil { - return xerrors.Errorf("can't marshal value: %w", err) + return fmt.Errorf("can't marshal value: %w", err) } if err = bpfMapUpdateElem(m.fd, keyPtr, valuePtr, uint64(flags)); err != nil { - return xerrors.Errorf("update failed: %w", err) + return fmt.Errorf("update failed: %w", err) } return nil @@ -420,11 +419,11 @@ func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error { func (m *Map) Delete(key interface{}) error { keyPtr, err := marshalPtr(key, int(m.abi.KeySize)) if err != nil { - return xerrors.Errorf("can't marshal key: %w", err) + return fmt.Errorf("can't marshal key: %w", err) } if err = bpfMapDeleteElem(m.fd, keyPtr); err != nil { - return xerrors.Errorf("delete failed: %w", err) + return fmt.Errorf("delete failed: %w", err) } return nil } @@ -446,7 +445,7 @@ func (m *Map) NextKey(key, nextKeyOut interface{}) error { } if err := unmarshalBytes(nextKeyOut, nextKeyBytes); err != nil { - return xerrors.Errorf("can't unmarshal next key: %w", err) + return fmt.Errorf("can't unmarshal next key: %w", err) } return nil } @@ -463,7 +462,7 @@ func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) { nextKeyPtr := internal.NewSlicePointer(nextKey) err := m.nextKey(key, nextKeyPtr) - if xerrors.Is(err, ErrKeyNotExist) { + if errors.Is(err, ErrKeyNotExist) { return nil, nil } @@ -479,12 +478,12 @@ func (m *Map) nextKey(key interface{}, nextKeyOut internal.Pointer) error { if key != nil { keyPtr, err = marshalPtr(key, int(m.abi.KeySize)) if err != nil { - return xerrors.Errorf("can't marshal key: %w", err) + return fmt.Errorf("can't marshal key: %w", err) } } if err = bpfMapGetNextKey(m.fd, keyPtr, nextKeyOut); err != nil { - return xerrors.Errorf("next key failed: %w", err) + return fmt.Errorf("next key failed: %w", err) } return nil } @@ -537,7 +536,7 @@ func (m *Map) Clone() (*Map, error) { dup, err := m.fd.Dup() if err != nil { - return nil, xerrors.Errorf("can't clone map: %w", err) + return nil, fmt.Errorf("can't clone map: %w", err) } return newMap(dup, m.name, &m.abi) @@ -547,7 +546,7 @@ func (m *Map) Clone() (*Map, error) { // // This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional func (m *Map) Pin(fileName string) error { - return bpfPinObject(fileName, m.fd) + return internal.BPFObjPin(fileName, m.fd) } // Freeze prevents a map to be modified from user space. @@ -555,11 +554,11 @@ func (m *Map) Pin(fileName string) error { // It makes no changes to kernel-side restrictions. func (m *Map) Freeze() error { if err := haveMapMutabilityModifiers(); err != nil { - return xerrors.Errorf("can't freeze map: %w", err) + return fmt.Errorf("can't freeze map: %w", err) } if err := bpfMapFreeze(m.fd); err != nil { - return xerrors.Errorf("can't freeze map: %w", err) + return fmt.Errorf("can't freeze map: %w", err) } return nil } @@ -567,7 +566,7 @@ func (m *Map) Freeze() error { func (m *Map) populate(contents []MapKV) error { for _, kv := range contents { if err := m.Put(kv.Key, kv.Value); err != nil { - return xerrors.Errorf("key %v: %w", kv.Key, err) + return fmt.Errorf("key %v: %w", kv.Key, err) } } return nil @@ -578,7 +577,7 @@ func (m *Map) populate(contents []MapKV) error { // The function is not compatible with nested maps. // Use LoadPinnedMapExplicit in these situations. func LoadPinnedMap(fileName string) (*Map, error) { - fd, err := bpfGetObject(fileName) + fd, err := internal.BPFObjGet(fileName) if err != nil { return nil, err } @@ -592,7 +591,7 @@ func LoadPinnedMap(fileName string) (*Map, error) { // LoadPinnedMapExplicit loads a map with explicit parameters. func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) { - fd, err := bpfGetObject(fileName) + fd, err := internal.BPFObjGet(fileName) if err != nil { return nil, err } @@ -601,7 +600,7 @@ func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) { func unmarshalMap(buf []byte) (*Map, error) { if len(buf) != 4 { - return nil, xerrors.New("map id requires 4 byte value") + return nil, errors.New("map id requires 4 byte value") } // Looking up an entry in a nested map or prog array returns an id, @@ -626,12 +625,12 @@ func patchValue(value []byte, typ btf.Type, replacements map[string]interface{}) replaced := make(map[string]bool) replace := func(name string, offset, size int, replacement interface{}) error { if offset+size > len(value) { - return xerrors.Errorf("%s: offset %d(+%d) is out of bounds", name, offset, size) + return fmt.Errorf("%s: offset %d(+%d) is out of bounds", name, offset, size) } buf, err := marshalBytes(replacement, size) if err != nil { - return xerrors.Errorf("marshal %s: %w", name, err) + return fmt.Errorf("marshal %s: %w", name, err) } copy(value[offset:offset+size], buf) @@ -655,7 +654,7 @@ func patchValue(value []byte, typ btf.Type, replacements map[string]interface{}) } default: - return xerrors.Errorf("patching %T is not supported", typ) + return fmt.Errorf("patching %T is not supported", typ) } if len(replaced) == len(replacements) { @@ -670,10 +669,10 @@ func patchValue(value []byte, typ btf.Type, replacements map[string]interface{}) } if len(missing) == 1 { - return xerrors.Errorf("unknown field: %s", missing[0]) + return fmt.Errorf("unknown field: %s", missing[0]) } - return xerrors.Errorf("unknown fields: %s", strings.Join(missing, ",")) + return fmt.Errorf("unknown fields: %s", strings.Join(missing, ",")) } // MapIterator iterates a Map. @@ -731,7 +730,7 @@ func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool { mi.prevKey = mi.prevBytes mi.err = mi.target.Lookup(nextBytes, valueOut) - if xerrors.Is(mi.err, ErrKeyNotExist) { + if errors.Is(mi.err, ErrKeyNotExist) { // Even though the key should be valid, we couldn't look up // its value. If we're iterating a hash map this is probably // because a concurrent delete removed the value before we @@ -750,7 +749,7 @@ func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool { return mi.err == nil } - mi.err = xerrors.Errorf("%w", ErrIterationAborted) + mi.err = fmt.Errorf("%w", ErrIterationAborted) return false } @@ -767,7 +766,7 @@ func (mi *MapIterator) Err() error { // // Returns ErrNotExist, if there is no next eBPF map. func MapGetNextID(startID MapID) (MapID, error) { - id, err := objGetNextID(_MapGetNextID, uint32(startID)) + id, err := objGetNextID(internal.BPF_MAP_GET_NEXT_ID, uint32(startID)) return MapID(id), err } @@ -775,7 +774,7 @@ func MapGetNextID(startID MapID) (MapID, error) { // // Returns ErrNotExist, if there is no eBPF map with the given id. func NewMapFromID(id MapID) (*Map, error) { - fd, err := bpfObjGetFDByID(_MapGetFDByID, uint32(id)) + fd, err := bpfObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id)) if err != nil { return nil, err } diff --git a/vendor/github.com/cilium/ebpf/marshalers.go b/vendor/github.com/cilium/ebpf/marshalers.go index 89fdc86028c..c0db2f6b0b1 100644 --- a/vendor/github.com/cilium/ebpf/marshalers.go +++ b/vendor/github.com/cilium/ebpf/marshalers.go @@ -4,13 +4,13 @@ import ( "bytes" "encoding" "encoding/binary" + "errors" + "fmt" "reflect" "runtime" "unsafe" "github.com/cilium/ebpf/internal" - - "golang.org/x/xerrors" ) func marshalPtr(data interface{}, length int) (internal.Pointer, error) { @@ -18,7 +18,7 @@ func marshalPtr(data interface{}, length int) (internal.Pointer, error) { if length == 0 { return internal.NewPointer(nil), nil } - return internal.Pointer{}, xerrors.New("can't use nil as key of map") + return internal.Pointer{}, errors.New("can't use nil as key of map") } if ptr, ok := data.(unsafe.Pointer); ok { @@ -42,12 +42,12 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) { case []byte: buf = value case unsafe.Pointer: - err = xerrors.New("can't marshal from unsafe.Pointer") + err = errors.New("can't marshal from unsafe.Pointer") default: var wr bytes.Buffer err = binary.Write(&wr, internal.NativeEndian, value) if err != nil { - err = xerrors.Errorf("encoding %T: %v", value, err) + err = fmt.Errorf("encoding %T: %v", value, err) } buf = wr.Bytes() } @@ -56,7 +56,7 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) { } if len(buf) != length { - return nil, xerrors.Errorf("%T doesn't marshal to %d bytes", data, length) + return nil, fmt.Errorf("%T doesn't marshal to %d bytes", data, length) } return buf, nil } @@ -92,13 +92,13 @@ func unmarshalBytes(data interface{}, buf []byte) error { *value = buf return nil case string: - return xerrors.New("require pointer to string") + return errors.New("require pointer to string") case []byte: - return xerrors.New("require pointer to []byte") + return errors.New("require pointer to []byte") default: rd := bytes.NewReader(buf) if err := binary.Read(rd, internal.NativeEndian, value); err != nil { - return xerrors.Errorf("decoding %T: %v", value, err) + return fmt.Errorf("decoding %T: %v", value, err) } return nil } @@ -113,7 +113,7 @@ func unmarshalBytes(data interface{}, buf []byte) error { func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, error) { sliceType := reflect.TypeOf(slice) if sliceType.Kind() != reflect.Slice { - return internal.Pointer{}, xerrors.New("per-CPU value requires slice") + return internal.Pointer{}, errors.New("per-CPU value requires slice") } possibleCPUs, err := internal.PossibleCPUs() @@ -124,7 +124,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er sliceValue := reflect.ValueOf(slice) sliceLen := sliceValue.Len() if sliceLen > possibleCPUs { - return internal.Pointer{}, xerrors.Errorf("per-CPU value exceeds number of CPUs") + return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs") } alignedElemLength := align(elemLength, 8) @@ -151,7 +151,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) error { slicePtrType := reflect.TypeOf(slicePtr) if slicePtrType.Kind() != reflect.Ptr || slicePtrType.Elem().Kind() != reflect.Slice { - return xerrors.Errorf("per-cpu value requires pointer to slice") + return fmt.Errorf("per-cpu value requires pointer to slice") } possibleCPUs, err := internal.PossibleCPUs() @@ -170,7 +170,7 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro step := len(buf) / possibleCPUs if step < elemLength { - return xerrors.Errorf("per-cpu element length is larger than available data") + return fmt.Errorf("per-cpu element length is larger than available data") } for i := 0; i < possibleCPUs; i++ { var elem interface{} @@ -188,7 +188,7 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro err := unmarshalBytes(elem, elemBytes) if err != nil { - return xerrors.Errorf("cpu %d: %w", i, err) + return fmt.Errorf("cpu %d: %w", i, err) } buf = buf[step:] diff --git a/vendor/github.com/cilium/ebpf/prog.go b/vendor/github.com/cilium/ebpf/prog.go index ed31ac5d958..429203f07e8 100644 --- a/vendor/github.com/cilium/ebpf/prog.go +++ b/vendor/github.com/cilium/ebpf/prog.go @@ -3,18 +3,16 @@ package ebpf import ( "bytes" "encoding/binary" + "errors" "fmt" "math" "strings" "time" - "unsafe" "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/btf" "github.com/cilium/ebpf/internal/unix" - - "golang.org/x/xerrors" ) // ErrNotSupported is returned whenever the kernel doesn't support a feature. @@ -48,11 +46,24 @@ type ProgramOptions struct { type ProgramSpec struct { // Name is passed to the kernel as a debug aid. Must only contain // alpha numeric and '_' characters. - Name string - Type ProgramType - AttachType AttachType - Instructions asm.Instructions - License string + Name string + // Type determines at which hook in the kernel a program will run. + Type ProgramType + AttachType AttachType + // Name of a kernel data structure to attach to. It's interpretation + // depends on Type and AttachType. + AttachTo string + Instructions asm.Instructions + + // License of the program. Some helpers are only available if + // the license is deemed compatible with the GPL. + // + // See https://www.kernel.org/doc/html/latest/process/license-rules.html#id1 + License string + + // Version used by tracing programs. + // + // Deprecated: superseded by BTF. KernelVersion uint32 // The BTF associated with this program. Changing Instructions @@ -84,9 +95,10 @@ type Program struct { // otherwise it is empty. VerifierLog string - fd *internal.FD - name string - abi ProgramABI + fd *internal.FD + name string + abi ProgramABI + attachType AttachType } // NewProgram creates a new Program. @@ -107,8 +119,8 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er } handle, err := btf.NewHandle(btf.ProgramSpec(spec.BTF)) - if err != nil && !xerrors.Is(err, btf.ErrNotSupported) { - return nil, xerrors.Errorf("can't load BTF: %w", err) + if err != nil && !errors.Is(err, btf.ErrNotSupported) { + return nil, fmt.Errorf("can't load BTF: %w", err) } return newProgramWithBTF(spec, handle, opts) @@ -152,7 +164,7 @@ func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions) } err = internal.ErrorWithLog(err, logBuf, logErr) - return nil, xerrors.Errorf("can't load program: %w", err) + return nil, fmt.Errorf("can't load program: %w", err) } // NewProgramFromFD creates a program from a raw fd. @@ -162,7 +174,7 @@ func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions) // Requires at least Linux 4.11. func NewProgramFromFD(fd int) (*Program, error) { if fd < 0 { - return nil, xerrors.New("invalid fd") + return nil, errors.New("invalid fd") } bpfFd := internal.NewFD(uint32(fd)) @@ -185,15 +197,15 @@ func newProgram(fd *internal.FD, name string, abi *ProgramABI) *Program { func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr, error) { if len(spec.Instructions) == 0 { - return nil, xerrors.New("Instructions cannot be empty") + return nil, errors.New("Instructions cannot be empty") } if len(spec.License) == 0 { - return nil, xerrors.New("License cannot be empty") + return nil, errors.New("License cannot be empty") } if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian { - return nil, xerrors.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian) + return nil, fmt.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian) } buf := bytes.NewBuffer(make([]byte, 0, len(spec.Instructions)*asm.InstructionSize)) @@ -222,7 +234,7 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr recSize, bytes, err := btf.ProgramLineInfos(spec.BTF) if err != nil { - return nil, xerrors.Errorf("can't get BTF line infos: %w", err) + return nil, fmt.Errorf("can't get BTF line infos: %w", err) } attr.lineInfoRecSize = recSize attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize)) @@ -230,13 +242,23 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF) if err != nil { - return nil, xerrors.Errorf("can't get BTF function infos: %w", err) + return nil, fmt.Errorf("can't get BTF function infos: %w", err) } attr.funcInfoRecSize = recSize attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize)) attr.funcInfo = internal.NewSlicePointer(bytes) } + if spec.AttachTo != "" { + target, err := resolveBTFType(spec.AttachTo, spec.Type, spec.AttachType) + if err != nil { + return nil, err + } + if target != nil { + attr.attachBTFID = target.ID() + } + } + return attr, nil } @@ -278,7 +300,7 @@ func (p *Program) Clone() (*Program, error) { dup, err := p.fd.Dup() if err != nil { - return nil, xerrors.Errorf("can't clone program: %w", err) + return nil, fmt.Errorf("can't clone program: %w", err) } return newProgram(dup, p.name, &p.abi), nil @@ -288,8 +310,8 @@ func (p *Program) Clone() (*Program, error) { // // This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional func (p *Program) Pin(fileName string) error { - if err := bpfPinObject(fileName, p.fd); err != nil { - return xerrors.Errorf("can't pin program: %w", err) + if err := internal.BPFObjPin(fileName, p.fd); err != nil { + return fmt.Errorf("can't pin program: %w", err) } return nil } @@ -313,7 +335,7 @@ func (p *Program) Close() error { func (p *Program) Test(in []byte) (uint32, []byte, error) { ret, out, _, err := p.testRun(in, 1, nil) if err != nil { - return ret, nil, xerrors.Errorf("can't test program: %w", err) + return ret, nil, fmt.Errorf("can't test program: %w", err) } return ret, out, nil } @@ -332,12 +354,12 @@ func (p *Program) Test(in []byte) (uint32, []byte, error) { func (p *Program) Benchmark(in []byte, repeat int, reset func()) (uint32, time.Duration, error) { ret, _, total, err := p.testRun(in, repeat, reset) if err != nil { - return ret, total, xerrors.Errorf("can't benchmark program: %w", err) + return ret, total, fmt.Errorf("can't benchmark program: %w", err) } return ret, total, nil } -var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() bool { +var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() (bool, error) { prog, err := NewProgram(&ProgramSpec{ Type: SocketFilter, Instructions: asm.Instructions{ @@ -348,28 +370,23 @@ var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() b }) if err != nil { // This may be because we lack sufficient permissions, etc. - return false + return false, err } defer prog.Close() - fd, err := prog.fd.Value() - if err != nil { - return false - } - // Programs require at least 14 bytes input in := make([]byte, 14) attr := bpfProgTestRunAttr{ - fd: fd, + fd: uint32(prog.FD()), dataSizeIn: uint32(len(in)), dataIn: internal.NewSlicePointer(in), } - _, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + err = bpfProgTestRun(&attr) // Check for EINVAL specifically, rather than err != nil since we // otherwise misdetect due to insufficient permissions. - return !xerrors.Is(err, unix.EINVAL) + return !errors.Is(err, unix.EINVAL), nil }) func (p *Program) testRun(in []byte, repeat int, reset func()) (uint32, []byte, time.Duration, error) { @@ -411,19 +428,19 @@ func (p *Program) testRun(in []byte, repeat int, reset func()) (uint32, []byte, } for { - _, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + err = bpfProgTestRun(&attr) if err == nil { break } - if xerrors.Is(err, unix.EINTR) { + if errors.Is(err, unix.EINTR) { if reset != nil { reset() } continue } - return 0, nil, 0, xerrors.Errorf("can't run test: %w", err) + return 0, nil, 0, fmt.Errorf("can't run test: %w", err) } if int(attr.dataSizeOut) > cap(out) { @@ -439,7 +456,7 @@ func (p *Program) testRun(in []byte, repeat int, reset func()) (uint32, []byte, func unmarshalProgram(buf []byte) (*Program, error) { if len(buf) != 4 { - return nil, xerrors.New("program id requires 4 byte value") + return nil, errors.New("program id requires 4 byte value") } // Looking up an entry in a nested map or prog array returns an id, @@ -460,10 +477,12 @@ func (p *Program) MarshalBinary() ([]byte, error) { return buf, nil } -// Attach a Program to a container object fd +// Attach a Program. +// +// Deprecated: use link.RawAttachProgram instead. func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error { if fd < 0 { - return xerrors.New("invalid fd") + return errors.New("invalid fd") } pfd, err := p.fd.Value() @@ -471,20 +490,26 @@ func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error { return err } - attr := bpfProgAlterAttr{ - targetFd: uint32(fd), - attachBpfFd: pfd, - attachType: uint32(typ), - attachFlags: uint32(flags), + attr := internal.BPFProgAttachAttr{ + TargetFd: uint32(fd), + AttachBpfFd: pfd, + AttachType: uint32(typ), + AttachFlags: uint32(flags), } - return bpfProgAlter(_ProgAttach, &attr) + return internal.BPFProgAttach(&attr) } -// Detach a Program from a container object fd +// Detach a Program. +// +// Deprecated: use link.RawDetachProgram instead. func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error { if fd < 0 { - return xerrors.New("invalid fd") + return errors.New("invalid fd") + } + + if flags != 0 { + return errors.New("flags must be zero") } pfd, err := p.fd.Value() @@ -492,21 +517,20 @@ func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error { return err } - attr := bpfProgAlterAttr{ - targetFd: uint32(fd), - attachBpfFd: pfd, - attachType: uint32(typ), - attachFlags: uint32(flags), + attr := internal.BPFProgDetachAttr{ + TargetFd: uint32(fd), + AttachBpfFd: pfd, + AttachType: uint32(typ), } - return bpfProgAlter(_ProgDetach, &attr) + return internal.BPFProgDetach(&attr) } // LoadPinnedProgram loads a Program from a BPF file. // // Requires at least Linux 4.11. func LoadPinnedProgram(fileName string) (*Program, error) { - fd, err := bpfGetObject(fileName) + fd, err := internal.BPFObjGet(fileName) if err != nil { return nil, err } @@ -514,7 +538,7 @@ func LoadPinnedProgram(fileName string) (*Program, error) { name, abi, err := newProgramABIFromFd(fd) if err != nil { _ = fd.Close() - return nil, xerrors.Errorf("can't get ABI for %s: %w", fileName, err) + return nil, fmt.Errorf("can't get ABI for %s: %w", fileName, err) } return newProgram(fd, name, abi), nil @@ -540,7 +564,7 @@ func SanitizeName(name string, replacement rune) string { // // Returns ErrNotExist, if there is no next eBPF program. func ProgramGetNextID(startID ProgramID) (ProgramID, error) { - id, err := objGetNextID(_ProgGetNextID, uint32(startID)) + id, err := objGetNextID(internal.BPF_PROG_GET_NEXT_ID, uint32(startID)) return ProgramID(id), err } @@ -548,7 +572,7 @@ func ProgramGetNextID(startID ProgramID) (ProgramID, error) { // // Returns ErrNotExist, if there is no eBPF program with the given id. func NewProgramFromID(id ProgramID) (*Program, error) { - fd, err := bpfObjGetFDByID(_ProgGetFDByID, uint32(id)) + fd, err := bpfObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id)) if err != nil { return nil, err } @@ -570,3 +594,29 @@ func (p *Program) ID() (ProgramID, error) { } return ProgramID(info.id), nil } + +func resolveBTFType(name string, progType ProgramType, attachType AttachType) (btf.Type, error) { + kernel, err := btf.LoadKernelSpec() + if err != nil { + return nil, fmt.Errorf("can't resolve BTF type %s: %w", name, err) + } + + type match struct { + p ProgramType + a AttachType + } + + target := match{progType, attachType} + switch target { + case match{Tracing, AttachTraceIter}: + var target btf.Func + if err := kernel.FindType("bpf_iter_"+name, &target); err != nil { + return nil, fmt.Errorf("can't resolve BTF for iterator %s: %w", name, err) + } + + return &target, nil + + default: + return nil, nil + } +} diff --git a/vendor/github.com/cilium/ebpf/run-tests.sh b/vendor/github.com/cilium/ebpf/run-tests.sh index e60c35e2531..c43a90ddd0d 100644 --- a/vendor/github.com/cilium/ebpf/run-tests.sh +++ b/vendor/github.com/cilium/ebpf/run-tests.sh @@ -15,8 +15,13 @@ if [[ "${1:-}" = "--in-vm" ]]; then export GOPROXY=file:///run/go-root/pkg/mod/cache/download export GOCACHE=/run/go-cache + elfs="" + if [[ -d "/run/input/bpf" ]]; then + elfs="/run/input/bpf" + fi + echo Running tests... - /usr/local/bin/go test -coverprofile="$1/coverage.txt" -covermode=atomic -v ./... + /usr/local/bin/go test -coverprofile="$1/coverage.txt" -covermode=atomic -v -elfs "$elfs" ./... touch "$1/success" exit 0 fi @@ -39,20 +44,34 @@ if [[ -z "${kernel_version}" ]]; then fi readonly kernel="linux-${kernel_version}.bz" +readonly selftests="linux-${kernel_version}-selftests-bpf.bz" +readonly input="$(mktemp -d)" readonly output="$(mktemp -d)" -readonly tmp_dir="${TMPDIR:-$(mktemp -d)}" +readonly tmp_dir="${TMPDIR:-/tmp}" +readonly branch="${BRANCH:-master}" -test -e "${tmp_dir}/${kernel}" || { - echo Fetching "${kernel}" - curl --fail -L "https://github.com/cilium/ci-kernels/blob/master/${kernel}?raw=true" -o "${tmp_dir}/${kernel}" +fetch() { + echo Fetching "${1}" + wget -nv -N -P "${tmp_dir}" "https://github.com/cilium/ci-kernels/raw/${branch}/${1}" } +fetch "${kernel}" + +if fetch "${selftests}"; then + mkdir "${input}/bpf" + tar --strip-components=4 -xjf "${tmp_dir}/${selftests}" -C "${input}/bpf" +else + echo "No selftests found, disabling" +fi + echo Testing on "${kernel_version}" $sudo virtme-run --kimg "${tmp_dir}/${kernel}" --memory 512M --pwd \ + --rwdir=/run/input="${input}" \ --rwdir=/run/output="${output}" \ --rodir=/run/go-path="$(go env GOPATH)" \ --rwdir=/run/go-cache="$(go env GOCACHE)" \ - --script-sh "$(realpath "$0") --in-vm /run/output" + --script-sh "$(realpath "$0") --in-vm /run/output" \ + --qemu-opts -smp 2 # need at least two CPUs for some tests if [[ ! -e "${output}/success" ]]; then echo "Test failed on ${kernel_version}" @@ -66,4 +85,5 @@ else fi fi +$sudo rm -r "${input}" $sudo rm -r "${output}" diff --git a/vendor/github.com/cilium/ebpf/syscalls.go b/vendor/github.com/cilium/ebpf/syscalls.go index 7d29344cb1a..2b713d06a0c 100644 --- a/vendor/github.com/cilium/ebpf/syscalls.go +++ b/vendor/github.com/cilium/ebpf/syscalls.go @@ -1,20 +1,19 @@ package ebpf import ( + "errors" + "fmt" "os" - "path/filepath" "unsafe" "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/btf" "github.com/cilium/ebpf/internal/unix" - - "golang.org/x/xerrors" ) // Generic errors returned by BPF syscalls. var ( - ErrNotExist = xerrors.New("requested object does not exist") + ErrNotExist = errors.New("requested object does not exist") ) // bpfObjName is a null-terminated string made up of @@ -80,12 +79,6 @@ type bpfMapInfo struct { mapName bpfObjName // since 4.15 ad5b177bd73f } -type bpfPinObjAttr struct { - fileName internal.Pointer - fd uint32 - padding uint32 -} - type bpfProgLoadAttr struct { progType ProgramType insCount uint32 @@ -106,6 +99,8 @@ type bpfProgLoadAttr struct { lineInfoRecSize uint32 lineInfo internal.Pointer lineInfoCnt uint32 + attachBTFID btf.TypeID + attachProgFd uint32 } type bpfProgInfo struct { @@ -134,13 +129,6 @@ type bpfProgTestRunAttr struct { duration uint32 } -type bpfProgAlterAttr struct { - targetFd uint32 - attachBpfFd uint32 - attachType uint32 - attachFlags uint32 -} - type bpfObjGetInfoByFDAttr struct { fd uint32 infoLen uint32 @@ -164,7 +152,7 @@ type bpfObjGetNextIDAttr struct { func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) { for { - fd, err := internal.BPF(_ProgLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) + fd, err := internal.BPF(internal.BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) // As of ~4.20 the verifier can be interrupted by a signal, // and returns EAGAIN in that case. if err == unix.EAGAIN { @@ -179,15 +167,15 @@ func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) { } } -func bpfProgAlter(cmd int, attr *bpfProgAlterAttr) error { - _, err := internal.BPF(cmd, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) +func bpfProgTestRun(attr *bpfProgTestRunAttr) error { + _, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) return err } func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) { - fd, err := internal.BPF(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) - if xerrors.Is(err, os.ErrPermission) { - return nil, xerrors.New("permission denied or insufficient rlimit to lock memory for map") + fd, err := internal.BPF(internal.BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) + if errors.Is(err, os.ErrPermission) { + return nil, errors.New("permission denied or insufficient rlimit to lock memory for map") } if err != nil { @@ -197,7 +185,7 @@ func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) { return internal.NewFD(uint32(fd)), nil } -var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool { +var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() (bool, error) { inner, err := bpfMapCreate(&bpfMapCreateAttr{ mapType: Array, keySize: 4, @@ -205,7 +193,7 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool { maxEntries: 1, }) if err != nil { - return false + return false, err } defer inner.Close() @@ -218,14 +206,14 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool { innerMapFd: innerFd, }) if err != nil { - return false + return false, nil } _ = nested.Close() - return true + return true, nil }) -var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() bool { +var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() (bool, 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 := bpfMapCreate(&bpfMapCreateAttr{ @@ -236,10 +224,10 @@ var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps flags: unix.BPF_F_RDONLY_PROG, }) if err != nil { - return false + return false, nil } _ = m.Close() - return true + return true, nil }) func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error { @@ -253,7 +241,7 @@ func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error { key: key, value: valueOut, } - _, err = internal.BPF(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = internal.BPF(internal.BPF_MAP_LOOKUP_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return wrapMapError(err) } @@ -268,7 +256,7 @@ func bpfMapLookupAndDelete(m *internal.FD, key, valueOut internal.Pointer) error key: key, value: valueOut, } - _, err = internal.BPF(_MapLookupAndDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = internal.BPF(internal.BPF_MAP_LOOKUP_AND_DELETE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return wrapMapError(err) } @@ -284,7 +272,7 @@ func bpfMapUpdateElem(m *internal.FD, key, valueOut internal.Pointer, flags uint value: valueOut, flags: flags, } - _, err = internal.BPF(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = internal.BPF(internal.BPF_MAP_UPDATE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return wrapMapError(err) } @@ -298,7 +286,7 @@ func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error { mapFd: fd, key: key, } - _, err = internal.BPF(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = internal.BPF(internal.BPF_MAP_DELETE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return wrapMapError(err) } @@ -313,11 +301,11 @@ func bpfMapGetNextKey(m *internal.FD, key, nextKeyOut internal.Pointer) error { key: key, value: nextKeyOut, } - _, err = internal.BPF(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = internal.BPF(internal.BPF_MAP_GET_NEXT_KEY, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return wrapMapError(err) } -func objGetNextID(cmd int, start uint32) (uint32, error) { +func objGetNextID(cmd internal.BPFCmd, start uint32) (uint32, error) { attr := bpfObjGetNextIDAttr{ startID: start, } @@ -329,11 +317,11 @@ func wrapObjError(err error) error { if err == nil { return nil } - if xerrors.Is(err, unix.ENOENT) { - return xerrors.Errorf("%w", ErrNotExist) + if errors.Is(err, unix.ENOENT) { + return fmt.Errorf("%w", ErrNotExist) } - return xerrors.New(err.Error()) + return errors.New(err.Error()) } func wrapMapError(err error) error { @@ -341,15 +329,15 @@ func wrapMapError(err error) error { return nil } - if xerrors.Is(err, unix.ENOENT) { + if errors.Is(err, unix.ENOENT) { return ErrKeyNotExist } - if xerrors.Is(err, unix.EEXIST) { + if errors.Is(err, unix.EEXIST) { return ErrKeyExist } - return xerrors.New(err.Error()) + return errors.New(err.Error()) } func bpfMapFreeze(m *internal.FD) error { @@ -361,47 +349,10 @@ func bpfMapFreeze(m *internal.FD) error { attr := bpfMapFreezeAttr{ mapFd: fd, } - _, err = internal.BPF(_MapFreeze, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = internal.BPF(internal.BPF_MAP_FREEZE, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return err } -const bpfFSType = 0xcafe4a11 - -func bpfPinObject(fileName string, fd *internal.FD) error { - dirName := filepath.Dir(fileName) - var statfs unix.Statfs_t - if err := unix.Statfs(dirName, &statfs); err != nil { - return err - } - if uint64(statfs.Type) != bpfFSType { - return xerrors.Errorf("%s is not on a bpf filesystem", fileName) - } - - value, err := fd.Value() - if err != nil { - return err - } - - _, err = internal.BPF(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{ - fileName: internal.NewStringPointer(fileName), - fd: value, - }), 16) - if err != nil { - return xerrors.Errorf("pin object %s: %w", fileName, err) - } - return nil -} - -func bpfGetObject(fileName string) (*internal.FD, error) { - ptr, err := internal.BPF(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{ - fileName: internal.NewStringPointer(fileName), - }), 16) - if err != nil { - return nil, xerrors.Errorf("get object %s: %w", fileName, err) - } - return internal.NewFD(uint32(ptr)), nil -} - func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) error { value, err := fd.Value() if err != nil { @@ -414,9 +365,9 @@ func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) er infoLen: uint32(size), info: internal.NewPointer(info), } - _, err = internal.BPF(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = internal.BPF(internal.BPF_OBJ_GET_INFO_BY_FD, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) if err != nil { - return xerrors.Errorf("fd %d: %w", fd, err) + return fmt.Errorf("fd %d: %w", fd, err) } return nil } @@ -424,7 +375,7 @@ func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) er func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) { var info bpfProgInfo if err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil { - return nil, xerrors.Errorf("can't get program info: %w", err) + return nil, fmt.Errorf("can't get program info: %w", err) } return &info, nil } @@ -433,12 +384,12 @@ func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) { var info bpfMapInfo err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)) if err != nil { - return nil, xerrors.Errorf("can't get map info: %w", err) + return nil, fmt.Errorf("can't get map info: %w", err) } return &info, nil } -var haveObjName = internal.FeatureTest("object names", "4.15", func() bool { +var haveObjName = internal.FeatureTest("object names", "4.15", func() (bool, error) { attr := bpfMapCreateAttr{ mapType: Array, keySize: 4, @@ -449,16 +400,16 @@ var haveObjName = internal.FeatureTest("object names", "4.15", func() bool { fd, err := bpfMapCreate(&attr) if err != nil { - return false + return false, nil } _ = fd.Close() - return true + return true, nil }) -var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func() bool { +var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func() (bool, error) { if err := haveObjName(); err != nil { - return false + return false, err } attr := bpfMapCreateAttr{ @@ -471,14 +422,14 @@ var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func() fd, err := bpfMapCreate(&attr) if err != nil { - return false + return false, nil } _ = fd.Close() - return true + return true, nil }) -func bpfObjGetFDByID(cmd int, id uint32) (*internal.FD, error) { +func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) { attr := bpfGetFDByIDAttr{ id: id, } diff --git a/vendor/github.com/cilium/ebpf/types.go b/vendor/github.com/cilium/ebpf/types.go index 94cdb30814b..1ffc62123be 100644 --- a/vendor/github.com/cilium/ebpf/types.go +++ b/vendor/github.com/cilium/ebpf/types.go @@ -1,6 +1,6 @@ package ebpf -//go:generate stringer -output types_string.go -type=MapType,ProgramType +//go:generate stringer -output types_string.go -type=MapType,ProgramType,AttachType // MapType indicates the type map structure // that will be initialized in the kernel. @@ -85,39 +85,12 @@ const ( // hasPerCPUValue returns true if the Map stores a value per CPU. func (mt MapType) hasPerCPUValue() bool { - if mt == PerCPUHash || mt == PerCPUArray { + if mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash { return true } return false } -const ( - _MapCreate = iota - _MapLookupElem - _MapUpdateElem - _MapDeleteElem - _MapGetNextKey - _ProgLoad - _ObjPin - _ObjGet - _ProgAttach - _ProgDetach - _ProgTestRun - _ProgGetNextID - _MapGetNextID - _ProgGetFDByID - _MapGetFDByID - _ObjGetInfoByFD - _ProgQuery - _RawTracepointOpen - _BTFLoad - _BTFGetFDByID - _TaskFDQuery - _MapLookupAndDeleteElem - _MapFreeze - _BTFGetNextID -) - // ProgramType of the eBPF program type ProgramType uint32 @@ -214,6 +187,9 @@ const ( AttachTraceRawTp AttachTraceFEntry AttachTraceFExit + AttachModifyReturn + AttachLSMMac + AttachTraceIter ) // AttachFlags of the eBPF program used in BPF_PROG_ATTACH command diff --git a/vendor/github.com/cilium/ebpf/types_string.go b/vendor/github.com/cilium/ebpf/types_string.go index f41ba77df90..c7139578ec6 100644 --- a/vendor/github.com/cilium/ebpf/types_string.go +++ b/vendor/github.com/cilium/ebpf/types_string.go @@ -1,4 +1,4 @@ -// Code generated by "stringer -output types_string.go -type=MapType,ProgramType"; DO NOT EDIT. +// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,AttachType"; DO NOT EDIT. package ebpf @@ -89,3 +89,49 @@ func (i ProgramType) String() string { } return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]] } +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[AttachNone-0] + _ = x[AttachCGroupInetIngress-0] + _ = x[AttachCGroupInetEgress-1] + _ = x[AttachCGroupInetSockCreate-2] + _ = x[AttachCGroupSockOps-3] + _ = x[AttachSkSKBStreamParser-4] + _ = x[AttachSkSKBStreamVerdict-5] + _ = x[AttachCGroupDevice-6] + _ = x[AttachSkMsgVerdict-7] + _ = x[AttachCGroupInet4Bind-8] + _ = x[AttachCGroupInet6Bind-9] + _ = x[AttachCGroupInet4Connect-10] + _ = x[AttachCGroupInet6Connect-11] + _ = x[AttachCGroupInet4PostBind-12] + _ = x[AttachCGroupInet6PostBind-13] + _ = x[AttachCGroupUDP4Sendmsg-14] + _ = x[AttachCGroupUDP6Sendmsg-15] + _ = x[AttachLircMode2-16] + _ = x[AttachFlowDissector-17] + _ = x[AttachCGroupSysctl-18] + _ = x[AttachCGroupUDP4Recvmsg-19] + _ = x[AttachCGroupUDP6Recvmsg-20] + _ = x[AttachCGroupGetsockopt-21] + _ = x[AttachCGroupSetsockopt-22] + _ = x[AttachTraceRawTp-23] + _ = x[AttachTraceFEntry-24] + _ = x[AttachTraceFExit-25] + _ = x[AttachModifyReturn-26] + _ = x[AttachLSMMac-27] + _ = x[AttachTraceIter-28] +} + +const _AttachType_name = "AttachNoneAttachCGroupInetEgressAttachCGroupInetSockCreateAttachCGroupSockOpsAttachSkSKBStreamParserAttachSkSKBStreamVerdictAttachCGroupDeviceAttachSkMsgVerdictAttachCGroupInet4BindAttachCGroupInet6BindAttachCGroupInet4ConnectAttachCGroupInet6ConnectAttachCGroupInet4PostBindAttachCGroupInet6PostBindAttachCGroupUDP4SendmsgAttachCGroupUDP6SendmsgAttachLircMode2AttachFlowDissectorAttachCGroupSysctlAttachCGroupUDP4RecvmsgAttachCGroupUDP6RecvmsgAttachCGroupGetsockoptAttachCGroupSetsockoptAttachTraceRawTpAttachTraceFEntryAttachTraceFExitAttachModifyReturnAttachLSMMacAttachTraceIter" + +var _AttachType_index = [...]uint16{0, 10, 32, 58, 77, 100, 124, 142, 160, 181, 202, 226, 250, 275, 300, 323, 346, 361, 380, 398, 421, 444, 466, 488, 504, 521, 537, 555, 567, 582} + +func (i AttachType) String() string { + if i >= AttachType(len(_AttachType_index)-1) { + return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]] +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go index a70619cbb34..6a8f1d35485 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go @@ -23,6 +23,9 @@ func (s *DevicesGroup) Name() string { } func (s *DevicesGroup) Apply(d *cgroupData) error { + if d.config.SkipDevices { + return nil + } _, err := d.join("devices") if err != nil { // We will return error even it's `not found` error, devices @@ -52,7 +55,7 @@ func buildEmulator(rules []*configs.DeviceRule) (*devices.Emulator, error) { } func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error { - if system.RunningInUserNS() { + if system.RunningInUserNS() || cgroup.SkipDevices { return nil } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go index 245ce84f4c4..b9f298b41ed 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go @@ -204,7 +204,7 @@ func (m *manager) Apply(pid int) (err error) { if err != nil { // The non-presence of the devices subsystem is // considered fatal for security reasons. - if cgroups.IsNotFound(err) && sys.Name() != "devices" { + if cgroups.IsNotFound(err) && (c.SkipDevices || sys.Name() != "devices") { continue } return err @@ -298,7 +298,7 @@ func (m *manager) Set(container *configs.Config) error { // Freeze toggles the container's freezer cgroup depending on the state // provided -func (m *manager) Freeze(state configs.FreezerState) (Err error) { +func (m *manager) Freeze(state configs.FreezerState) error { path := m.Path("freezer") if m.cgroups == nil || path == "" { return errors.New("cannot toggle freezer: cgroups not configured for container") @@ -306,17 +306,9 @@ func (m *manager) Freeze(state configs.FreezerState) (Err error) { prevState := m.cgroups.Resources.Freezer m.cgroups.Resources.Freezer = state - defer func() { - if Err != nil { - m.cgroups.Resources.Freezer = prevState - } - }() - - freezer, err := m.getSubsystems().Get("freezer") - if err != nil { - return err - } + freezer := &FreezerGroup{} if err := freezer.Set(path, m.cgroups); err != nil { + m.cgroups.Resources.Freezer = prevState return err } return nil @@ -359,14 +351,14 @@ func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) { } func (raw *cgroupData) path(subsystem string) (string, error) { - mnt, err := cgroups.FindCgroupMountpoint(raw.root, subsystem) - // If we didn't mount the subsystem, there is no point we make the path. - if err != nil { - return "", err - } - // If the cgroup name/path is absolute do not look relative to the cgroup of the init process. if filepath.IsAbs(raw.innerPath) { + mnt, err := cgroups.FindCgroupMountpoint(raw.root, subsystem) + // If we didn't mount the subsystem, there is no point we make the path. + if err != nil { + return "", err + } + // Sometimes subsystems can be mounted together as 'cpu,cpuacct'. return filepath.Join(raw.root, filepath.Base(mnt), raw.innerPath), nil } @@ -418,13 +410,12 @@ func (m *manager) GetCgroups() (*configs.Cgroup, error) { func (m *manager) GetFreezerState() (configs.FreezerState, error) { dir := m.Path("freezer") - freezer, err := m.getSubsystems().Get("freezer") - // If the container doesn't have the freezer cgroup, say it's undefined. - if err != nil || dir == "" { + if dir == "" { return configs.Undefined, nil } - return freezer.(*FreezerGroup).GetState(dir) + freezer := &FreezerGroup{} + return freezer.GetState(dir) } func (m *manager) Exists() bool { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go index ee180bdaf50..053ec33e01a 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go @@ -37,6 +37,9 @@ func canSkipEBPFError(cgroup *configs.Cgroup) bool { } func setDevices(dirPath string, cgroup *configs.Cgroup) error { + if cgroup.SkipDevices { + return nil + } // XXX: This is currently a white-list (but all callers pass a blacklist of // devices). This is bad for a whole variety of reasons, but will need // to be fixed with co-ordinated effort with downstreams. diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go index 53fa3f2c895..b567f3e1fcb 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go @@ -27,6 +27,9 @@ var ( versionOnce sync.Once version int versionErr error + + isRunningSystemdOnce sync.Once + isRunningSystemd bool ) // NOTE: This function comes from package github.com/coreos/go-systemd/util @@ -37,11 +40,11 @@ var ( // checks whether /run/systemd/system/ exists and is a directory. // http://www.freedesktop.org/software/systemd/man/sd_booted.html func IsRunningSystemd() bool { - fi, err := os.Lstat("/run/systemd/system") - if err != nil { - return false - } - return fi.IsDir() + isRunningSystemdOnce.Do(func() { + fi, err := os.Lstat("/run/systemd/system") + isRunningSystemd = err == nil && fi.IsDir() + }) + return isRunningSystemd } // systemd represents slice hierarchy using `-`, so we need to follow suit when diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go index 9e8e2fdd18f..c3cc9c8b3bb 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go @@ -222,7 +222,14 @@ func (m *legacyManager) Destroy() error { return err } unitName := getUnitName(m.cgroups) - if err := stopUnit(dbusConnection, unitName); err != nil { + + err = stopUnit(dbusConnection, unitName) + // Both on success and on error, cleanup all the cgroups we are aware of. + // Some of them were created directly by Apply() and are not managed by systemd. + if err := cgroups.RemovePaths(m.paths); err != nil { + return err + } + if err != nil { return err } m.paths = make(map[string]string) @@ -319,10 +326,7 @@ func (m *legacyManager) Freeze(state configs.FreezerState) error { } prevState := m.cgroups.Resources.Freezer m.cgroups.Resources.Freezer = state - freezer, err := legacySubsystems.Get("freezer") - if err != nil { - return err - } + freezer := &fs.FreezerGroup{} err = freezer.Set(path, m.cgroups) if err != nil { m.cgroups.Resources.Freezer = prevState @@ -379,24 +383,27 @@ func (m *legacyManager) Set(container *configs.Config) error { return err } - // Figure out the current freezer state, so we can revert to it after we - // temporarily freeze the container. - targetFreezerState, err := m.GetFreezerState() - if err != nil { - return err - } - if targetFreezerState == configs.Undefined { - targetFreezerState = configs.Thawed - } - // We have to freeze the container while systemd sets the cgroup settings. // The reason for this is that systemd's application of DeviceAllow rules // is done disruptively, resulting in spurrious errors to common devices // (unlike our fs driver, they will happily write deny-all rules to running // containers). So we freeze the container to avoid them hitting the cgroup // error. But if the freezer cgroup isn't supported, we just warn about it. - if err := m.Freeze(configs.Frozen); err != nil { - logrus.Infof("freeze container before SetUnitProperties failed: %v", err) + targetFreezerState := configs.Undefined + if !m.cgroups.SkipDevices { + // Figure out the current freezer state, so we can revert to it after we + // temporarily freeze the container. + targetFreezerState, err = m.GetFreezerState() + if err != nil { + return err + } + if targetFreezerState == configs.Undefined { + targetFreezerState = configs.Thawed + } + + if err := m.Freeze(configs.Frozen); err != nil { + logrus.Infof("freeze container before SetUnitProperties failed: %v", err) + } } if err := dbusConnection.SetUnitProperties(getUnitName(container.Cgroups), true, properties...); err != nil { @@ -458,11 +465,8 @@ func (m *legacyManager) GetFreezerState() (configs.FreezerState, error) { if err != nil && !cgroups.IsNotFound(err) { return configs.Undefined, err } - freezer, err := legacySubsystems.Get("freezer") - if err != nil { - return configs.Undefined, err - } - return freezer.(*fs.FreezerGroup).GetState(path) + freezer := &fs.FreezerGroup{} + return freezer.GetState(path) } func (m *legacyManager) Exists() bool { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go index 6e343aa9850..e1a6622a0d3 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go @@ -298,24 +298,27 @@ func (m *unifiedManager) Set(container *configs.Config) error { return err } - // Figure out the current freezer state, so we can revert to it after we - // temporarily freeze the container. - targetFreezerState, err := m.GetFreezerState() - if err != nil { - return err - } - if targetFreezerState == configs.Undefined { - targetFreezerState = configs.Thawed - } - // We have to freeze the container while systemd sets the cgroup settings. // The reason for this is that systemd's application of DeviceAllow rules // is done disruptively, resulting in spurrious errors to common devices // (unlike our fs driver, they will happily write deny-all rules to running // containers). So we freeze the container to avoid them hitting the cgroup // error. But if the freezer cgroup isn't supported, we just warn about it. - if err := m.Freeze(configs.Frozen); err != nil { - logrus.Infof("freeze container before SetUnitProperties failed: %v", err) + targetFreezerState := configs.Undefined + if !m.cgroups.SkipDevices { + // Figure out the current freezer state, so we can revert to it after we + // temporarily freeze the container. + targetFreezerState, err = m.GetFreezerState() + if err != nil { + return err + } + if targetFreezerState == configs.Undefined { + targetFreezerState = configs.Thawed + } + + if err := m.Freeze(configs.Frozen); err != nil { + logrus.Infof("freeze container before SetUnitProperties failed: %v", err) + } } if err := dbusConnection.SetUnitProperties(getUnitName(m.cgroups), true, properties...); err != nil { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go index f1a5bd11f5b..6e90ae16b50 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go @@ -126,4 +126,11 @@ type Resources struct { // CpuWeight sets a proportional bandwidth limit. CpuWeight uint64 `json:"cpu_weight"` + + // SkipDevices allows to skip configuring device permissions. + // Used by e.g. kubelet while creating a parent cgroup (kubepods) + // common for many containers. + // + // NOTE it is impossible to start a container which has this flag set. + SkipDevices bool `json:"skip_devices"` } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go index b4d722b03ac..c5188b1dbba 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go @@ -251,6 +251,9 @@ func (c *linuxContainer) Set(config configs.Config) error { func (c *linuxContainer) Start(process *Process) error { c.m.Lock() defer c.m.Unlock() + if c.config.Cgroups.Resources.SkipDevices { + return newGenericError(errors.New("can't start container with SkipDevices set"), ConfigInvalid) + } if process.Init { if err := c.createExecFifo(); err != nil { return err diff --git a/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go index 5487a223c1d..f2dc17e00e9 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go @@ -184,6 +184,9 @@ func setupConsole(socket *os.File, config *initConfig, mount bool) error { return err } + // After we return from here, we don't need the console anymore. + defer pty.Close() + if config.ConsoleHeight != 0 && config.ConsoleWidth != 0 { err = pty.Resize(console.WinSize{ Height: config.ConsoleHeight, @@ -195,9 +198,6 @@ func setupConsole(socket *os.File, config *initConfig, mount bool) error { } } - // After we return from here, we don't need the console anymore. - defer pty.Close() - // Mount the console inside our rootfs. if mount { if err := mountConsole(slavePath); err != nil { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go index de30982ba2f..4b89dad7376 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go @@ -60,7 +60,7 @@ type Group struct { // groupFromOS converts an os/user.(*Group) to local Group // -// (This does not include Pass, Shell or Gecos) +// (This does not include Pass or List) func groupFromOS(g *user.Group) (Group, error) { newGroup := Group{ Name: g.Name, diff --git a/vendor/modules.txt b/vendor/modules.txt index f81e9f1cc2b..fb2e0e46a99 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -135,7 +135,7 @@ github.com/chai2010/gettext-go/gettext/po # github.com/checkpoint-restore/go-criu/v4 v4.0.2 => github.com/checkpoint-restore/go-criu/v4 v4.0.2 github.com/checkpoint-restore/go-criu/v4 github.com/checkpoint-restore/go-criu/v4/rpc -# github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574 => github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574 +# github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 => github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 github.com/cilium/ebpf github.com/cilium/ebpf/asm github.com/cilium/ebpf/internal @@ -575,7 +575,7 @@ github.com/opencontainers/go-digest # github.com/opencontainers/image-spec v1.0.1 => github.com/opencontainers/image-spec v1.0.1 github.com/opencontainers/image-spec/specs-go github.com/opencontainers/image-spec/specs-go/v1 -# github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657 => github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657 +# github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb => github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb github.com/opencontainers/runc/libcontainer github.com/opencontainers/runc/libcontainer/apparmor github.com/opencontainers/runc/libcontainer/cgroups From 0d2a493a8f8367e76bbbf2b7b68aba86cdcb01bf Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Tue, 7 Jul 2020 08:56:15 +0200 Subject: [PATCH 2/2] kubelet: skip setting the devices cgroup use the new libcontainer feature of skipping setting the devices cgroup. This is necessary on cgroup v2 to avoid leaking a eBPF program every time the cgroup is re-configured. Signed-off-by: Giuseppe Scrivano --- pkg/kubelet/cm/cgroup_manager_linux.go | 2 ++ pkg/kubelet/cm/container_manager_linux.go | 1 + pkg/kubelet/dockershim/cm/container_manager_linux.go | 5 +++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/kubelet/cm/cgroup_manager_linux.go b/pkg/kubelet/cm/cgroup_manager_linux.go index c7c7026da40..b0986bd3767 100644 --- a/pkg/kubelet/cm/cgroup_manager_linux.go +++ b/pkg/kubelet/cm/cgroup_manager_linux.go @@ -495,6 +495,7 @@ func setResourcesV2(cgroupConfig *libcontainerconfigs.Cgroup) error { Major: libcontainerconfigs.Wildcard, }, } + cgroupConfig.Resources.SkipDevices = true manager, err := cgroupfs2.NewManager(cgroupConfig, cgroupConfig.Path, false) if err != nil { @@ -517,6 +518,7 @@ func (m *cgroupManagerImpl) toResources(resourceConfig *ResourceConfig) *libcont Major: libcontainerconfigs.Wildcard, }, }, + SkipDevices: true, } if resourceConfig == nil { return resources diff --git a/pkg/kubelet/cm/container_manager_linux.go b/pkg/kubelet/cm/container_manager_linux.go index 3bc8e5f45a5..57110ed7745 100644 --- a/pkg/kubelet/cm/container_manager_linux.go +++ b/pkg/kubelet/cm/container_manager_linux.go @@ -384,6 +384,7 @@ func createManager(containerName string) (cgroups.Manager, error) { Major: configs.Wildcard, }, }, + SkipDevices: true, }, } diff --git a/pkg/kubelet/dockershim/cm/container_manager_linux.go b/pkg/kubelet/dockershim/cm/container_manager_linux.go index 2599517716d..4430efb538c 100644 --- a/pkg/kubelet/dockershim/cm/container_manager_linux.go +++ b/pkg/kubelet/dockershim/cm/container_manager_linux.go @@ -123,8 +123,9 @@ func createCgroupManager(name string) (cgroups.Manager, error) { Parent: "/", Name: name, Resources: &configs.Resources{ - Memory: int64(memoryLimit), - MemorySwap: -1, + Memory: int64(memoryLimit), + MemorySwap: -1, + SkipDevices: true, Devices: []*configs.DeviceRule{ { Minor: configs.Wildcard,