diff --git a/go.mod b/go.mod index e114faba5e4..7f5be146d64 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/caddyserver/caddy v1.0.3 github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c github.com/checkpoint-restore/go-criu v0.0.0-20181120144056-17b0214f6c48 // indirect - github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3 // indirect + github.com/cilium/ebpf v0.0.0-20191025125908-95b36a581eed // indirect github.com/client9/misspell v0.3.4 github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 github.com/codegangsta/negroni v1.0.0 // indirect @@ -222,7 +222,7 @@ replace ( github.com/chai2010/gettext-go => github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 github.com/checkpoint-restore/go-criu => github.com/checkpoint-restore/go-criu v0.0.0-20181120144056-17b0214f6c48 // 17b0214f6c48 is the SHA for git tag 3.11 github.com/cheekybits/genny => github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9 - github.com/cilium/ebpf => github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3 + github.com/cilium/ebpf => github.com/cilium/ebpf v0.0.0-20191025125908-95b36a581eed github.com/client9/misspell => github.com/client9/misspell v0.3.4 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 diff --git a/go.sum b/go.sum index b6c0a10a0cf..0b2b4767c3d 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1 github.com/checkpoint-restore/go-criu v0.0.0-20181120144056-17b0214f6c48 h1:AQMF0Xixllgf29MKlx/TGEhRk7bEDX5kxz8Ui8lOvEs= github.com/checkpoint-restore/go-criu v0.0.0-20181120144056-17b0214f6c48/go.mod h1:TrMrLQfeENAPYPRsJuq3jsqdlRh3lvi6trTZJG8+tho= github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3 h1:i8+1fuPLjSgAYXUyBlHNhFwjcfAsP4ufiuH1+PWkyDU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20191025125908-95b36a581eed h1:/UgmF+cZTm9kp4uJ122y/9cVhczNJCgAgAeH2FfzPeg= +github.com/cilium/ebpf v0.0.0-20191025125908-95b36a581eed/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 h1:eIHD9GNM3Hp7kcRW5mvcz7WTR3ETeoYYKwpgA04kaXE= diff --git a/vendor/github.com/cilium/ebpf/BUILD b/vendor/github.com/cilium/ebpf/BUILD index 1ae725fdb7f..67d9d39612c 100644 --- a/vendor/github.com/cilium/ebpf/BUILD +++ b/vendor/github.com/cilium/ebpf/BUILD @@ -7,10 +7,14 @@ go_library( "collection.go", "doc.go", "elf_reader.go", + "feature.go", "linker.go", "map.go", "marshalers.go", "prog.go", + "ptr_32_be.go", + "ptr_32_le.go", + "ptr_64.go", "syscalls.go", "types.go", "types_string.go", @@ -21,7 +25,6 @@ go_library( deps = [ "//vendor/github.com/cilium/ebpf/asm:go_default_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/github.com/pkg/errors:go_default_library", ], diff --git a/vendor/github.com/cilium/ebpf/abi.go b/vendor/github.com/cilium/ebpf/abi.go index 77227ffda73..999b8cc8597 100644 --- a/vendor/github.com/cilium/ebpf/abi.go +++ b/vendor/github.com/cilium/ebpf/abi.go @@ -1,90 +1,143 @@ package ebpf import ( - "bufio" - "bytes" - "fmt" - "io" - "os" - "syscall" - - "github.com/cilium/ebpf/internal" - "github.com/pkg/errors" ) -// MapABI are the attributes of a Map which are available across all supported kernels. +// CollectionABI describes the interface of an eBPF collection. +type CollectionABI struct { + Maps map[string]*MapABI + Programs map[string]*ProgramABI +} + +// CheckSpec verifies that all maps and programs mentioned +// in the ABI are present in the spec. +func (abi *CollectionABI) CheckSpec(cs *CollectionSpec) error { + for name := range abi.Maps { + if cs.Maps[name] == nil { + return errors.Errorf("missing map %s", name) + } + } + + for name := range abi.Programs { + if cs.Programs[name] == nil { + return errors.Errorf("missing program %s", name) + } + } + + return nil +} + +// Check verifies that all items in a collection conform to this ABI. +func (abi *CollectionABI) Check(coll *Collection) error { + for name, mapABI := range abi.Maps { + m := coll.Maps[name] + if m == nil { + return errors.Errorf("missing map %s", name) + } + if err := mapABI.Check(m); err != nil { + return errors.Wrapf(err, "map %s", name) + } + } + + for name, progABI := range abi.Programs { + p := coll.Programs[name] + if p == nil { + return errors.Errorf("missing program %s", name) + } + if err := progABI.Check(p); err != nil { + return errors.Wrapf(err, "program %s", name) + } + } + + return nil +} + +// MapABI describes a Map. +// +// Use it to assert that a Map matches what your code expects. type MapABI struct { Type MapType KeySize uint32 ValueSize uint32 MaxEntries uint32 - Flags uint32 + InnerMap *MapABI } func newMapABIFromSpec(spec *MapSpec) *MapABI { + var inner *MapABI + if spec.InnerMap != nil { + inner = newMapABIFromSpec(spec.InnerMap) + } + return &MapABI{ spec.Type, spec.KeySize, spec.ValueSize, spec.MaxEntries, - spec.Flags, + inner, } } -func newMapABIFromFd(fd *internal.FD) (string, *MapABI, error) { +func newMapABIFromFd(fd *bpfFD) (*MapABI, error) { info, err := bpfGetMapInfoByFD(fd) - if err != nil { - if errors.Cause(err) == syscall.EINVAL { - abi, err := newMapABIFromProc(fd) - return "", abi, err - } - return "", nil, err - } - - return "", &MapABI{ - MapType(info.mapType), - info.keySize, - info.valueSize, - info.maxEntries, - info.flags, - }, nil -} - -func newMapABIFromProc(fd *internal.FD) (*MapABI, error) { - var abi MapABI - err := scanFdInfo(fd, map[string]interface{}{ - "map_type": &abi.Type, - "key_size": &abi.KeySize, - "value_size": &abi.ValueSize, - "max_entries": &abi.MaxEntries, - "map_flags": &abi.Flags, - }) if err != nil { return nil, err } - return &abi, nil -} -// Equal returns true if two ABIs have the same values. -func (abi *MapABI) Equal(other *MapABI) bool { - switch { - case abi.Type != other.Type: - return false - case abi.KeySize != other.KeySize: - return false - case abi.ValueSize != other.ValueSize: - return false - case abi.MaxEntries != other.MaxEntries: - return false - case abi.Flags != other.Flags: - return false - default: - return true + mapType := MapType(info.mapType) + if mapType == ArrayOfMaps || mapType == HashOfMaps { + return nil, errors.New("can't get map info for nested maps") } + + return &MapABI{ + mapType, + info.keySize, + info.valueSize, + info.maxEntries, + nil, + }, nil } -// ProgramABI are the attributes of a Program which are available across all supported kernels. +// Check verifies that a Map conforms to the ABI. +// +// Members of ABI which have the zero value of their type are not checked. +func (abi *MapABI) Check(m *Map) error { + return abi.check(&m.abi) +} + +func (abi *MapABI) check(other *MapABI) error { + if abi.Type != UnspecifiedMap && other.Type != abi.Type { + return errors.Errorf("expected map type %s, have %s", abi.Type, other.Type) + } + if err := checkUint32("key size", abi.KeySize, other.KeySize); err != nil { + return err + } + if err := checkUint32("value size", abi.ValueSize, other.ValueSize); err != nil { + return err + } + if err := checkUint32("max entries", abi.MaxEntries, other.MaxEntries); err != nil { + return err + } + + if abi.InnerMap == nil { + if abi.Type == ArrayOfMaps || abi.Type == HashOfMaps { + return errors.New("missing inner map ABI") + } + + return nil + } + + if other.InnerMap == nil { + return errors.New("missing inner map") + } + + return errors.Wrap(abi.InnerMap.check(other.InnerMap), "inner map") +} + +// ProgramABI describes a Program. +// +// Use it to assert that a Program matches what your code expects. type ProgramABI struct { Type ProgramType } @@ -95,110 +148,36 @@ func newProgramABIFromSpec(spec *ProgramSpec) *ProgramABI { } } -func newProgramABIFromFd(fd *internal.FD) (string, *ProgramABI, error) { +func newProgramABIFromFd(fd *bpfFD) (*ProgramABI, error) { info, err := bpfGetProgInfoByFD(fd) if err != nil { - if errors.Cause(err) == syscall.EINVAL { - return newProgramABIFromProc(fd) - } - - return "", nil, err + return nil, err } - var name string - if bpfName := internal.CString(info.name[:]); bpfName != "" { - name = bpfName - } else { - name = internal.CString(info.tag[:]) - } + return newProgramABIFromInfo(info), nil +} - return name, &ProgramABI{ +func newProgramABIFromInfo(info *bpfProgInfo) *ProgramABI { + return &ProgramABI{ Type: ProgramType(info.progType), - }, nil + } } -func newProgramABIFromProc(fd *internal.FD) (string, *ProgramABI, error) { - var ( - abi ProgramABI - name string - ) - - err := scanFdInfo(fd, map[string]interface{}{ - "prog_type": &abi.Type, - "prog_tag": &name, - }) - if errors.Cause(err) == errMissingFields { - return "", nil, &internal.UnsupportedFeatureError{ - Name: "reading ABI from /proc/self/fdinfo", - MinimumVersion: internal.Version{4, 11, 0}, - } - } - if err != nil { - return "", nil, err - } - - return name, &abi, nil -} - -func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error { - raw, err := fd.Value() - if err != nil { - return err - } - - fh, err := os.Open(fmt.Sprintf("/proc/self/fdinfo/%d", raw)) - if err != nil { - return err - } - defer fh.Close() - - return errors.Wrap(scanFdInfoReader(fh, fields), fh.Name()) -} - -var errMissingFields = errors.New("missing fields") - -func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error { - var ( - scanner = bufio.NewScanner(r) - scanned int - ) - - for scanner.Scan() { - parts := bytes.SplitN(scanner.Bytes(), []byte("\t"), 2) - if len(parts) != 2 { - continue - } - - name := bytes.TrimSuffix(parts[0], []byte(":")) - field, ok := fields[string(name)] - if !ok { - continue - } - - if n, err := fmt.Fscanln(bytes.NewReader(parts[1]), field); err != nil || n != 1 { - return errors.Wrapf(err, "can't parse field %s", name) - } - - scanned++ - } - - if err := scanner.Err(); err != nil { - return err - } - - if scanned != len(fields) { - return errMissingFields +// Check verifies that a Program conforms to the ABI. +// +// Members which have the zero value of their type +// are not checked. +func (abi *ProgramABI) Check(prog *Program) error { + if abi.Type != UnspecifiedProgram && prog.abi.Type != abi.Type { + return errors.Errorf("expected program type %s, have %s", abi.Type, prog.abi.Type) } return nil } -// Equal returns true if two ABIs have the same values. -func (abi *ProgramABI) Equal(other *ProgramABI) bool { - switch { - case abi.Type != other.Type: - return false - default: - return true +func checkUint32(name string, want, have uint32) error { + if want != 0 && have != want { + return errors.Errorf("expected %s to be %d, have %d", name, want, have) } + return nil } diff --git a/vendor/github.com/cilium/ebpf/collection.go b/vendor/github.com/cilium/ebpf/collection.go index bf6a96d4a50..5ad1a5ec4b7 100644 --- a/vendor/github.com/cilium/ebpf/collection.go +++ b/vendor/github.com/cilium/ebpf/collection.go @@ -2,7 +2,6 @@ package ebpf import ( "github.com/cilium/ebpf/asm" - "github.com/cilium/ebpf/internal/btf" "github.com/pkg/errors" ) @@ -56,61 +55,17 @@ func NewCollection(spec *CollectionSpec) (*Collection, error) { // NewCollectionWithOptions creates a Collection from a specification. // // Only maps referenced by at least one of the programs are initialized. -func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (coll *Collection, err error) { - var ( - maps = make(map[string]*Map) - progs = make(map[string]*Program) - btfs = make(map[*btf.Spec]*btf.Handle) - ) - - defer func() { - for _, btf := range btfs { - btf.Close() - } - - if err == nil { - return - } - - for _, m := range maps { - m.Close() - } - - for _, p := range progs { - p.Close() - } - }() - - loadBTF := func(spec *btf.Spec) (*btf.Handle, error) { - if btfs[spec] != nil { - return btfs[spec], nil - } - - handle, err := btf.NewHandle(spec) - if err != nil { - return nil, err - } - - btfs[spec] = handle - return handle, nil - } - +func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) { + maps := make(map[string]*Map) for mapName, mapSpec := range spec.Maps { - var handle *btf.Handle - if mapSpec.BTF != nil { - handle, err = loadBTF(btf.MapSpec(mapSpec.BTF)) - if err != nil && !btf.IsNotSupported(err) { - return nil, err - } - } - - m, err := newMapWithBTF(mapSpec, handle) + m, err := NewMap(mapSpec) if err != nil { return nil, errors.Wrapf(err, "map %s", mapName) } maps[mapName] = m } + progs := make(map[string]*Program) for progName, origProgSpec := range spec.Programs { progSpec := origProgSpec.Copy() @@ -136,15 +91,7 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (col } } - var handle *btf.Handle - if progSpec.BTF != nil { - handle, err = loadBTF(btf.ProgramSpec(progSpec.BTF)) - if err != nil && !btf.IsNotSupported(err) { - return nil, err - } - } - - prog, err := newProgramWithBTF(progSpec, handle, opts.Programs) + prog, err := NewProgramWithOptions(progSpec, opts.Programs) if err != nil { return nil, errors.Wrapf(err, "program %s", progName) } diff --git a/vendor/github.com/cilium/ebpf/elf_reader.go b/vendor/github.com/cilium/ebpf/elf_reader.go index c33b744f86e..3bdc0849bdd 100644 --- a/vendor/github.com/cilium/ebpf/elf_reader.go +++ b/vendor/github.com/cilium/ebpf/elf_reader.go @@ -4,13 +4,12 @@ import ( "bytes" "debug/elf" "encoding/binary" + "fmt" "io" "os" "strings" "github.com/cilium/ebpf/asm" - "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/btf" "github.com/pkg/errors" ) @@ -19,8 +18,6 @@ type elfCode struct { *elf.File symbols []elf.Symbol symbolsPerSection map[elf.SectionIndex]map[uint64]string - license string - version uint32 } // LoadCollectionSpec parses an ELF file into a CollectionSpec. @@ -36,8 +33,8 @@ func LoadCollectionSpec(file string) (*CollectionSpec, error) { } // LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec. -func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { - f, err := elf.NewFile(rd) +func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) { + f, err := elf.NewFile(code) if err != nil { return nil, err } @@ -48,17 +45,12 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { return nil, errors.Wrap(err, "load symbols") } - ec := &elfCode{f, symbols, symbolsPerSection(symbols), "", 0} - - var ( - licenseSection *elf.Section - versionSection *elf.Section - btfMaps = make(map[elf.SectionIndex]*elf.Section) - progSections = make(map[elf.SectionIndex]*elf.Section) - relSections = make(map[elf.SectionIndex]*elf.Section) - mapSections = make(map[elf.SectionIndex]*elf.Section) - ) + ec := &elfCode{f, symbols, symbolsPerSection(symbols)} + var licenseSection, versionSection *elf.Section + progSections := make(map[elf.SectionIndex]*elf.Section) + relSections := make(map[elf.SectionIndex]*elf.Section) + mapSections := make(map[elf.SectionIndex]*elf.Section) for i, sec := range ec.Sections { switch { case strings.HasPrefix(sec.Name, "license"): @@ -67,8 +59,6 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { versionSection = sec case strings.HasPrefix(sec.Name, "maps"): mapSections[elf.SectionIndex(i)] = sec - case sec.Name == ".maps": - btfMaps[elf.SectionIndex(i)] = sec case sec.Type == elf.SHT_REL: if int(sec.Info) >= len(ec.Sections) { return nil, errors.Errorf("found relocation section %v for missing section %v", i, sec.Info) @@ -77,7 +67,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { // Store relocations under the section index of the target idx := elf.SectionIndex(sec.Info) if relSections[idx] != nil { - return nil, errors.Errorf("section %d has multiple relocation sections", sec.Info) + return nil, errors.Errorf("section %d has multiple relocation sections", idx) } relSections[idx] = sec case sec.Type == elf.SHT_PROGBITS && (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0: @@ -85,38 +75,35 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { } } - ec.license, err = loadLicense(licenseSection) + license, err := loadLicense(licenseSection) if err != nil { return nil, errors.Wrap(err, "load license") } - ec.version, err = loadVersion(versionSection, ec.ByteOrder) + version, err := loadVersion(versionSection, ec.ByteOrder) if err != nil { return nil, errors.Wrap(err, "load version") } - btf, err := btf.LoadSpecFromReader(rd) + maps, err := ec.loadMaps(mapSections) if err != nil { - return nil, errors.Wrap(err, "load BTF") - } - - maps := make(map[string]*MapSpec) - - if err := ec.loadMaps(maps, mapSections); err != nil { return nil, errors.Wrap(err, "load maps") } - if len(btfMaps) > 0 { - if err := ec.loadBTFMaps(maps, btfMaps, btf); err != nil { - return nil, errors.Wrap(err, "load BTF maps") - } - } - - progs, err := ec.loadPrograms(progSections, relSections, btf) + progs, libs, err := ec.loadPrograms(progSections, relSections, license, version) if err != nil { return nil, errors.Wrap(err, "load programs") } + if len(libs) > 0 { + for name, prog := range progs { + prog.Instructions, err = link(prog.Instructions, libs...) + if err != nil { + return nil, errors.Wrapf(err, "program %s", name) + } + } + } + return &CollectionSpec{maps, progs}, nil } @@ -141,74 +128,52 @@ func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) { return version, errors.Wrapf(err, "section %s", sec.Name) } -func (ec *elfCode) loadPrograms(progSections, relSections map[elf.SectionIndex]*elf.Section, btf *btf.Spec) (map[string]*ProgramSpec, error) { +func (ec *elfCode) loadPrograms(progSections, relSections map[elf.SectionIndex]*elf.Section, license string, version uint32) (map[string]*ProgramSpec, []asm.Instructions, error) { var ( - progs []*ProgramSpec - libs []*ProgramSpec + progs = make(map[string]*ProgramSpec) + libs []asm.Instructions ) - for idx, prog := range progSections { syms := ec.symbolsPerSection[idx] if len(syms) == 0 { - return nil, errors.Errorf("section %v: missing symbols", prog.Name) + return nil, nil, errors.Errorf("section %v: missing symbols", prog.Name) } funcSym := syms[0] if funcSym == "" { - return nil, errors.Errorf("section %v: no label at start", prog.Name) + return nil, nil, errors.Errorf("section %v: no label at start", prog.Name) } rels, err := ec.loadRelocations(relSections[idx]) if err != nil { - return nil, errors.Wrapf(err, "program %s: can't load relocations", funcSym) + return nil, nil, errors.Wrapf(err, "program %s: can't load relocations", funcSym) } - insns, length, err := ec.loadInstructions(prog, syms, rels) + insns, err := ec.loadInstructions(prog, syms, rels) if err != nil { - return nil, errors.Wrapf(err, "program %s: can't unmarshal instructions", funcSym) + return nil, nil, errors.Wrapf(err, "program %s: can't unmarshal instructions", funcSym) } - progType, attachType := getProgType(prog.Name) - - spec := &ProgramSpec{ - Name: funcSym, - Type: progType, - AttachType: attachType, - License: ec.license, - KernelVersion: ec.version, - Instructions: insns, - } - - if btf != nil { - spec.BTF, err = btf.Program(prog.Name, length) - if err != nil { - return nil, errors.Wrapf(err, "BTF for section %s (program %s)", prog.Name, funcSym) - } - } - - if spec.Type == UnspecifiedProgram { + if progType, attachType := getProgType(prog.Name); progType == UnspecifiedProgram { // There is no single name we can use for "library" sections, // since they may contain multiple functions. We'll decode the // labels they contain later on, and then link sections that way. - libs = append(libs, spec) + libs = append(libs, insns) } else { - progs = append(progs, spec) + progs[funcSym] = &ProgramSpec{ + Name: funcSym, + Type: progType, + AttachType: attachType, + License: license, + KernelVersion: version, + Instructions: insns, + } } } - - res := make(map[string]*ProgramSpec, len(progs)) - for _, prog := range progs { - err := link(prog, libs) - if err != nil { - return nil, errors.Wrapf(err, "program %s", prog.Name) - } - res[prog.Name] = prog - } - - return res, nil + return progs, libs, nil } -func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations map[uint64]string) (asm.Instructions, uint64, error) { +func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations map[uint64]string) (asm.Instructions, error) { var ( r = section.Open() insns asm.Instructions @@ -218,10 +183,10 @@ func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations m for { n, err := ins.Unmarshal(r, ec.ByteOrder) if err == io.EOF { - return insns, offset, nil + return insns, nil } if err != nil { - return nil, 0, errors.Wrapf(err, "offset %d", offset) + return nil, errors.Wrapf(err, "offset %d", offset) } ins.Symbol = symbols[offset] @@ -232,15 +197,19 @@ func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations m } } -func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section) error { +func (ec *elfCode) loadMaps(mapSections map[elf.SectionIndex]*elf.Section) (map[string]*MapSpec, error) { + var ( + maps = make(map[string]*MapSpec) + b = make([]byte, 1) + ) for idx, sec := range mapSections { syms := ec.symbolsPerSection[idx] if len(syms) == 0 { - return errors.Errorf("section %v: no symbols", sec.Name) + return nil, errors.Errorf("section %v: no symbols", sec.Name) } if sec.Size%uint64(len(syms)) != 0 { - return errors.Errorf("section %v: map descriptors are not of equal size", sec.Name) + return nil, errors.Errorf("section %v: map descriptors are not of equal size", sec.Name) } var ( @@ -250,11 +219,12 @@ 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 := syms[offset] if mapSym == "" { - return errors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset) + fmt.Println(syms) + return nil, errors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset) } if maps[mapSym] != nil { - return errors.Errorf("section %v: map %v already exists", sec.Name, mapSym) + return nil, errors.Errorf("section %v: map %v already exists", sec.Name, mapSym) } lr := io.LimitReader(r, int64(size)) @@ -262,152 +232,51 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio var spec MapSpec switch { case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil: - return errors.Errorf("map %v: missing type", mapSym) + return nil, errors.Errorf("map %v: missing type", mapSym) case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil: - return errors.Errorf("map %v: missing key size", mapSym) + return nil, errors.Errorf("map %v: missing key size", mapSym) case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil: - return errors.Errorf("map %v: missing value size", mapSym) + return nil, errors.Errorf("map %v: missing value size", mapSym) case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil: - return errors.Errorf("map %v: missing max entries", mapSym) + return nil, errors.Errorf("map %v: missing max entries", mapSym) case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil: - return errors.Errorf("map %v: missing flags", mapSym) + return nil, errors.Errorf("map %v: missing flags", mapSym) } - if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil { - return errors.Errorf("map %v: unknown and non-zero fields in definition", mapSym) + for { + _, err := lr.Read(b) + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + if b[0] != 0 { + return nil, errors.Errorf("map %v: unknown and non-zero fields in definition", mapSym) + } } maps[mapSym] = &spec } } - - return nil -} - -func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error { - - if spec == nil { - return errors.Errorf("missing BTF") - } - - for idx, sec := range mapSections { - syms := ec.symbolsPerSection[idx] - if len(syms) == 0 { - return errors.Errorf("section %v: no symbols", sec.Name) - } - - for _, sym := range syms { - if maps[sym] != nil { - return errors.Errorf("section %v: map %v already exists", sec.Name, sym) - } - - btfMap, err := spec.Map(sym) - if err != nil { - return errors.Wrapf(err, "map %v: can't get BTF", sym) - } - - spec, err := mapSpecFromBTF(btfMap) - if err != nil { - return errors.Wrapf(err, "map %v", sym) - } - - maps[sym] = spec - } - } - - return nil -} - -func mapSpecFromBTF(btfMap *btf.Map) (*MapSpec, error) { - var ( - mapType, flags, maxEntries uint32 - err error - ) - for _, member := range btf.MapType(btfMap).Members { - switch member.Name { - case "type": - mapType, err = uintFromBTF(member.Type) - if err != nil { - return nil, errors.Wrap(err, "can't get type") - } - - case "map_flags": - flags, err = uintFromBTF(member.Type) - if err != nil { - return nil, errors.Wrap(err, "can't get BTF map flags") - } - - case "max_entries": - maxEntries, err = uintFromBTF(member.Type) - if err != nil { - return nil, errors.Wrap(err, "can't get BTF map max entries") - } - - case "key": - case "value": - default: - return nil, errors.Errorf("unrecognized field %s in BTF map definition", member.Name) - } - } - - keySize, err := btf.Sizeof(btf.MapKey(btfMap)) - if err != nil { - return nil, errors.Wrap(err, "can't get size of BTF key") - } - - valueSize, err := btf.Sizeof(btf.MapValue(btfMap)) - if err != nil { - return nil, errors.Wrap(err, "can't get size of BTF value") - } - - return &MapSpec{ - Type: MapType(mapType), - KeySize: uint32(keySize), - ValueSize: uint32(valueSize), - MaxEntries: maxEntries, - Flags: flags, - BTF: btfMap, - }, nil -} - -// uintFromBTF resolves the __uint macro, which is a pointer to a sized -// array, e.g. for int (*foo)[10], this function will return 10. -func uintFromBTF(typ btf.Type) (uint32, error) { - ptr, ok := typ.(*btf.Pointer) - if !ok { - return 0, errors.Errorf("not a pointer: %v", typ) - } - - arr, ok := ptr.Target.(*btf.Array) - if !ok { - return 0, errors.Errorf("not a pointer to array: %v", typ) - } - - return arr.Nelems, nil + return maps, 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, + "socket": SocketFilter, + "seccomp": SocketFilter, + "kprobe/": Kprobe, + "kretprobe/": Kprobe, + "tracepoint/": TracePoint, + "xdp": XDP, + "perf_event": PerfEvent, + "sockops": SockOps, + "sk_skb": SkSKB, + "sk_msg": SkMsg, + "lirc_mode2": LircMode2, + "flow_dissector": FlowDissector, "cgroup_skb/": CGroupSKB, "cgroup/dev": CGroupDevice, diff --git a/vendor/github.com/cilium/ebpf/feature.go b/vendor/github.com/cilium/ebpf/feature.go new file mode 100644 index 00000000000..9104bc9c4ce --- /dev/null +++ b/vendor/github.com/cilium/ebpf/feature.go @@ -0,0 +1,19 @@ +package ebpf + +import ( + "sync" +) + +type featureTest struct { + Fn func() bool + + once sync.Once + result bool +} + +func (ft *featureTest) Result() bool { + ft.once.Do(func() { + ft.result = ft.Fn() + }) + return ft.result +} diff --git a/vendor/github.com/cilium/ebpf/internal/BUILD b/vendor/github.com/cilium/ebpf/internal/BUILD index c0f62fe2e30..fd4e8df2b1a 100644 --- a/vendor/github.com/cilium/ebpf/internal/BUILD +++ b/vendor/github.com/cilium/ebpf/internal/BUILD @@ -5,23 +5,11 @@ go_library( srcs = [ "cpu.go", "endian.go", - "errors.go", - "fd.go", - "feature.go", - "io.go", - "ptr.go", - "ptr_32_be.go", - "ptr_32_le.go", - "ptr_64.go", - "syscall.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/github.com/pkg/errors:go_default_library", - ], + deps = ["//vendor/github.com/pkg/errors:go_default_library"], ) filegroup( @@ -35,7 +23,6 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//vendor/github.com/cilium/ebpf/internal/btf:all-srcs", "//vendor/github.com/cilium/ebpf/internal/unix:all-srcs", ], tags = ["automanaged"], diff --git a/vendor/github.com/cilium/ebpf/internal/btf/BUILD b/vendor/github.com/cilium/ebpf/internal/btf/BUILD deleted file mode 100644 index 2a29764c31c..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/btf/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "btf.go", - "btf_types.go", - "doc.go", - "ext_info.go", - "strings.go", - "types.go", - ], - importmap = "k8s.io/kubernetes/vendor/github.com/cilium/ebpf/internal/btf", - importpath = "github.com/cilium/ebpf/internal/btf", - visibility = ["//vendor/github.com/cilium/ebpf:__subpackages__"], - deps = [ - "//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/github.com/pkg/errors:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/github.com/cilium/ebpf/internal/btf/btf.go b/vendor/github.com/cilium/ebpf/internal/btf/btf.go deleted file mode 100644 index b2122f37ede..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/btf/btf.go +++ /dev/null @@ -1,530 +0,0 @@ -package btf - -import ( - "bytes" - "debug/elf" - "encoding/binary" - "io" - "io/ioutil" - "math" - "reflect" - "unsafe" - - "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/unix" - - "github.com/pkg/errors" -) - -const btfMagic = 0xeB9F - -// Spec represents decoded BTF. -type Spec struct { - rawTypes []rawType - strings stringTable - types map[string][]Type - funcInfos map[string]extInfo - lineInfos map[string]extInfo -} - -type btfHeader struct { - Magic uint16 - Version uint8 - Flags uint8 - HdrLen uint32 - - TypeOff uint32 - TypeLen uint32 - StringOff uint32 - StringLen uint32 -} - -// LoadSpecFromReader reads BTF sections from an ELF. -// -// Returns a nil Spec and no error if no BTF was present. -func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { - file, err := elf.NewFile(rd) - if err != nil { - return nil, err - } - defer file.Close() - - var ( - btfSection *elf.Section - btfExtSection *elf.Section - ) - - for _, sec := range file.Sections { - switch sec.Name { - case ".BTF": - btfSection = sec - case ".BTF.ext": - btfExtSection = sec - } - } - - if btfSection == nil { - return nil, nil - } - - spec, err := parseBTF(btfSection.Open(), file.ByteOrder) - if err != nil { - return nil, err - } - - if btfExtSection != nil { - spec.funcInfos, spec.lineInfos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings) - if err != nil { - return nil, errors.Wrap(err, "can't read ext info") - } - } - - return spec, nil -} - -func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) (*Spec, error) { - rawBTF, err := ioutil.ReadAll(btf) - if err != nil { - return nil, errors.Wrap(err, "can't read BTF") - } - - rd := bytes.NewReader(rawBTF) - - var header btfHeader - if err := binary.Read(rd, bo, &header); err != nil { - return nil, errors.Wrap(err, "can't read header") - } - - if header.Magic != btfMagic { - return nil, errors.Errorf("incorrect magic value %v", header.Magic) - } - - if header.Version != 1 { - return nil, errors.Errorf("unexpected version %v", header.Version) - } - - if header.Flags != 0 { - return nil, errors.Errorf("unsupported flags %v", header.Flags) - } - - remainder := int64(header.HdrLen) - int64(binary.Size(&header)) - if remainder < 0 { - return nil, errors.New("header is too short") - } - - if _, err := io.CopyN(internal.DiscardZeroes{}, rd, remainder); err != nil { - return nil, errors.Wrap(err, "header padding") - } - - if _, err := rd.Seek(int64(header.HdrLen+header.StringOff), io.SeekStart); err != nil { - return nil, errors.Wrap(err, "can't seek to start of string section") - } - - strings, err := readStringTable(io.LimitReader(rd, int64(header.StringLen))) - if err != nil { - return nil, errors.Wrap(err, "can't read type names") - } - - if _, err := rd.Seek(int64(header.HdrLen+header.TypeOff), io.SeekStart); err != nil { - return nil, errors.Wrap(err, "can't seek to start of type section") - } - - rawTypes, err := readTypes(io.LimitReader(rd, int64(header.TypeLen)), bo) - if err != nil { - return nil, errors.Wrap(err, "can't read types") - } - - types, err := inflateRawTypes(rawTypes, strings) - if err != nil { - return nil, err - } - - return &Spec{ - rawTypes: rawTypes, - types: types, - strings: strings, - funcInfos: make(map[string]extInfo), - lineInfos: make(map[string]extInfo), - }, nil -} - -func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) { - var ( - buf bytes.Buffer - header = new(btfHeader) - headerLen = binary.Size(header) - ) - - // Reserve space for the header. We have to write it last since - // we don't know the size of the type section yet. - _, _ = buf.Write(make([]byte, headerLen)) - - // Write type section, just after the header. - for _, typ := range s.rawTypes { - if typ.Kind() == kindDatasec { - // Datasec requires patching with information from the ELF - // file. We don't support this at the moment, so patch - // out any Datasec by turning it into a void*. - typ = rawType{} - typ.SetKind(kindPointer) - } - - if err := typ.Marshal(&buf, bo); err != nil { - return nil, errors.Wrap(err, "can't marshal BTF") - } - } - - typeLen := uint32(buf.Len() - headerLen) - - // Write string section after type section. - _, _ = buf.Write(s.strings) - - // Fill out the header, and write it out. - header = &btfHeader{ - Magic: btfMagic, - Version: 1, - Flags: 0, - HdrLen: uint32(headerLen), - TypeOff: 0, - TypeLen: typeLen, - StringOff: typeLen, - StringLen: uint32(len(s.strings)), - } - - raw := buf.Bytes() - err := binary.Write(sliceWriter(raw[:headerLen]), bo, header) - if err != nil { - return nil, errors.Wrap(err, "can't write header") - } - - return raw, nil -} - -type sliceWriter []byte - -func (sw sliceWriter) Write(p []byte) (int, error) { - if len(p) != len(sw) { - return 0, errors.New("size doesn't match") - } - - return copy(sw, p), nil -} - -// Program finds the BTF for a specific section. -// -// Length is the number of bytes in the raw BPF instruction stream. -// -// Returns an error if there is no BTF. -func (s *Spec) Program(name string, length uint64) (*Program, error) { - if length == 0 { - return nil, errors.New("length musn't be zero") - } - - funcInfos, funcOK := s.funcInfos[name] - lineInfos, lineOK := s.lineInfos[name] - - if !funcOK && !lineOK { - return nil, errors.Errorf("no BTF for program %s", name) - } - - return &Program{s, length, funcInfos, lineInfos}, nil -} - -// Map finds the BTF for a map. -// -// Returns an error if there is no BTF for the given name. -func (s *Spec) Map(name string) (*Map, error) { - var mapVar Var - if err := s.FindType(name, &mapVar); err != nil { - return nil, err - } - - mapStruct, ok := mapVar.Type.(*Struct) - if !ok { - return nil, errors.Errorf("expected struct, have %s", mapVar.Type) - } - - var key, value Type - for _, member := range mapStruct.Members { - switch member.Name { - case "key": - key = member.Type - - case "value": - value = member.Type - } - } - - if key == nil { - return nil, errors.Errorf("map %s: missing 'key' in type", name) - } - - if value == nil { - return nil, errors.Errorf("map %s: missing 'value' in type", name) - } - - return &Map{mapStruct, s, key, value}, nil -} - -var errNotFound = errors.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. -func (s *Spec) FindType(name string, typ Type) error { - var ( - wanted = reflect.TypeOf(typ) - candidate Type - ) - - for _, typ := range s.types[name] { - if reflect.TypeOf(typ) != wanted { - continue - } - - if candidate != nil { - return errors.Errorf("type %s: multiple candidates for %T", name, typ) - } - - candidate = typ - } - - if candidate == nil { - return errors.WithMessagef(errNotFound, "type %s", name) - } - - value := reflect.Indirect(reflect.ValueOf(copyType(candidate))) - reflect.Indirect(reflect.ValueOf(typ)).Set(value) - return nil -} - -// Handle is a reference to BTF loaded into the kernel. -type Handle struct { - fd *internal.FD -} - -// NewHandle loads BTF into the kernel. -// -// Returns an error if BTF is not supported, which can -// be checked by IsNotSupported. -func NewHandle(spec *Spec) (*Handle, error) { - if err := haveBTF(); err != nil { - return nil, err - } - - btf, err := spec.marshal(internal.NativeEndian) - if err != nil { - return nil, errors.Wrap(err, "can't marshal BTF") - } - - if uint64(len(btf)) > math.MaxUint32 { - return nil, errors.New("BTF exceeds the maximum size") - } - - attr := &bpfLoadBTFAttr{ - btf: internal.NewSlicePointer(btf), - btfSize: uint32(len(btf)), - } - - fd, err := bpfLoadBTF(attr) - if err != nil { - logBuf := make([]byte, 64*1024) - attr.logBuf = internal.NewSlicePointer(logBuf) - attr.btfLogSize = uint32(len(logBuf)) - attr.btfLogLevel = 1 - _, logErr := bpfLoadBTF(attr) - return nil, internal.ErrorWithLog(err, logBuf, logErr) - } - - return &Handle{fd}, nil -} - -// Close destroys the handle. -// -// Subsequent calls to FD will return an invalid value. -func (h *Handle) Close() error { - return h.fd.Close() -} - -// FD returns the file descriptor for the handle. -func (h *Handle) FD() int { - value, err := h.fd.Value() - if err != nil { - return -1 - } - - return int(value) -} - -// Map is the BTF for a map. -type Map struct { - definition *Struct - spec *Spec - key, value Type -} - -// MapSpec should be a method on Map, but is a free function -// to hide it from users of the ebpf package. -func MapSpec(m *Map) *Spec { - return m.spec -} - -// MapType should be a method on Map, but is a free function -// to hide it from users of the ebpf package. -func MapType(m *Map) *Struct { - return m.definition -} - -// MapKey should be a method on Map, but is a free function -// to hide it from users of the ebpf package. -func MapKey(m *Map) Type { - return m.key -} - -// MapValue should be a method on Map, but is a free function -// to hide it from users of the ebpf package. -func MapValue(m *Map) Type { - return m.value -} - -// Program is the BTF information for a stream of instructions. -type Program struct { - spec *Spec - length uint64 - funcInfos, lineInfos extInfo -} - -// ProgramSpec returns the Spec needed for loading function and line infos into the kernel. -// -// This is a free function instead of a method to hide it from users -// of package ebpf. -func ProgramSpec(s *Program) *Spec { - return s.spec -} - -// ProgramAppend the information from other to the Program. -// -// This is a free function instead of a method to hide it from users -// of package ebpf. -func ProgramAppend(s, other *Program) error { - funcInfos, err := s.funcInfos.append(other.funcInfos, s.length) - if err != nil { - return errors.Wrap(err, "func infos") - } - - lineInfos, err := s.lineInfos.append(other.lineInfos, s.length) - if err != nil { - return errors.Wrap(err, "line infos") - } - - s.length += other.length - s.funcInfos = funcInfos - s.lineInfos = lineInfos - return nil -} - -// ProgramFuncInfos returns the binary form of BTF function infos. -// -// This is a free function instead of a method to hide it from users -// of package ebpf. -func ProgramFuncInfos(s *Program) (recordSize uint32, bytes []byte, err error) { - bytes, err = s.funcInfos.MarshalBinary() - if err != nil { - return 0, nil, err - } - - return s.funcInfos.recordSize, bytes, nil -} - -// ProgramLineInfos returns the binary form of BTF line infos. -// -// This is a free function instead of a method to hide it from users -// of package ebpf. -func ProgramLineInfos(s *Program) (recordSize uint32, bytes []byte, err error) { - bytes, err = s.lineInfos.MarshalBinary() - if err != nil { - return 0, nil, err - } - - return s.lineInfos.recordSize, bytes, nil -} - -// IsNotSupported returns true if the error indicates that the kernel -// doesn't support BTF. -func IsNotSupported(err error) bool { - ufe, ok := errors.Cause(err).(*internal.UnsupportedFeatureError) - return ok && ufe.Name == "BTF" -} - -type bpfLoadBTFAttr struct { - btf internal.Pointer - logBuf internal.Pointer - btfSize uint32 - btfLogSize uint32 - btfLogLevel uint32 -} - -func bpfLoadBTF(attr *bpfLoadBTFAttr) (*internal.FD, error) { - const _BTFLoad = 18 - - fd, err := internal.BPF(_BTFLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) - if err != nil { - return nil, err - } - - return internal.NewFD(uint32(fd)), nil -} - -func minimalBTF(bo binary.ByteOrder) []byte { - const minHeaderLength = 24 - - 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 - // the kernel understands BTF at least as well as we - // do. BTF_KIND_VAR was introduced ~5.1. - types.Integer.SetKind(kindPointer) - types.Var.NameOff = 1 - 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) - - 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)), - }) - if err == nil { - fd.Close() - } - // Check for EINVAL specifically, rather than err != nil since we - // otherwise misdetect due to insufficient permissions. - return errors.Cause(err) != unix.EINVAL -}) diff --git a/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go b/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go deleted file mode 100644 index 6570fedffe6..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go +++ /dev/null @@ -1,190 +0,0 @@ -package btf - -import ( - "encoding/binary" - "io" - - "github.com/pkg/errors" -) - -// btfKind describes a Type. -type btfKind uint8 - -// Equivalents of the BTF_KIND_* constants. -const ( - kindUnknown btfKind = iota - kindInt - kindPointer - kindArray - kindStruct - kindUnion - kindEnum - kindForward - kindTypedef - kindVolatile - kindConst - kindRestrict - // Added ~4.20 - kindFunc - kindFuncProto - // Added ~5.1 - kindVar - kindDatasec -) - -const ( - btfTypeKindShift = 24 - btfTypeKindLen = 4 - btfTypeVlenShift = 0 - btfTypeVlenMask = 16 -) - -// btfType is equivalent to struct btf_type in Documentation/bpf/btf.rst. -type btfType struct { - NameOff uint32 - /* "info" bits arrangement - * bits 0-15: vlen (e.g. # of struct's members) - * bits 16-23: unused - * bits 24-27: kind (e.g. int, ptr, array...etc) - * bits 28-30: unused - * bit 31: kind_flag, currently used by - * struct, union and fwd - */ - Info uint32 - /* "size" is used by INT, ENUM, STRUCT and UNION. - * "size" tells the size of the type it is describing. - * - * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, - * FUNC and FUNC_PROTO. - * "type" is a type_id referring to another type. - */ - SizeType uint32 -} - -func mask(len uint32) uint32 { - return (1 << len) - 1 -} - -func (bt *btfType) info(len, shift uint32) uint32 { - return (bt.Info >> shift) & mask(len) -} - -func (bt *btfType) setInfo(value, len, shift uint32) { - bt.Info &^= mask(len) << shift - bt.Info |= (value & mask(len)) << shift -} - -func (bt *btfType) Kind() btfKind { - return btfKind(bt.info(btfTypeKindLen, btfTypeKindShift)) -} - -func (bt *btfType) SetKind(kind btfKind) { - bt.setInfo(uint32(kind), btfTypeKindLen, btfTypeKindShift) -} - -func (bt *btfType) Vlen() int { - return int(bt.info(btfTypeVlenMask, btfTypeVlenShift)) -} - -func (bt *btfType) SetVlen(vlen int) { - bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift) -} - -func (bt *btfType) Type() TypeID { - // TODO: Panic here if wrong kind? - return TypeID(bt.SizeType) -} - -func (bt *btfType) Size() uint32 { - // TODO: Panic here if wrong kind? - return bt.SizeType -} - -type rawType struct { - btfType - data interface{} -} - -func (rt *rawType) Marshal(w io.Writer, bo binary.ByteOrder) error { - if err := binary.Write(w, bo, &rt.btfType); err != nil { - return err - } - - if rt.data == nil { - return nil - } - - return binary.Write(w, bo, rt.data) -} - -type btfArray struct { - Type TypeID - IndexType TypeID - Nelems uint32 -} - -type btfMember struct { - NameOff uint32 - Type TypeID - Offset uint32 -} - -func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) { - var ( - header btfType - types []rawType - ) - - for id := TypeID(1); ; id++ { - if err := binary.Read(r, bo, &header); err == io.EOF { - return types, nil - } else if err != nil { - return nil, errors.Wrapf(err, "can't read type info for id %v", id) - } - - var data interface{} - switch header.Kind() { - case kindInt: - // sizeof(uint32) - data = make([]byte, 4) - case kindPointer: - case kindArray: - data = new(btfArray) - case kindStruct: - fallthrough - case kindUnion: - data = make([]btfMember, header.Vlen()) - case kindEnum: - // sizeof(struct btf_enum) - data = make([]byte, header.Vlen()*4*2) - case kindForward: - case kindTypedef: - case kindVolatile: - case kindConst: - case kindRestrict: - case kindFunc: - case kindFuncProto: - // sizeof(struct btf_param) - data = make([]byte, header.Vlen()*4*2) - case kindVar: - // sizeof(struct btf_variable) - data = make([]byte, 4) - case kindDatasec: - // sizeof(struct btf_var_secinfo) - data = make([]byte, header.Vlen()*4*3) - default: - return nil, errors.Errorf("type id %v: unknown kind: %v", id, header.Kind()) - } - - if data == nil { - types = append(types, rawType{header, nil}) - continue - } - - if err := binary.Read(r, bo, data); err != nil { - return nil, errors.Wrapf(err, "type id %d: kind %v: can't read %T", id, header.Kind(), data) - } - - types = append(types, rawType{header, data}) - } -} diff --git a/vendor/github.com/cilium/ebpf/internal/btf/doc.go b/vendor/github.com/cilium/ebpf/internal/btf/doc.go deleted file mode 100644 index ad2576cb23c..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/btf/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// Package btf handles data encoded according to the BPF Type Format. -// -// The canonical documentation lives in the Linux kernel repository and is -// available at https://www.kernel.org/doc/html/latest/bpf/btf.html -// -// The API is very much unstable. You should only use this via the main -// ebpf library. -package btf diff --git a/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go b/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go deleted file mode 100644 index ab019cac7f7..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go +++ /dev/null @@ -1,184 +0,0 @@ -package btf - -import ( - "bytes" - "encoding/binary" - "io" - "io/ioutil" - - "github.com/cilium/ebpf/asm" - "github.com/cilium/ebpf/internal" - - "github.com/pkg/errors" -) - -type btfExtHeader struct { - Magic uint16 - Version uint8 - Flags uint8 - HdrLen uint32 - - FuncInfoOff uint32 - FuncInfoLen uint32 - LineInfoOff uint32 - LineInfoLen uint32 -} - -func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, err error) { - const expectedMagic = 0xeB9F - - var header btfExtHeader - if err := binary.Read(r, bo, &header); err != nil { - return nil, nil, errors.Wrap(err, "can't read header") - } - - if header.Magic != expectedMagic { - return nil, nil, errors.Errorf("incorrect magic value %v", header.Magic) - } - - if header.Version != 1 { - return nil, nil, errors.Errorf("unexpected version %v", header.Version) - } - - if header.Flags != 0 { - return nil, nil, errors.Errorf("unsupported flags %v", header.Flags) - } - - remainder := int64(header.HdrLen) - int64(binary.Size(&header)) - if remainder < 0 { - 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, errors.Wrap(err, "header padding") - } - - if _, err := r.Seek(int64(header.HdrLen+header.FuncInfoOff), io.SeekStart); err != nil { - return nil, nil, errors.Wrap(err, "can't seek to function info section") - } - - funcInfo, err = parseExtInfo(io.LimitReader(r, int64(header.FuncInfoLen)), bo, strings) - if err != nil { - return nil, nil, errors.Wrap(err, "function info") - } - - if _, err := r.Seek(int64(header.HdrLen+header.LineInfoOff), io.SeekStart); err != nil { - return nil, nil, errors.Wrap(err, "can't seek to line info section") - } - - lineInfo, err = parseExtInfo(io.LimitReader(r, int64(header.LineInfoLen)), bo, strings) - if err != nil { - return nil, nil, errors.Wrap(err, "line info") - } - - return funcInfo, lineInfo, nil -} - -type btfExtInfoSec struct { - SecNameOff uint32 - NumInfo uint32 -} - -type extInfoRecord struct { - InsnOff uint64 - Opaque []byte -} - -type extInfo struct { - recordSize uint32 - records []extInfoRecord -} - -func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) { - if other.recordSize != ei.recordSize { - return extInfo{}, errors.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize) - } - - records := make([]extInfoRecord, 0, len(ei.records)+len(other.records)) - records = append(records, ei.records...) - for _, info := range other.records { - records = append(records, extInfoRecord{ - InsnOff: info.InsnOff + offset, - Opaque: info.Opaque, - }) - } - return extInfo{ei.recordSize, records}, nil -} - -func (ei extInfo) MarshalBinary() ([]byte, error) { - if len(ei.records) == 0 { - return nil, nil - } - - buf := bytes.NewBuffer(make([]byte, 0, int(ei.recordSize)*len(ei.records))) - for _, info := range ei.records { - // The kernel expects offsets in number of raw bpf instructions, - // 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, errors.Wrap(err, "can't write instruction offset") - } - - buf.Write(info.Opaque) - } - - return buf.Bytes(), nil -} - -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, errors.Wrap(err, "can't read record size") - } - - if recordSize < 4 { - // Need at least insnOff - return nil, errors.New("record size too short") - } - - result := make(map[string]extInfo) - for { - var infoHeader btfExtInfoSec - if err := binary.Read(r, bo, &infoHeader); err == io.EOF { - return result, nil - } else if err != nil { - return nil, errors.Wrap(err, "can't read ext info header") - } - - secName, err := strings.Lookup(infoHeader.SecNameOff) - if err != nil { - return nil, errors.Wrap(err, "can't get section name") - } - - if infoHeader.NumInfo == 0 { - return nil, errors.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, errors.Wrapf(err, "section %v: can't read extended info offset", secName) - } - - buf := make([]byte, int(recordSize-4)) - if _, err := io.ReadFull(r, buf); err != nil { - return nil, errors.Wrapf(err, "section %v: can't read record", secName) - } - - if byteOff%asm.InstructionSize != 0 { - return nil, errors.Errorf("section %v: offset %v is not aligned with instruction size", secName, byteOff) - } - - records = append(records, extInfoRecord{uint64(byteOff), buf}) - } - - result[secName] = extInfo{ - recordSize, - records, - } - } -} diff --git a/vendor/github.com/cilium/ebpf/internal/btf/strings.go b/vendor/github.com/cilium/ebpf/internal/btf/strings.go deleted file mode 100644 index c0337649e9c..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/btf/strings.go +++ /dev/null @@ -1,60 +0,0 @@ -package btf - -import ( - "bytes" - "io" - "io/ioutil" - - "github.com/pkg/errors" -) - -type stringTable []byte - -func readStringTable(r io.Reader) (stringTable, error) { - contents, err := ioutil.ReadAll(r) - if err != nil { - return nil, errors.Wrap(err, "can't read string table") - } - - if len(contents) < 1 { - return nil, errors.New("string table is empty") - } - - if contents[0] != '\x00' { - return nil, errors.New("first item in string table is non-empty") - } - - if contents[len(contents)-1] != '\x00' { - return nil, errors.New("string table isn't null terminated") - } - - return stringTable(contents), nil -} - -func (st stringTable) Lookup(offset uint32) (string, error) { - if int64(offset) > int64(^uint(0)>>1) { - return "", errors.Errorf("offset %d overflows int", offset) - } - - pos := int(offset) - if pos >= len(st) { - return "", errors.Errorf("offset %d is out of bounds", offset) - } - - if pos > 0 && st[pos-1] != '\x00' { - return "", errors.Errorf("offset %d isn't start of a string", offset) - } - - str := st[pos:] - end := bytes.IndexByte(str, '\x00') - if end == -1 { - return "", errors.Errorf("offset %d isn't null terminated", offset) - } - - return string(str[:end]), nil -} - -func (st stringTable) LookupName(offset uint32) (Name, error) { - str, err := st.Lookup(offset) - return Name(str), err -} diff --git a/vendor/github.com/cilium/ebpf/internal/btf/types.go b/vendor/github.com/cilium/ebpf/internal/btf/types.go deleted file mode 100644 index c49cb862119..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/btf/types.go +++ /dev/null @@ -1,550 +0,0 @@ -package btf - -import ( - "math" - - "github.com/pkg/errors" -) - -const maxTypeDepth = 32 - -// TypeID identifies a type in a BTF section. -type TypeID uint32 - -// ID implements part of the Type interface. -func (tid TypeID) ID() TypeID { - return tid -} - -// Type represents a type described by BTF. -type Type interface { - ID() TypeID - - // Make a copy of the type, without copying Type members. - copy() Type - - walk(*copyStack) -} - -// Name identifies a type. -// -// Anonymous types have an empty name. -type Name string - -func (n Name) name() string { - return string(n) -} - -// 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) {} - -// Int is an integer of a given length. -type Int struct { - TypeID - Name - - // The size of the integer in bytes. - Size uint32 -} - -func (i *Int) size() uint32 { return i.Size } -func (i *Int) walk(*copyStack) {} -func (i *Int) copy() Type { - cpy := *i - return &cpy -} - -// Pointer is a pointer to another type. -type Pointer struct { - TypeID - Target Type -} - -func (p *Pointer) size() uint32 { return 8 } -func (p *Pointer) walk(cs *copyStack) { cs.push(&p.Target) } -func (p *Pointer) copy() Type { - cpy := *p - return &cpy -} - -// Array is an array with a fixed number of elements. -type Array struct { - TypeID - Type Type - Nelems uint32 -} - -func (arr *Array) walk(cs *copyStack) { cs.push(&arr.Type) } -func (arr *Array) copy() Type { - cpy := *arr - return &cpy -} - -// Struct is a compound type of consecutive members. -type Struct struct { - TypeID - Name - // The size of the struct including padding, in bytes - Size uint32 - Members []Member -} - -func (s *Struct) size() uint32 { return s.Size } - -func (s *Struct) walk(cs *copyStack) { - for i := range s.Members { - cs.push(&s.Members[i].Type) - } -} - -func (s *Struct) copy() Type { - cpy := *s - cpy.Members = copyMembers(cpy.Members) - return &cpy -} - -// Union is a compound type where members occupy the same memory. -type Union struct { - TypeID - Name - // The size of the union including padding, in bytes. - Size uint32 - Members []Member -} - -func (u *Union) size() uint32 { return u.Size } - -func (u *Union) walk(cs *copyStack) { - for i := range u.Members { - cs.push(&u.Members[i].Type) - } -} - -func (u *Union) copy() Type { - cpy := *u - cpy.Members = copyMembers(cpy.Members) - return &cpy -} - -// Member is part of a Struct or Union. -// -// It is not a valid Type. -type Member struct { - Name - Type Type - Offset uint32 -} - -func copyMembers(in []Member) []Member { - cpy := make([]Member, 0, len(in)) - for _, member := range in { - cpy = append(cpy, member) - } - return cpy -} - -// Enum lists possible values. -type Enum struct { - TypeID - Name -} - -func (e *Enum) size() uint32 { return 4 } -func (e *Enum) walk(*copyStack) {} -func (e *Enum) copy() Type { - cpy := *e - return &cpy -} - -// Fwd is a forward declaration of a Type. -type Fwd struct { - TypeID - Name -} - -func (f *Fwd) walk(*copyStack) {} -func (f *Fwd) copy() Type { - cpy := *f - return &cpy -} - -// Typedef is an alias of a Type. -type Typedef struct { - TypeID - Name - Type Type -} - -func (td *Typedef) walk(cs *copyStack) { cs.push(&td.Type) } -func (td *Typedef) copy() Type { - cpy := *td - return &cpy -} - -// Volatile is a modifier. -type Volatile struct { - TypeID - Type Type -} - -func (v *Volatile) walk(cs *copyStack) { cs.push(&v.Type) } -func (v *Volatile) copy() Type { - cpy := *v - return &cpy -} - -// Const is a modifier. -type Const struct { - TypeID - Type Type -} - -func (c *Const) walk(cs *copyStack) { cs.push(&c.Type) } -func (c *Const) copy() Type { - cpy := *c - return &cpy -} - -// Restrict is a modifier. -type Restrict struct { - TypeID - Type Type -} - -func (r *Restrict) walk(cs *copyStack) { cs.push(&r.Type) } -func (r *Restrict) copy() Type { - cpy := *r - return &cpy -} - -// Func is a function definition. -type Func struct { - TypeID - Name - Type Type -} - -func (f *Func) walk(cs *copyStack) { cs.push(&f.Type) } -func (f *Func) copy() Type { - cpy := *f - return &cpy -} - -// FuncProto is a function declaration. -type FuncProto struct { - TypeID - Return Type - // Parameters not supported yet -} - -func (fp *FuncProto) walk(cs *copyStack) { cs.push(&fp.Return) } -func (fp *FuncProto) copy() Type { - cpy := *fp - return &cpy -} - -// Var is a global variable. -type Var struct { - TypeID - Name - Type Type -} - -func (v *Var) walk(cs *copyStack) { cs.push(&v.Type) } -func (v *Var) copy() Type { - cpy := *v - return &cpy -} - -// Datasec is a global program section containing data. -type Datasec struct { - TypeID - Name - Size uint32 -} - -func (ds *Datasec) size() uint32 { return ds.Size } -func (ds *Datasec) walk(*copyStack) {} -func (ds *Datasec) copy() Type { - cpy := *ds - return &cpy -} - -type sizer interface { - size() uint32 -} - -var ( - _ sizer = (*Int)(nil) - _ sizer = (*Pointer)(nil) - _ sizer = (*Struct)(nil) - _ sizer = (*Union)(nil) - _ sizer = (*Enum)(nil) - _ sizer = (*Datasec)(nil) -) - -// Sizeof returns the size of a type in bytes. -// -// Returns an error if the size can't be computed. -func Sizeof(typ Type) (int, error) { - var ( - n = int64(1) - elem int64 - ) - - for i := 0; i < maxTypeDepth; i++ { - switch v := typ.(type) { - case *Array: - if n > 0 && int64(v.Nelems) > math.MaxInt64/n { - return 0, errors.New("overflow") - } - - // Arrays may be of zero length, which allows - // n to be zero as well. - n *= int64(v.Nelems) - typ = v.Type - continue - - case sizer: - elem = int64(v.size()) - - case *Typedef: - typ = v.Type - continue - case *Volatile: - typ = v.Type - continue - case *Const: - typ = v.Type - continue - case *Restrict: - typ = v.Type - continue - - default: - return 0, errors.Errorf("unrecognized type %T", typ) - } - - if n > 0 && elem > math.MaxInt64/n { - return 0, errors.New("overflow") - } - - size := n * elem - if int64(int(size)) != size { - return 0, errors.New("overflow") - } - - return int(size), nil - } - - return 0, errors.New("exceeded type depth") -} - -// copy a Type recursively. -// -// typ may form a cycle. -func copyType(typ Type) Type { - var ( - copies = make(map[Type]Type) - work copyStack - ) - - for t := &typ; t != nil; t = work.pop() { - // *t is the identity of the type. - if cpy := copies[*t]; cpy != nil { - *t = cpy - continue - } - - cpy := (*t).copy() - copies[*t] = cpy - *t = cpy - - // Mark any nested types for copying. - cpy.walk(&work) - } - - return typ -} - -// copyStack keeps track of pointers to types which still -// need to be copied. -type copyStack []*Type - -// push adds a type to the stack. -func (cs *copyStack) push(t *Type) { - *cs = append(*cs, t) -} - -// pop returns the topmost Type, or nil. -func (cs *copyStack) pop() *Type { - n := len(*cs) - if n == 0 { - return nil - } - - t := (*cs)[n-1] - *cs = (*cs)[:n-1] - return t -} - -type namer interface { - name() string -} - -var _ namer = Name("") - -// inflateRawTypes takes a list of raw btf types linked via type IDs, and turns -// it into a graph of Types connected via pointers. -// -// Returns a map of named types (so, where NameOff is non-zero). Since BTF ignores -// compilation units, multiple types may share the same name. A Type may form a -// cyclic graph by pointing at itself. -func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map[string][]Type, err error) { - type fixup struct { - id TypeID - typ *Type - } - - var fixups []fixup - convertMembers := func(raw []btfMember) ([]Member, error) { - // NB: The fixup below relies on pre-allocating this array to - // work, since otherwise append might re-allocate members. - members := make([]Member, 0, len(raw)) - for i, btfMember := range raw { - name, err := rawStrings.LookupName(btfMember.NameOff) - if err != nil { - return nil, errors.Wrapf(err, "can't get name for member %d", i) - } - members = append(members, Member{ - Name: name, - Offset: btfMember.Offset, - }) - } - for i := range members { - fixups = append(fixups, fixup{raw[i].Type, &members[i].Type}) - } - return members, nil - } - - types := make([]Type, 0, len(rawTypes)) - types = append(types, Void{}) - namedTypes = make(map[string][]Type) - - for i, raw := range rawTypes { - var ( - // Void is defined to always be type ID 0, and is thus - // omitted from BTF. - id = TypeID(i + 1) - typ Type - ) - - name, err := rawStrings.LookupName(raw.NameOff) - if err != nil { - return nil, errors.Wrapf(err, "can't get name for type id %d", id) - } - - switch raw.Kind() { - case kindInt: - typ = &Int{id, name, raw.Size()} - - case kindPointer: - ptr := &Pointer{id, nil} - fixups = append(fixups, fixup{raw.Type(), &ptr.Target}) - typ = ptr - - case kindArray: - btfArr := raw.data.(*btfArray) - - // IndexType is unused according to btf.rst. - // Don't make it available right now. - arr := &Array{id, nil, btfArr.Nelems} - fixups = append(fixups, fixup{btfArr.Type, &arr.Type}) - typ = arr - - case kindStruct: - members, err := convertMembers(raw.data.([]btfMember)) - if err != nil { - return nil, errors.Wrapf(err, "struct %s (id %d)", name, id) - } - typ = &Struct{id, name, raw.Size(), members} - - case kindUnion: - members, err := convertMembers(raw.data.([]btfMember)) - if err != nil { - return nil, errors.Wrapf(err, "union %s (id %d)", name, id) - } - typ = &Union{id, name, raw.Size(), members} - - case kindEnum: - typ = &Enum{id, name} - - case kindForward: - typ = &Fwd{id, name} - - case kindTypedef: - typedef := &Typedef{id, name, nil} - fixups = append(fixups, fixup{raw.Type(), &typedef.Type}) - typ = typedef - - case kindVolatile: - volatile := &Volatile{id, nil} - fixups = append(fixups, fixup{raw.Type(), &volatile.Type}) - typ = volatile - - case kindConst: - cnst := &Const{id, nil} - fixups = append(fixups, fixup{raw.Type(), &cnst.Type}) - typ = cnst - - case kindRestrict: - restrict := &Restrict{id, nil} - fixups = append(fixups, fixup{raw.Type(), &restrict.Type}) - typ = restrict - - case kindFunc: - fn := &Func{id, name, nil} - fixups = append(fixups, fixup{raw.Type(), &fn.Type}) - typ = fn - - case kindFuncProto: - fp := &FuncProto{id, nil} - fixups = append(fixups, fixup{raw.Type(), &fp.Return}) - typ = fp - - case kindVar: - v := &Var{id, name, nil} - fixups = append(fixups, fixup{raw.Type(), &v.Type}) - typ = v - - case kindDatasec: - typ = &Datasec{id, name, raw.SizeType} - - default: - return nil, errors.Errorf("type id %d: unknown kind: %v", id, raw.Kind()) - } - - types = append(types, typ) - - if namer, ok := typ.(namer); ok { - if name := namer.name(); name != "" { - namedTypes[name] = append(namedTypes[name], typ) - } - } - } - - for _, fixup := range fixups { - i := int(fixup.id) - if i >= len(types) { - return nil, errors.Errorf("reference to invalid type id: %d", fixup.id) - } - - *fixup.typ = types[i] - } - - return namedTypes, nil -} diff --git a/vendor/github.com/cilium/ebpf/internal/errors.go b/vendor/github.com/cilium/ebpf/internal/errors.go deleted file mode 100644 index 9590fe84e15..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/errors.go +++ /dev/null @@ -1,50 +0,0 @@ -package internal - -import ( - "bytes" - "fmt" - "strings" - - "github.com/cilium/ebpf/internal/unix" - "github.com/pkg/errors" -) - -// ErrorWithLog returns an error that includes logs from the -// kernel verifier. -// -// logErr should be the error returned by the syscall that generated -// 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 errors.Cause(logErr) == unix.ENOSPC { - logStr += " (truncated...)" - } - - return &loadError{err, logStr} -} - -type loadError struct { - cause error - log string -} - -func (le *loadError) Error() string { - if le.log == "" { - return le.cause.Error() - } - - return fmt.Sprintf("%s: %s", le.cause, le.log) -} - -func (le *loadError) Cause() error { - return le.cause -} - -// CString turns a NUL / zero terminated byte buffer into a string. -func CString(in []byte) string { - inLen := bytes.IndexByte(in, 0) - if inLen == -1 { - return "" - } - return string(in[:inLen]) -} diff --git a/vendor/github.com/cilium/ebpf/internal/fd.go b/vendor/github.com/cilium/ebpf/internal/fd.go deleted file mode 100644 index 6800c84aaac..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/fd.go +++ /dev/null @@ -1,63 +0,0 @@ -package internal - -import ( - "runtime" - "strconv" - - "github.com/cilium/ebpf/internal/unix" - - "github.com/pkg/errors" -) - -var ErrClosedFd = errors.New("use of closed file descriptor") - -type FD struct { - raw int64 -} - -func NewFD(value uint32) *FD { - fd := &FD{int64(value)} - runtime.SetFinalizer(fd, (*FD).Close) - return fd -} - -func (fd *FD) String() string { - return strconv.FormatInt(fd.raw, 10) -} - -func (fd *FD) Value() (uint32, error) { - if fd.raw < 0 { - return 0, ErrClosedFd - } - - return uint32(fd.raw), nil -} - -func (fd *FD) Close() error { - if fd.raw < 0 { - return nil - } - - value := int(fd.raw) - fd.raw = -1 - - fd.Forget() - return unix.Close(value) -} - -func (fd *FD) Forget() { - runtime.SetFinalizer(fd, nil) -} - -func (fd *FD) Dup() (*FD, error) { - if fd.raw < 0 { - return nil, ErrClosedFd - } - - dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0) - if err != nil { - return nil, errors.Wrap(err, "can't dup fd") - } - - return NewFD(uint32(dup)), nil -} diff --git a/vendor/github.com/cilium/ebpf/internal/feature.go b/vendor/github.com/cilium/ebpf/internal/feature.go deleted file mode 100644 index f7497d37f18..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/feature.go +++ /dev/null @@ -1,85 +0,0 @@ -package internal - -import ( - "fmt" - "sync" - - "github.com/pkg/errors" -) - -// UnsupportedFeatureError is returned by FeatureTest() functions. -type UnsupportedFeatureError struct { - // The minimum Linux mainline version required for this feature. - // Used for the error string, and for sanity checking during testing. - MinimumVersion Version - - // The name of the feature that isn't supported. - Name string -} - -func (ufe *UnsupportedFeatureError) Error() string { - return fmt.Sprintf("%s not supported (requires >= %s)", ufe.Name, ufe.MinimumVersion) -} - -// 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 { - v, err := NewVersion(version) - if err != nil { - return func() error { return err } - } - - var ( - once sync.Once - result error - ) - - return func() error { - once.Do(func() { - if !fn() { - result = &UnsupportedFeatureError{ - MinimumVersion: v, - Name: name, - } - } - }) - return result - } -} - -// A Version in the form Major.Minor.Patch. -type Version [3]uint16 - -// NewVersion creates a version from a string like "Major.Minor.Patch". -// -// Patch is optional. -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{}, errors.Errorf("invalid version: %s", ver) - } - return Version{major, minor, patch}, nil -} - -func (v Version) String() string { - if v[2] == 0 { - return fmt.Sprintf("v%d.%d", v[0], v[1]) - } - return fmt.Sprintf("v%d.%d.%d", v[0], v[1], v[2]) -} - -// Less returns true if the version is less than another version. -func (v Version) Less(other Version) bool { - for i, a := range v { - if a == other[i] { - continue - } - return a < other[i] - } - return false -} diff --git a/vendor/github.com/cilium/ebpf/internal/io.go b/vendor/github.com/cilium/ebpf/internal/io.go deleted file mode 100644 index 756e8611915..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/io.go +++ /dev/null @@ -1,16 +0,0 @@ -package internal - -import "github.com/pkg/errors" - -// DiscardZeroes makes sure that all written bytes are zero -// before discarding them. -type DiscardZeroes struct{} - -func (DiscardZeroes) Write(p []byte) (int, error) { - for _, b := range p { - if b != 0 { - return 0, errors.New("encountered non-zero byte") - } - } - return len(p), nil -} diff --git a/vendor/github.com/cilium/ebpf/internal/ptr.go b/vendor/github.com/cilium/ebpf/internal/ptr.go deleted file mode 100644 index e79b5aa004c..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/ptr.go +++ /dev/null @@ -1,26 +0,0 @@ -package internal - -import "unsafe" - -// NewPointer creates a 64-bit pointer from an unsafe Pointer. -func NewPointer(ptr unsafe.Pointer) Pointer { - return Pointer{ptr: ptr} -} - -// NewSlicePointer creates a 64-bit pointer from a byte slice. -func NewSlicePointer(buf []byte) Pointer { - if len(buf) == 0 { - return Pointer{} - } - - return Pointer{ptr: unsafe.Pointer(&buf[0])} -} - -// NewStringPointer creates a 64-bit pointer from a string. -func NewStringPointer(str string) Pointer { - if str == "" { - return Pointer{} - } - - return Pointer{ptr: unsafe.Pointer(&[]byte(str)[0])} -} diff --git a/vendor/github.com/cilium/ebpf/internal/syscall.go b/vendor/github.com/cilium/ebpf/internal/syscall.go deleted file mode 100644 index b32cf3bceb3..00000000000 --- a/vendor/github.com/cilium/ebpf/internal/syscall.go +++ /dev/null @@ -1,23 +0,0 @@ -package internal - -import ( - "runtime" - "unsafe" - - "github.com/cilium/ebpf/internal/unix" -) - -// 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) { - r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size) - runtime.KeepAlive(attr) - - var err error - if errNo != 0 { - err = errNo - } - - return r1, err -} diff --git a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go index 16930966745..49c6be5b0e6 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go @@ -30,7 +30,6 @@ const ( PerfBitWatermark = linux.PerfBitWatermark PERF_SAMPLE_RAW = linux.PERF_SAMPLE_RAW PERF_FLAG_FD_CLOEXEC = linux.PERF_FLAG_FD_CLOEXEC - RLIM_INFINITY = linux.RLIM_INFINITY ) // Statfs_t is a wrapper @@ -117,11 +116,3 @@ type PerfEventAttr = linux.PerfEventAttr func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { return linux.PerfEventOpen(attr, pid, cpu, groupFd, flags) } - -// Utsname is a wrapper -type Utsname = linux.Utsname - -// Uname is a wrapper -func Uname(buf *Utsname) (err error) { - return linux.Uname(buf) -} 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 57a514da7a1..a327f2a5991 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_other.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_other.go @@ -181,13 +181,3 @@ type PerfEventAttr struct { func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { return 0, errNonLinux } - -// Utsname is a wrapper -type Utsname struct { - Release [65]byte -} - -// Uname is a wrapper -func Uname(buf *Utsname) (err error) { - return errNonLinux -} diff --git a/vendor/github.com/cilium/ebpf/linker.go b/vendor/github.com/cilium/ebpf/linker.go index 25f2ab947f7..da556c2269e 100644 --- a/vendor/github.com/cilium/ebpf/linker.go +++ b/vendor/github.com/cilium/ebpf/linker.go @@ -2,35 +2,23 @@ package ebpf import ( "github.com/cilium/ebpf/asm" - "github.com/cilium/ebpf/internal/btf" - "github.com/pkg/errors" ) // link resolves bpf-to-bpf calls. // -// Each library may contain multiple functions / labels, and is only linked +// Each section may contain multiple functions / labels, and is only linked // if the program being edited references one of these functions. // -// Libraries must not require linking themselves. -func link(prog *ProgramSpec, libs []*ProgramSpec) error { - for _, lib := range libs { - insns, err := linkSection(prog.Instructions, lib.Instructions) +// Sections must not require linking themselves. +func link(insns asm.Instructions, sections ...asm.Instructions) (asm.Instructions, error) { + for _, section := range sections { + var err error + insns, err = linkSection(insns, section) if err != nil { - return errors.Wrapf(err, "linking %s", lib.Name) - } - - if len(insns) == len(prog.Instructions) { - continue - } - - prog.Instructions = insns - if prog.BTF != nil && lib.BTF != nil { - if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil { - return errors.Wrapf(err, "linking BTF of %s", lib.Name) - } + return nil, err } } - return nil + return insns, nil } func linkSection(insns, section asm.Instructions) (asm.Instructions, error) { diff --git a/vendor/github.com/cilium/ebpf/map.go b/vendor/github.com/cilium/ebpf/map.go index 86eff1aefcc..028a9135202 100644 --- a/vendor/github.com/cilium/ebpf/map.go +++ b/vendor/github.com/cilium/ebpf/map.go @@ -2,9 +2,9 @@ package ebpf import ( "fmt" + "unsafe" "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/btf" "github.com/cilium/ebpf/internal/unix" "github.com/pkg/errors" @@ -20,12 +20,8 @@ type MapSpec struct { ValueSize uint32 MaxEntries uint32 Flags uint32 - // InnerMap is used as a template for ArrayOfMaps and HashOfMaps InnerMap *MapSpec - - // The BTF associated with this map. - BTF *btf.Map } func (ms *MapSpec) String() string { @@ -53,9 +49,8 @@ func (ms *MapSpec) Copy() *MapSpec { // Implement encoding.BinaryMarshaler or encoding.BinaryUnmarshaler // if you require custom encoding. type Map struct { - name string - fd *internal.FD - abi MapABI + fd *bpfFD + abi MapABI // Per CPU maps return values larger than the size in the spec fullValueSize int } @@ -67,14 +62,14 @@ func NewMapFromFD(fd int) (*Map, error) { if fd < 0 { return nil, errors.New("invalid fd") } - bpfFd := internal.NewFD(uint32(fd)) + bpfFd := newBPFFD(uint32(fd)) - name, abi, err := newMapABIFromFd(bpfFd) + abi, err := newMapABIFromFd(bpfFd) if err != nil { - bpfFd.Forget() + bpfFd.forget() return nil, err } - return newMap(bpfFd, name, abi) + return newMap(bpfFd, abi) } // NewMap creates a new Map. @@ -82,47 +77,30 @@ func NewMapFromFD(fd int) (*Map, error) { // Creating a map for the first time will perform feature detection // by creating small, temporary maps. func NewMap(spec *MapSpec) (*Map, error) { - if spec.BTF == nil { - return newMapWithBTF(spec, nil) - } - - handle, err := btf.NewHandle(btf.MapSpec(spec.BTF)) - if err != nil && !btf.IsNotSupported(err) { - return nil, errors.Wrap(err, "can't load BTF") - } - - return newMapWithBTF(spec, handle) -} - -func newMapWithBTF(spec *MapSpec, handle *btf.Handle) (*Map, error) { if spec.Type != ArrayOfMaps && spec.Type != HashOfMaps { - return createMap(spec, nil, handle) + return createMap(spec, nil) } if spec.InnerMap == nil { return nil, errors.Errorf("%s requires InnerMap", spec.Type) } - template, err := createMap(spec.InnerMap, nil, handle) + template, err := createMap(spec.InnerMap, nil) if err != nil { return nil, err } defer template.Close() - return createMap(spec, template.fd, handle) + return createMap(spec, template.fd) } -func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, error) { +func createMap(spec *MapSpec, inner *bpfFD) (*Map, error) { spec = spec.Copy() switch spec.Type { case ArrayOfMaps: fallthrough case HashOfMaps: - if err := haveNestedMaps(); err != nil { - return nil, err - } - if spec.ValueSize != 0 && spec.ValueSize != 4 { return nil, errors.Errorf("ValueSize must be zero or four for map of map") } @@ -157,24 +135,18 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err if inner != nil { var err error - attr.innerMapFd, err = inner.Value() + attr.innerMapFd, err = inner.value() if err != nil { return nil, errors.Wrap(err, "map create") } } - if handle != nil && spec.BTF != nil { - attr.btfFd = uint32(handle.FD()) - attr.btfKeyTypeID = btf.MapKey(spec.BTF).ID() - attr.btfValueTypeID = btf.MapValue(spec.BTF).ID() - } - name, err := newBPFObjName(spec.Name) if err != nil { return nil, errors.Wrap(err, "map create") } - if haveObjName() == nil { + if haveObjName.Result() { attr.mapName = name } @@ -183,12 +155,11 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err return nil, errors.Wrap(err, "map create") } - return newMap(fd, spec.Name, newMapABIFromSpec(spec)) + return newMap(fd, newMapABIFromSpec(spec)) } -func newMap(fd *internal.FD, name string, abi *MapABI) (*Map, error) { +func newMap(fd *bpfFD, abi *MapABI) (*Map, error) { m := &Map{ - name, fd, *abi, int(abi.ValueSize), @@ -208,10 +179,7 @@ func newMap(fd *internal.FD, name string, abi *MapABI) (*Map, error) { } func (m *Map) String() string { - if m.name != "" { - return fmt.Sprintf("%s(%s)#%v", m.abi.Type, m.name, m.fd) - } - return fmt.Sprintf("%s#%v", m.abi.Type, m.fd) + return fmt.Sprintf("%s#%d", m.abi.Type, m.fd) } // ABI gets the ABI of the Map @@ -274,28 +242,12 @@ func (m *Map) Lookup(key, valueOut interface{}) error { } } -// LookupAndDelete retrieves and deletes a value from a Map. -func (m *Map) LookupAndDelete(key, valueOut interface{}) error { - valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize) - - keyPtr, err := marshalPtr(key, int(m.abi.KeySize)) - if err != nil { - return errors.WithMessage(err, "can't marshal key") - } - - if err := bpfMapLookupAndDelete(m.fd, keyPtr, valuePtr); err != nil { - return errors.WithMessage(err, "lookup and delete and delete failed") - } - - return unmarshalBytes(valueOut, valueBytes) -} - // LookupBytes gets a value from Map. // // Returns a nil value if a key doesn't exist. func (m *Map) LookupBytes(key interface{}) ([]byte, error) { valueBytes := make([]byte, m.fullValueSize) - valuePtr := internal.NewSlicePointer(valueBytes) + valuePtr := newPtr(unsafe.Pointer(&valueBytes[0])) err := m.lookup(key, valuePtr) if IsNotExist(err) { @@ -305,7 +257,7 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) { return valueBytes, err } -func (m *Map) lookup(key interface{}, valueOut internal.Pointer) error { +func (m *Map) lookup(key interface{}, valueOut syscallPtr) error { keyPtr, err := marshalPtr(key, int(m.abi.KeySize)) if err != nil { return errors.WithMessage(err, "can't marshal key") @@ -343,7 +295,7 @@ func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error { return errors.WithMessage(err, "can't marshal key") } - var valuePtr internal.Pointer + var valuePtr syscallPtr if m.abi.Type.hasPerCPUValue() { valuePtr, err = marshalPerCPUValue(value, int(m.abi.ValueSize)) } else { @@ -394,7 +346,7 @@ func (m *Map) NextKey(key, nextKeyOut interface{}) error { // Use Iterate if you want to traverse all entries in the map. func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) { nextKey := make([]byte, m.abi.KeySize) - nextKeyPtr := internal.NewSlicePointer(nextKey) + nextKeyPtr := newPtr(unsafe.Pointer(&nextKey[0])) err := m.nextKey(key, nextKeyPtr) if IsNotExist(err) { @@ -404,9 +356,9 @@ func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) { return nextKey, err } -func (m *Map) nextKey(key interface{}, nextKeyOut internal.Pointer) error { +func (m *Map) nextKey(key interface{}, nextKeyOut syscallPtr) error { var ( - keyPtr internal.Pointer + keyPtr syscallPtr err error ) @@ -439,14 +391,14 @@ func (m *Map) Close() error { return nil } - return m.fd.Close() + return m.fd.close() } // FD gets the file descriptor of the Map. // // Calling this function is invalid after Close has been called. func (m *Map) FD() int { - fd, err := m.fd.Value() + fd, err := m.fd.value() if err != nil { // Best effort: -1 is the number most likely to be an // invalid file descriptor. @@ -467,12 +419,12 @@ func (m *Map) Clone() (*Map, error) { return nil, nil } - dup, err := m.fd.Dup() + dup, err := m.fd.dup() if err != nil { return nil, errors.Wrap(err, "can't clone map") } - return newMap(dup, m.name, &m.abi) + return newMap(dup, &m.abi) } // Pin persists the map past the lifetime of the process that created it. @@ -484,19 +436,19 @@ func (m *Map) Pin(fileName string) error { // LoadPinnedMap load a Map from a BPF file. // -// The function is not compatible with nested maps. -// Use LoadPinnedMapExplicit in these situations. +// Requires at least Linux 4.13, and is not compatible with +// nested maps. Use LoadPinnedMapExplicit in these situations. func LoadPinnedMap(fileName string) (*Map, error) { fd, err := bpfGetObject(fileName) if err != nil { return nil, err } - name, abi, err := newMapABIFromFd(fd) + abi, err := newMapABIFromFd(fd) if err != nil { - _ = fd.Close() + _ = fd.close() return nil, err } - return newMap(fd, name, abi) + return newMap(fd, abi) } // LoadPinnedMapExplicit loads a map with explicit parameters. @@ -505,7 +457,7 @@ func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) { if err != nil { return nil, err } - return newMap(fd, "", abi) + return newMap(fd, abi) } func unmarshalMap(buf []byte) (*Map, error) { @@ -521,18 +473,18 @@ func unmarshalMap(buf []byte) (*Map, error) { return nil, err } - name, abi, err := newMapABIFromFd(fd) + abi, err := newMapABIFromFd(fd) if err != nil { - _ = fd.Close() + _ = fd.close() return nil, err } - return newMap(fd, name, abi) + return newMap(fd, abi) } // MarshalBinary implements BinaryMarshaler. func (m *Map) MarshalBinary() ([]byte, error) { - fd, err := m.fd.Value() + fd, err := m.fd.value() 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 64b7d4de76f..44ba2733056 100644 --- a/vendor/github.com/cilium/ebpf/marshalers.go +++ b/vendor/github.com/cilium/ebpf/marshalers.go @@ -13,24 +13,17 @@ import ( "github.com/pkg/errors" ) -func marshalPtr(data interface{}, length int) (internal.Pointer, error) { - if data == nil { - if length == 0 { - return internal.NewPointer(nil), nil - } - return internal.Pointer{}, errors.New("can't use nil as key of map") - } - +func marshalPtr(data interface{}, length int) (syscallPtr, error) { if ptr, ok := data.(unsafe.Pointer); ok { - return internal.NewPointer(ptr), nil + return newPtr(ptr), nil } buf, err := marshalBytes(data, length) if err != nil { - return internal.Pointer{}, err + return syscallPtr{}, err } - return internal.NewSlicePointer(buf), nil + return newPtr(unsafe.Pointer(&buf[0])), nil } func marshalBytes(data interface{}, length int) (buf []byte, err error) { @@ -59,13 +52,13 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) { return buf, nil } -func makeBuffer(dst interface{}, length int) (internal.Pointer, []byte) { +func makeBuffer(dst interface{}, length int) (syscallPtr, []byte) { if ptr, ok := dst.(unsafe.Pointer); ok { - return internal.NewPointer(ptr), nil + return newPtr(ptr), nil } buf := make([]byte, length) - return internal.NewSlicePointer(buf), buf + return newPtr(unsafe.Pointer(&buf[0])), buf } func unmarshalBytes(data interface{}, buf []byte) error { @@ -106,21 +99,21 @@ func unmarshalBytes(data interface{}, buf []byte) error { // Values are initialized to zero if the slice has less elements than CPUs. // // slice must have a type like []elementType. -func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, error) { +func marshalPerCPUValue(slice interface{}, elemLength int) (syscallPtr, error) { sliceType := reflect.TypeOf(slice) if sliceType.Kind() != reflect.Slice { - return internal.Pointer{}, errors.New("per-CPU value requires slice") + return syscallPtr{}, errors.New("per-CPU value requires slice") } possibleCPUs, err := internal.PossibleCPUs() if err != nil { - return internal.Pointer{}, err + return syscallPtr{}, err } sliceValue := reflect.ValueOf(slice) sliceLen := sliceValue.Len() if sliceLen > possibleCPUs { - return internal.Pointer{}, errors.Errorf("per-CPU value exceeds number of CPUs") + return syscallPtr{}, errors.Errorf("per-CPU value exceeds number of CPUs") } alignedElemLength := align(elemLength, 8) @@ -130,14 +123,14 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er elem := sliceValue.Index(i).Interface() elemBytes, err := marshalBytes(elem, elemLength) if err != nil { - return internal.Pointer{}, err + return syscallPtr{}, err } offset := i * alignedElemLength copy(buf[offset:offset+elemLength], elemBytes) } - return internal.NewSlicePointer(buf), nil + return newPtr(unsafe.Pointer(&buf[0])), nil } // unmarshalPerCPUValue decodes a buffer into a slice containing one value per diff --git a/vendor/github.com/cilium/ebpf/prog.go b/vendor/github.com/cilium/ebpf/prog.go index 08ef4fa46d5..03b24fb950a 100644 --- a/vendor/github.com/cilium/ebpf/prog.go +++ b/vendor/github.com/cilium/ebpf/prog.go @@ -4,18 +4,22 @@ import ( "bytes" "fmt" "math" + "path/filepath" "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" "github.com/pkg/errors" ) +var ( + errNotSupported = errors.New("ebpf: not supported by kernel") +) + const ( // Number of bytes to pad the output buffer for BPF_PROG_TEST_RUN. // This is currently the maximum of spare space allocated for SKB @@ -47,11 +51,6 @@ type ProgramSpec struct { Instructions asm.Instructions License string KernelVersion uint32 - - // The BTF associated with this program. Changing Instructions - // will most likely invalidate the contained data, and may - // result in errors when attempting to load it into the kernel. - BTF *btf.Program } // Copy returns a copy of the spec. @@ -74,7 +73,7 @@ type Program struct { // otherwise it is empty. VerifierLog string - fd *internal.FD + fd *bpfFD name string abi ProgramABI } @@ -92,20 +91,7 @@ func NewProgram(spec *ProgramSpec) (*Program, error) { // Loading a program for the first time will perform // feature detection by loading small, temporary programs. func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, error) { - if spec.BTF == nil { - return newProgramWithBTF(spec, nil, opts) - } - - handle, err := btf.NewHandle(btf.ProgramSpec(spec.BTF)) - if err != nil && !btf.IsNotSupported(err) { - return nil, errors.Wrap(err, "can't load BTF") - } - - return newProgramWithBTF(spec, handle, opts) -} - -func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions) (*Program, error) { - attr, err := convertProgramSpec(spec, btf) + attr, err := convertProgramSpec(spec, haveObjName.Result()) if err != nil { return nil, err } @@ -120,51 +106,62 @@ func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions) logBuf = make([]byte, logSize) attr.logLevel = opts.LogLevel attr.logSize = uint32(len(logBuf)) - attr.logBuf = internal.NewSlicePointer(logBuf) + attr.logBuf = newPtr(unsafe.Pointer(&logBuf[0])) } fd, err := bpfProgLoad(attr) if err == nil { prog := newProgram(fd, spec.Name, &ProgramABI{spec.Type}) - prog.VerifierLog = internal.CString(logBuf) + prog.VerifierLog = convertCString(logBuf) return prog, nil } + truncated := errors.Cause(err) == unix.ENOSPC if opts.LogLevel == 0 { // Re-run with the verifier enabled to get better error messages. logBuf = make([]byte, logSize) attr.logLevel = 1 attr.logSize = uint32(len(logBuf)) - attr.logBuf = internal.NewSlicePointer(logBuf) + attr.logBuf = newPtr(unsafe.Pointer(&logBuf[0])) - _, logErr := bpfProgLoad(attr) - err = internal.ErrorWithLog(err, logBuf, logErr) + _, nerr := bpfProgLoad(attr) + truncated = errors.Cause(nerr) == unix.ENOSPC } - return nil, errors.Wrap(err, "can't load program") + logs := convertCString(logBuf) + if truncated { + logs += "\n(truncated...)" + } + + return nil, &loadError{err, logs} } // NewProgramFromFD creates a program from a raw fd. // // You should not use fd after calling this function. -// -// Requires at least Linux 4.11. func NewProgramFromFD(fd int) (*Program, error) { if fd < 0 { return nil, errors.New("invalid fd") } - bpfFd := internal.NewFD(uint32(fd)) + bpfFd := newBPFFD(uint32(fd)) - name, abi, err := newProgramABIFromFd(bpfFd) + info, err := bpfGetProgInfoByFD(bpfFd) if err != nil { - bpfFd.Forget() + bpfFd.forget() return nil, err } - return newProgram(bpfFd, name, abi), nil + var name string + if bpfName := convertCString(info.name[:]); bpfName != "" { + name = bpfName + } else { + name = convertCString(info.tag[:]) + } + + return newProgram(bpfFd, name, newProgramABIFromInfo(info)), nil } -func newProgram(fd *internal.FD, name string, abi *ProgramABI) *Program { +func newProgram(fd *bpfFD, name string, abi *ProgramABI) *Program { return &Program{ name: name, fd: fd, @@ -172,7 +169,7 @@ func newProgram(fd *internal.FD, name string, abi *ProgramABI) *Program { } } -func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr, error) { +func convertProgramSpec(spec *ProgramSpec, includeName bool) (*bpfProgLoadAttr, error) { if len(spec.Instructions) == 0 { return nil, errors.New("Instructions cannot be empty") } @@ -189,12 +186,13 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr bytecode := buf.Bytes() insCount := uint32(len(bytecode) / asm.InstructionSize) + lic := []byte(spec.License) attr := &bpfProgLoadAttr{ progType: spec.Type, expectedAttachType: spec.AttachType, insCount: insCount, - instructions: internal.NewSlicePointer(bytecode), - license: internal.NewStringPointer(spec.License), + instructions: newPtr(unsafe.Pointer(&bytecode[0])), + license: newPtr(unsafe.Pointer(&lic[0])), } name, err := newBPFObjName(spec.Name) @@ -202,38 +200,18 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr return nil, err } - if haveObjName() == nil { + if includeName { attr.progName = name } - if handle != nil && spec.BTF != nil { - attr.progBTFFd = uint32(handle.FD()) - - recSize, bytes, err := btf.ProgramLineInfos(spec.BTF) - if err != nil { - return nil, errors.Wrap(err, "can't get BTF line infos") - } - attr.lineInfoRecSize = recSize - attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize)) - attr.lineInfo = internal.NewSlicePointer(bytes) - - recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF) - if err != nil { - return nil, errors.Wrap(err, "can't get BTF function infos") - } - attr.funcInfoRecSize = recSize - attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize)) - attr.funcInfo = internal.NewSlicePointer(bytes) - } - return attr, nil } func (p *Program) String() string { if p.name != "" { - return fmt.Sprintf("%s(%s)#%v", p.abi.Type, p.name, p.fd) + return fmt.Sprintf("%s(%s)#%s", p.abi.Type, p.name, p.fd) } - return fmt.Sprintf("%s#%v", p.abi.Type, p.fd) + return fmt.Sprintf("%s#%s", p.abi.Type, p.fd) } // ABI gets the ABI of the Program @@ -245,7 +223,7 @@ func (p *Program) ABI() ProgramABI { // // It is invalid to call this function after Close has been called. func (p *Program) FD() int { - fd, err := p.fd.Value() + fd, err := p.fd.value() if err != nil { // Best effort: -1 is the number most likely to be an // invalid file descriptor. @@ -265,7 +243,7 @@ func (p *Program) Clone() (*Program, error) { return nil, nil } - dup, err := p.fd.Dup() + dup, err := p.fd.dup() if err != nil { return nil, errors.Wrap(err, "can't clone program") } @@ -286,7 +264,7 @@ func (p *Program) Close() error { return nil } - return p.fd.Close() + return p.fd.close() } // Test runs the Program in the kernel with the given input and returns the @@ -298,7 +276,7 @@ func (p *Program) Close() error { // This function requires at least Linux 4.12. func (p *Program) Test(in []byte) (uint32, []byte, error) { ret, out, _, err := p.testRun(in, 1) - return ret, out, errors.Wrap(err, "can't test program") + return ret, out, err } // Benchmark runs the Program with the given input for a number of times @@ -310,43 +288,42 @@ func (p *Program) Test(in []byte) (uint32, []byte, error) { // This function requires at least Linux 4.12. func (p *Program) Benchmark(in []byte, repeat int) (uint32, time.Duration, error) { ret, _, total, err := p.testRun(in, repeat) - return ret, total, errors.Wrap(err, "can't benchmark program") + return ret, total, err } -var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() bool { - prog, err := NewProgram(&ProgramSpec{ - Type: SocketFilter, - Instructions: asm.Instructions{ - asm.LoadImm(asm.R0, 0, asm.DWord), - asm.Return(), - }, - License: "MIT", - }) - if err != nil { - // This may be because we lack sufficient permissions, etc. - return false - } - defer prog.Close() +var noProgTestRun = featureTest{ + Fn: func() bool { + prog, err := NewProgram(&ProgramSpec{ + Type: SocketFilter, + Instructions: asm.Instructions{ + asm.LoadImm(asm.R0, 0, asm.DWord), + asm.Return(), + }, + License: "MIT", + }) + if err != nil { + // This may be because we lack sufficient permissions, etc. + return false + } + defer prog.Close() - fd, err := prog.fd.Value() - if err != nil { - return false - } + 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, - dataSizeIn: uint32(len(in)), - dataIn: internal.NewSlicePointer(in), - } + // Programs require at least 14 bytes input + in := make([]byte, 14) + attr := bpfProgTestRunAttr{ + fd: fd, + dataSizeIn: uint32(len(in)), + dataIn: newPtr(unsafe.Pointer(&in[0])), + } - _, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) - - // Check for EINVAL specifically, rather than err != nil since we - // otherwise misdetect due to insufficient permissions. - return errors.Cause(err) != unix.EINVAL -}) + _, err = bpfCall(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + return errors.Cause(err) == unix.EINVAL + }, +} func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration, error) { if uint(repeat) > math.MaxUint32 { @@ -361,8 +338,8 @@ func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration, return 0, nil, 0, fmt.Errorf("input is too long") } - if err := haveProgTestRun(); err != nil { - return 0, nil, 0, err + if noProgTestRun.Result() { + return 0, nil, 0, errNotSupported } // Older kernels ignore the dataSizeOut argument when copying to user space. @@ -372,7 +349,7 @@ func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration, // See https://patchwork.ozlabs.org/cover/1006822/ out := make([]byte, len(in)+outputPad) - fd, err := p.fd.Value() + fd, err := p.fd.value() if err != nil { return 0, nil, 0, err } @@ -381,12 +358,12 @@ func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration, fd: fd, dataSizeIn: uint32(len(in)), dataSizeOut: uint32(len(out)), - dataIn: internal.NewSlicePointer(in), - dataOut: internal.NewSlicePointer(out), + dataIn: newPtr(unsafe.Pointer(&in[0])), + dataOut: newPtr(unsafe.Pointer(&out[0])), repeat: uint32(repeat), } - _, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = bpfCall(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) if err != nil { return 0, nil, 0, errors.Wrap(err, "can't run test") } @@ -415,18 +392,18 @@ func unmarshalProgram(buf []byte) (*Program, error) { return nil, err } - name, abi, err := newProgramABIFromFd(fd) + abi, err := newProgramABIFromFd(fd) if err != nil { - _ = fd.Close() + _ = fd.close() return nil, err } - return newProgram(fd, name, abi), nil + return newProgram(fd, "", abi), nil } // MarshalBinary implements BinaryMarshaler. func (p *Program) MarshalBinary() ([]byte, error) { - value, err := p.fd.Value() + value, err := p.fd.value() if err != nil { return nil, err } @@ -442,7 +419,7 @@ func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error { return errors.New("invalid fd") } - pfd, err := p.fd.Value() + pfd, err := p.fd.value() if err != nil { return err } @@ -463,7 +440,7 @@ func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error { return errors.New("invalid fd") } - pfd, err := p.fd.Value() + pfd, err := p.fd.value() if err != nil { return err } @@ -480,20 +457,31 @@ func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error { // LoadPinnedProgram loads a Program from a BPF file. // -// Requires at least Linux 4.11. +// Requires at least Linux 4.13, use LoadPinnedProgramExplicit on +// earlier versions. func LoadPinnedProgram(fileName string) (*Program, error) { fd, err := bpfGetObject(fileName) if err != nil { return nil, err } - name, abi, err := newProgramABIFromFd(fd) + abi, err := newProgramABIFromFd(fd) if err != nil { - _ = fd.Close() - return nil, errors.Wrapf(err, "can't get ABI for %s", fileName) + _ = fd.close() + return nil, err } - return newProgram(fd, name, abi), nil + return newProgram(fd, filepath.Base(fileName), abi), nil +} + +// LoadPinnedProgramExplicit loads a program with explicit parameters. +func LoadPinnedProgramExplicit(fileName string, abi *ProgramABI) (*Program, error) { + fd, err := bpfGetObject(fileName) + if err != nil { + return nil, err + } + + return newProgram(fd, filepath.Base(fileName), abi), nil } // SanitizeName replaces all invalid characters in name. @@ -512,9 +500,24 @@ func SanitizeName(name string, replacement rune) string { }, name) } +type loadError struct { + cause error + verifierLog string +} + +func (le *loadError) Error() string { + if le.verifierLog == "" { + return fmt.Sprintf("failed to load program: %s", le.cause) + } + return fmt.Sprintf("failed to load program: %s: %s", le.cause, le.verifierLog) +} + +func (le *loadError) Cause() error { + return le.cause +} + // IsNotSupported returns true if an error occurred because // the kernel does not have support for a specific feature. func IsNotSupported(err error) bool { - _, notSupported := errors.Cause(err).(*internal.UnsupportedFeatureError) - return notSupported + return errors.Cause(err) == errNotSupported } diff --git a/vendor/github.com/cilium/ebpf/internal/ptr_32_be.go b/vendor/github.com/cilium/ebpf/ptr_32_be.go similarity index 59% rename from vendor/github.com/cilium/ebpf/internal/ptr_32_be.go rename to vendor/github.com/cilium/ebpf/ptr_32_be.go index a56fbcc8e01..775774436a1 100644 --- a/vendor/github.com/cilium/ebpf/internal/ptr_32_be.go +++ b/vendor/github.com/cilium/ebpf/ptr_32_be.go @@ -1,14 +1,14 @@ // +build armbe mips mips64p32 -package internal +package ebpf import ( "unsafe" ) -// Pointer wraps an unsafe.Pointer to be 64bit to +// ptr wraps an unsafe.Pointer to be 64bit to // conform to the syscall specification. -type Pointer struct { +type syscallPtr struct { pad uint32 ptr unsafe.Pointer } diff --git a/vendor/github.com/cilium/ebpf/internal/ptr_32_le.go b/vendor/github.com/cilium/ebpf/ptr_32_le.go similarity index 61% rename from vendor/github.com/cilium/ebpf/internal/ptr_32_le.go rename to vendor/github.com/cilium/ebpf/ptr_32_le.go index be2ecfca731..14b805e92cc 100644 --- a/vendor/github.com/cilium/ebpf/internal/ptr_32_le.go +++ b/vendor/github.com/cilium/ebpf/ptr_32_le.go @@ -1,14 +1,14 @@ // +build 386 amd64p32 arm mipsle mips64p32le -package internal +package ebpf import ( "unsafe" ) -// Pointer wraps an unsafe.Pointer to be 64bit to +// ptr wraps an unsafe.Pointer to be 64bit to // conform to the syscall specification. -type Pointer struct { +type syscallPtr struct { ptr unsafe.Pointer pad uint32 } diff --git a/vendor/github.com/cilium/ebpf/internal/ptr_64.go b/vendor/github.com/cilium/ebpf/ptr_64.go similarity index 65% rename from vendor/github.com/cilium/ebpf/internal/ptr_64.go rename to vendor/github.com/cilium/ebpf/ptr_64.go index 69452dceb9a..c897d7273bc 100644 --- a/vendor/github.com/cilium/ebpf/internal/ptr_64.go +++ b/vendor/github.com/cilium/ebpf/ptr_64.go @@ -1,14 +1,14 @@ // +build !386,!amd64p32,!arm,!mipsle,!mips64p32le // +build !armbe,!mips,!mips64p32 -package internal +package ebpf import ( "unsafe" ) -// Pointer wraps an unsafe.Pointer to be 64bit to +// ptr wraps an unsafe.Pointer to be 64bit to // conform to the syscall specification. -type Pointer struct { +type syscallPtr struct { ptr unsafe.Pointer } diff --git a/vendor/github.com/cilium/ebpf/run-tests.sh b/vendor/github.com/cilium/ebpf/run-tests.sh index 30f9744073d..f92d489932d 100644 --- a/vendor/github.com/cilium/ebpf/run-tests.sh +++ b/vendor/github.com/cilium/ebpf/run-tests.sh @@ -12,13 +12,10 @@ if [[ "${1:-}" = "--in-vm" ]]; then mount -t bpf bpf /sys/fs/bpf export CGO_ENABLED=0 - export GOFLAGS=-mod=readonly - export GOPROXY=file:///run/go-proxy - export GOCACHE=/run/go-cache export HOME="$home" echo Running tests... - /usr/local/bin/go test -coverprofile="$1/coverage.txt" -covermode=atomic -v ./... + /usr/local/bin/go test -mod=vendor -coverprofile="$1/coverage.txt" -covermode=atomic -v ./... touch "$1/success" exit 0 fi @@ -28,7 +25,7 @@ export GO111MODULE=on # Pull all dependencies, so that we can run tests without the # vm having network access. -go mod download +go mod vendor # Use sudo if /dev/kvm isn't accessible by the current user. sudo="" @@ -53,11 +50,7 @@ test -e "${tmp_dir}/${kernel}" || { } echo Testing on ${kernel_version} -$sudo virtme-run --kimg "${tmp_dir}/${kernel}" --memory 256M --pwd \ - --rwdir=/run/output="${output}" \ - --rodir=/run/go-proxy="$(go env GOPATH)/pkg/mod/cache/download" \ - --rwdir=/run/go-cache="$(go env GOCACHE)" \ - --script-sh "$(realpath "$0") --in-vm /run/output" --qemu-opts -smp 2 +$sudo virtme-run --kimg "${tmp_dir}/${kernel}" --memory 256M --pwd --rwdir=/run/output="${output}" --script-sh "$(realpath "$0") --in-vm /run/output" if [[ ! -e "${output}/success" ]]; then echo "Test failed on ${kernel_version}" diff --git a/vendor/github.com/cilium/ebpf/syscalls.go b/vendor/github.com/cilium/ebpf/syscalls.go index 70f8c127ab4..68abd3bc675 100644 --- a/vendor/github.com/cilium/ebpf/syscalls.go +++ b/vendor/github.com/cilium/ebpf/syscalls.go @@ -1,17 +1,71 @@ package ebpf import ( + "bytes" "path/filepath" + "runtime" + "strconv" "strings" "unsafe" - "github.com/cilium/ebpf/internal" - "github.com/cilium/ebpf/internal/btf" "github.com/cilium/ebpf/internal/unix" "github.com/pkg/errors" ) +var errClosedFd = errors.New("use of closed file descriptor") + +type bpfFD struct { + raw int64 +} + +func newBPFFD(value uint32) *bpfFD { + fd := &bpfFD{int64(value)} + runtime.SetFinalizer(fd, (*bpfFD).close) + return fd +} + +func (fd *bpfFD) String() string { + return strconv.FormatInt(fd.raw, 10) +} + +func (fd *bpfFD) value() (uint32, error) { + if fd.raw < 0 { + return 0, errClosedFd + } + + return uint32(fd.raw), nil +} + +func (fd *bpfFD) close() error { + if fd.raw < 0 { + return nil + } + + value := int(fd.raw) + fd.raw = -1 + + fd.forget() + return unix.Close(value) +} + +func (fd *bpfFD) forget() { + runtime.SetFinalizer(fd, nil) +} + +func (fd *bpfFD) dup() (*bpfFD, error) { + if fd.raw < 0 { + return nil, errClosedFd + } + + dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0) + if err != nil { + return nil, errors.Wrap(err, "can't dup fd") + } + + return newBPFFD(uint32(dup)), nil +} + // bpfObjName is a null-terminated string made up of // 'A-Za-z0-9_' characters. type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte @@ -44,25 +98,21 @@ func invalidBPFObjNameChar(char rune) bool { } type bpfMapCreateAttr struct { - mapType MapType - keySize uint32 - valueSize uint32 - maxEntries uint32 - flags uint32 - innerMapFd uint32 // since 4.12 56f668dfe00d - numaNode uint32 // since 4.14 96eabe7a40aa - mapName bpfObjName // since 4.15 ad5b177bd73f - mapIfIndex uint32 - btfFd uint32 - btfKeyTypeID btf.TypeID - btfValueTypeID btf.TypeID + mapType MapType + keySize uint32 + valueSize uint32 + maxEntries uint32 + flags uint32 + innerMapFd uint32 // since 4.12 56f668dfe00d + numaNode uint32 // since 4.14 96eabe7a40aa + mapName bpfObjName // since 4.15 ad5b177bd73f } type bpfMapOpAttr struct { mapFd uint32 padding uint32 - key internal.Pointer - value internal.Pointer + key syscallPtr + value syscallPtr flags uint64 } @@ -77,7 +127,7 @@ type bpfMapInfo struct { } type bpfPinObjAttr struct { - fileName internal.Pointer + fileName syscallPtr fd uint32 padding uint32 } @@ -85,23 +135,16 @@ type bpfPinObjAttr struct { type bpfProgLoadAttr struct { progType ProgramType insCount uint32 - instructions internal.Pointer - license internal.Pointer + instructions syscallPtr + license syscallPtr logLevel uint32 logSize uint32 - logBuf internal.Pointer + logBuf syscallPtr kernelVersion uint32 // since 4.1 2541517c32be progFlags uint32 // since 4.11 e07b98d9bffe progName bpfObjName // since 4.15 067cae47771c progIfIndex uint32 // since 4.15 1f6f4cb7ba21 expectedAttachType AttachType // since 4.17 5e43f899b03a - progBTFFd uint32 - funcInfoRecSize uint32 - funcInfo internal.Pointer - funcInfoCnt uint32 - lineInfoRecSize uint32 - lineInfo internal.Pointer - lineInfoCnt uint32 } type bpfProgInfo struct { @@ -110,12 +153,12 @@ type bpfProgInfo struct { tag [unix.BPF_TAG_SIZE]byte jitedLen uint32 xlatedLen uint32 - jited internal.Pointer - xlated internal.Pointer + jited syscallPtr + xlated syscallPtr loadTime uint64 // since 4.15 cb4d2b3f03d8 createdByUID uint32 nrMapIDs uint32 - mapIds internal.Pointer + mapIds syscallPtr name bpfObjName } @@ -124,8 +167,8 @@ type bpfProgTestRunAttr struct { retval uint32 dataSizeIn uint32 dataSizeOut uint32 - dataIn internal.Pointer - dataOut internal.Pointer + dataIn syscallPtr + dataOut syscallPtr repeat uint32 duration uint32 } @@ -140,7 +183,7 @@ type bpfProgAlterAttr struct { type bpfObjGetInfoByFDAttr struct { fd uint32 infoLen uint32 - info internal.Pointer // May be either bpfMapInfo or bpfProgInfo + info syscallPtr // May be either bpfMapInfo or bpfProgInfo } type bpfGetFDByIDAttr struct { @@ -148,9 +191,13 @@ type bpfGetFDByIDAttr struct { next uint32 } -func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) { +func newPtr(ptr unsafe.Pointer) syscallPtr { + return syscallPtr{ptr: ptr} +} + +func bpfProgLoad(attr *bpfProgLoadAttr) (*bpfFD, error) { for { - fd, err := internal.BPF(_ProgLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) + fd, err := bpfCall(_ProgLoad, 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 { @@ -161,54 +208,26 @@ func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) { return nil, err } - return internal.NewFD(uint32(fd)), nil + return newBPFFD(uint32(fd)), nil } } func bpfProgAlter(cmd int, attr *bpfProgAlterAttr) error { - _, err := internal.BPF(cmd, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) + _, err := bpfCall(cmd, 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)) +func bpfMapCreate(attr *bpfMapCreateAttr) (*bpfFD, error) { + fd, err := bpfCall(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) if err != nil { return nil, err } - return internal.NewFD(uint32(fd)), nil + return newBPFFD(uint32(fd)), nil } -var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool { - inner, err := bpfMapCreate(&bpfMapCreateAttr{ - mapType: Array, - keySize: 4, - valueSize: 4, - maxEntries: 1, - }) - if err != nil { - return false - } - defer inner.Close() - - innerFd, _ := inner.Value() - nested, err := bpfMapCreate(&bpfMapCreateAttr{ - mapType: ArrayOfMaps, - keySize: 4, - valueSize: 4, - maxEntries: 1, - innerMapFd: innerFd, - }) - if err != nil { - return false - } - - _ = nested.Close() - return true -}) - -func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error { - fd, err := m.Value() +func bpfMapLookupElem(m *bpfFD, key, valueOut syscallPtr) error { + fd, err := m.value() if err != nil { return err } @@ -218,27 +237,12 @@ 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 = bpfCall(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return err } -func bpfMapLookupAndDelete(m *internal.FD, key, valueOut internal.Pointer) error { - fd, err := m.Value() - if err != nil { - return err - } - - attr := bpfMapOpAttr{ - mapFd: fd, - key: key, - value: valueOut, - } - _, err = internal.BPF(_MapLookupAndDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) - return err -} - -func bpfMapUpdateElem(m *internal.FD, key, valueOut internal.Pointer, flags uint64) error { - fd, err := m.Value() +func bpfMapUpdateElem(m *bpfFD, key, valueOut syscallPtr, flags uint64) error { + fd, err := m.value() if err != nil { return err } @@ -249,12 +253,12 @@ 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 = bpfCall(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return err } -func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error { - fd, err := m.Value() +func bpfMapDeleteElem(m *bpfFD, key syscallPtr) error { + fd, err := m.value() if err != nil { return err } @@ -263,12 +267,12 @@ func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error { mapFd: fd, key: key, } - _, err = internal.BPF(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + _, err = bpfCall(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return err } -func bpfMapGetNextKey(m *internal.FD, key, nextKeyOut internal.Pointer) error { - fd, err := m.Value() +func bpfMapGetNextKey(m *bpfFD, key, nextKeyOut syscallPtr) error { + fd, err := m.value() if err != nil { return err } @@ -278,13 +282,13 @@ 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 = bpfCall(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) return err } const bpfFSType = 0xcafe4a11 -func bpfPinObject(fileName string, fd *internal.FD) error { +func bpfPinObject(fileName string, fd *bpfFD) error { dirName := filepath.Dir(fileName) var statfs unix.Statfs_t if err := unix.Statfs(dirName, &statfs); err != nil { @@ -294,30 +298,30 @@ func bpfPinObject(fileName string, fd *internal.FD) error { return errors.Errorf("%s is not on a bpf filesystem", fileName) } - value, err := fd.Value() + value, err := fd.value() if err != nil { return err } - _, err = internal.BPF(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{ - fileName: internal.NewStringPointer(fileName), + _, err = bpfCall(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{ + fileName: newPtr(unsafe.Pointer(&[]byte(fileName)[0])), fd: value, }), 16) return errors.Wrapf(err, "pin object %s", fileName) } -func bpfGetObject(fileName string) (*internal.FD, error) { - ptr, err := internal.BPF(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{ - fileName: internal.NewStringPointer(fileName), +func bpfGetObject(fileName string) (*bpfFD, error) { + ptr, err := bpfCall(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{ + fileName: newPtr(unsafe.Pointer(&[]byte(fileName)[0])), }), 16) if err != nil { return nil, errors.Wrapf(err, "get object %s", fileName) } - return internal.NewFD(uint32(ptr)), nil + return newBPFFD(uint32(ptr)), nil } -func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) error { - value, err := fd.Value() +func bpfGetObjectInfoByFD(fd *bpfFD, info unsafe.Pointer, size uintptr) error { + value, err := fd.value() if err != nil { return err } @@ -326,69 +330,91 @@ func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) er attr := bpfObjGetInfoByFDAttr{ fd: value, infoLen: uint32(size), - info: internal.NewPointer(info), + info: newPtr(info), } - _, err = internal.BPF(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) - return errors.Wrapf(err, "fd %d", fd) + _, err = bpfCall(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + return errors.Wrapf(err, "fd %d", value) } -func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) { +func bpfGetProgInfoByFD(fd *bpfFD) (*bpfProgInfo, error) { var info bpfProgInfo err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)) return &info, errors.Wrap(err, "can't get program info") } -func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) { +func bpfGetMapInfoByFD(fd *bpfFD) (*bpfMapInfo, error) { var info bpfMapInfo err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)) - return &info, errors.Wrap(err, "can't get map info") + return &info, errors.Wrap(err, "can't get map info:") } -var haveObjName = internal.FeatureTest("object names", "4.15", func() bool { - name, err := newBPFObjName("feature_test") - if err != nil { - // This really is a fatal error, but it should be caught - // by the unit tests not working. - return false - } +var haveObjName = featureTest{ + Fn: func() bool { + name, err := newBPFObjName("feature_test") + if err != nil { + // This really is a fatal error, but it should be caught + // by the unit tests not working. + return false + } - attr := bpfMapCreateAttr{ - mapType: Array, - keySize: 4, - valueSize: 4, - maxEntries: 1, - mapName: name, - } + attr := bpfMapCreateAttr{ + mapType: Array, + keySize: 4, + valueSize: 4, + maxEntries: 1, + mapName: name, + } - fd, err := bpfMapCreate(&attr) - if err != nil { - return false - } + fd, err := bpfMapCreate(&attr) + if err != nil { + return false + } - _ = fd.Close() - return true -}) + _ = fd.close() + return true + }, +} -func bpfGetMapFDByID(id uint32) (*internal.FD, error) { +func bpfGetMapFDByID(id uint32) (*bpfFD, error) { // available from 4.13 attr := bpfGetFDByIDAttr{ id: id, } - ptr, err := internal.BPF(_MapGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + ptr, err := bpfCall(_MapGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) if err != nil { return nil, errors.Wrapf(err, "can't get fd for map id %d", id) } - return internal.NewFD(uint32(ptr)), nil + return newBPFFD(uint32(ptr)), nil } -func bpfGetProgramFDByID(id uint32) (*internal.FD, error) { +func bpfGetProgramFDByID(id uint32) (*bpfFD, error) { // available from 4.13 attr := bpfGetFDByIDAttr{ id: id, } - ptr, err := internal.BPF(_ProgGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) + ptr, err := bpfCall(_ProgGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) if err != nil { return nil, errors.Wrapf(err, "can't get fd for program id %d", id) } - return internal.NewFD(uint32(ptr)), nil + return newBPFFD(uint32(ptr)), nil +} + +func bpfCall(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) { + r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size) + runtime.KeepAlive(attr) + + var err error + if errNo != 0 { + err = errNo + } + + return r1, err +} + +func convertCString(in []byte) string { + inLen := bytes.IndexByte(in, 0) + if inLen == -1 { + return "" + } + return string(in[:inLen]) } diff --git a/vendor/github.com/cilium/ebpf/types.go b/vendor/github.com/cilium/ebpf/types.go index 6a0228dc79f..0daf9a71527 100644 --- a/vendor/github.com/cilium/ebpf/types.go +++ b/vendor/github.com/cilium/ebpf/types.go @@ -57,30 +57,6 @@ const ( // HashOfMaps - Each item in the hash map is another map. The inner map mustn't be a map of maps // itself. HashOfMaps - // DevMap - Specialized map to store references to network devices. - DevMap - // SockMap - Specialized map to store references to sockets. - SockMap - // CPUMap - Specialized map to store references to CPUs. - CPUMap - // XSKMap - Specialized map for XDP programs to store references to open sockets. - XSKMap - // SockHash - Specialized hash to store references to sockets. - SockHash - // CGroupStorage - Special map for CGroups. - CGroupStorage - // ReusePortSockArray - Specialized map to store references to sockets that can be reused. - ReusePortSockArray - // PerCPUCGroupStorage - Special per CPU map for CGroups. - PerCPUCGroupStorage - // Queue - FIFO storage for BPF programs. - Queue - // Stack - LIFO storage for BPF programs. - Stack - // SkStorage - Specialized map for local storage at SK for BPF programs. - SkStorage - // DevMapHash - Hash-based indexing scheme for references to network devices. - DevMapHash ) // hasPerCPUValue returns true if the Map stores a value per CPU. @@ -108,13 +84,6 @@ const ( _ProgGetFDByID _MapGetFDByID _ObjGetInfoByFD - _ProgQuery - _RawTracepointOpen - _BTFLoad - _BTFGetFDByID - _TaskFDQuery - _MapLookupAndDeleteElem - _MapFreeze ) const ( @@ -180,8 +149,6 @@ const ( RawTracepointWritable // CGroupSockopt program CGroupSockopt - // Tracing program - Tracing ) // AttachType of the eBPF program, needed to differentiate allowed context accesses in @@ -216,9 +183,6 @@ const ( AttachCGroupUDP6Recvmsg AttachCGroupGetsockopt AttachCGroupSetsockopt - AttachTraceRawTp - AttachTraceFEntry - AttachTraceFExit ) // 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..4813437ec2a 100644 --- a/vendor/github.com/cilium/ebpf/types_string.go +++ b/vendor/github.com/cilium/ebpf/types_string.go @@ -22,23 +22,11 @@ func _() { _ = x[LPMTrie-11] _ = x[ArrayOfMaps-12] _ = x[HashOfMaps-13] - _ = x[DevMap-14] - _ = x[SockMap-15] - _ = x[CPUMap-16] - _ = x[XSKMap-17] - _ = x[SockHash-18] - _ = x[CGroupStorage-19] - _ = x[ReusePortSockArray-20] - _ = x[PerCPUCGroupStorage-21] - _ = x[Queue-22] - _ = x[Stack-23] - _ = x[SkStorage-24] - _ = x[DevMapHash-25] } -const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHash" +const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMaps" -var _MapType_index = [...]uint8{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248} +var _MapType_index = [...]uint8{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136} func (i MapType) String() string { if i >= MapType(len(_MapType_index)-1) { @@ -76,12 +64,11 @@ func _() { _ = x[CGroupSysctl-23] _ = x[RawTracepointWritable-24] _ = x[CGroupSockopt-25] - _ = x[Tracing-26] } -const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracing" +const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockopt" -var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258, 265} +var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258} func (i ProgramType) String() string { if i >= ProgramType(len(_ProgramType_index)-1) { diff --git a/vendor/modules.txt b/vendor/modules.txt index f648cf382ab..96a5c3ae8db 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -155,11 +155,10 @@ github.com/chai2010/gettext-go/gettext/plural github.com/chai2010/gettext-go/gettext/po # github.com/checkpoint-restore/go-criu v0.0.0-20181120144056-17b0214f6c48 => github.com/checkpoint-restore/go-criu v0.0.0-20181120144056-17b0214f6c48 github.com/checkpoint-restore/go-criu/rpc -# github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3 => github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3 +# github.com/cilium/ebpf v0.0.0-20191025125908-95b36a581eed => github.com/cilium/ebpf v0.0.0-20191025125908-95b36a581eed github.com/cilium/ebpf github.com/cilium/ebpf/asm github.com/cilium/ebpf/internal -github.com/cilium/ebpf/internal/btf github.com/cilium/ebpf/internal/unix # github.com/client9/misspell v0.3.4 => github.com/client9/misspell v0.3.4 github.com/client9/misspell