diff --git a/go.mod b/go.mod index 855cb5a3cf1..17719a9b268 100644 --- a/go.mod +++ b/go.mod @@ -206,7 +206,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-20191025125908-95b36a581eed + github.com/cilium/ebpf => github.com/cilium/ebpf v0.0.0-20191113100448-d9fb101ca1fb 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 969b524e598..901e9c18e61 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,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-20191025125908-95b36a581eed h1:/UgmF+cZTm9kp4uJ122y/9cVhczNJCgAgAeH2FfzPeg= -github.com/cilium/ebpf v0.0.0-20191025125908-95b36a581eed/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20191113100448-d9fb101ca1fb h1:bQ0NJ9dAB8vsw7ffajBDX/7Wr64BdLWeJkYY36UkeRY= +github.com/cilium/ebpf v0.0.0-20191113100448-d9fb101ca1fb/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/abi.go b/vendor/github.com/cilium/ebpf/abi.go index 999b8cc8597..e2ceccc4ee1 100644 --- a/vendor/github.com/cilium/ebpf/abi.go +++ b/vendor/github.com/cilium/ebpf/abi.go @@ -1,143 +1,88 @@ package ebpf import ( + "bufio" + "bytes" + "fmt" + "io" + "os" + "syscall" + "github.com/pkg/errors" ) -// 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. +// MapABI are the attributes of a Map which are available across all supported kernels. type MapABI struct { Type MapType KeySize uint32 ValueSize uint32 MaxEntries uint32 - InnerMap *MapABI + Flags uint32 } 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, - inner, + spec.Flags, } } -func newMapABIFromFd(fd *bpfFD) (*MapABI, error) { +func newMapABIFromFd(fd *bpfFD) (string, *MapABI, error) { info, err := bpfGetMapInfoByFD(fd) if err != nil { - return nil, err + if errors.Cause(err) == syscall.EINVAL { + abi, err := newMapABIFromProc(fd) + return "", abi, err + } + return "", nil, err } - mapType := MapType(info.mapType) - if mapType == ArrayOfMaps || mapType == HashOfMaps { - return nil, errors.New("can't get map info for nested maps") - } - - return &MapABI{ - mapType, + return "", &MapABI{ + MapType(info.mapType), info.keySize, info.valueSize, info.maxEntries, - nil, + info.flags, }, nil } -// 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 newMapABIFromProc(fd *bpfFD) (*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 } -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) +// 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 } - 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. +// ProgramABI are the attributes of a Program which are available across all supported kernels. type ProgramABI struct { Type ProgramType } @@ -148,36 +93,102 @@ func newProgramABIFromSpec(spec *ProgramSpec) *ProgramABI { } } -func newProgramABIFromFd(fd *bpfFD) (*ProgramABI, error) { +func newProgramABIFromFd(fd *bpfFD) (string, *ProgramABI, error) { info, err := bpfGetProgInfoByFD(fd) if err != nil { - return nil, err + if errors.Cause(err) == syscall.EINVAL { + return newProgramABIFromProc(fd) + } + + return "", nil, err } - return newProgramABIFromInfo(info), nil -} + var name string + if bpfName := convertCString(info.name[:]); bpfName != "" { + name = bpfName + } else { + name = convertCString(info.tag[:]) + } -func newProgramABIFromInfo(info *bpfProgInfo) *ProgramABI { - return &ProgramABI{ + return name, &ProgramABI{ Type: ProgramType(info.progType), - } + }, nil } -// 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) +func newProgramABIFromProc(fd *bpfFD) (string, *ProgramABI, error) { + var ( + abi ProgramABI + name string + ) + + err := scanFdInfo(fd, map[string]interface{}{ + "prog_type": &abi.Type, + "prog_tag": &name, + }) + if err != nil { + return "", nil, err + } + + return name, &abi, nil +} + +func scanFdInfo(fd *bpfFD, 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()) +} + +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 errors.Errorf("parsed %d instead of %d fields", scanned, len(fields)) } return nil } -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) +// 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 } - return nil } 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 49c6be5b0e6..003907b0228 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go @@ -30,6 +30,7 @@ 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 diff --git a/vendor/github.com/cilium/ebpf/map.go b/vendor/github.com/cilium/ebpf/map.go index 028a9135202..1570291f0a6 100644 --- a/vendor/github.com/cilium/ebpf/map.go +++ b/vendor/github.com/cilium/ebpf/map.go @@ -49,8 +49,9 @@ func (ms *MapSpec) Copy() *MapSpec { // Implement encoding.BinaryMarshaler or encoding.BinaryUnmarshaler // if you require custom encoding. type Map struct { - fd *bpfFD - abi MapABI + name string + fd *bpfFD + abi MapABI // Per CPU maps return values larger than the size in the spec fullValueSize int } @@ -64,12 +65,12 @@ func NewMapFromFD(fd int) (*Map, error) { } bpfFd := newBPFFD(uint32(fd)) - abi, err := newMapABIFromFd(bpfFd) + name, abi, err := newMapABIFromFd(bpfFd) if err != nil { bpfFd.forget() return nil, err } - return newMap(bpfFd, abi) + return newMap(bpfFd, name, abi) } // NewMap creates a new Map. @@ -155,11 +156,12 @@ func createMap(spec *MapSpec, inner *bpfFD) (*Map, error) { return nil, errors.Wrap(err, "map create") } - return newMap(fd, newMapABIFromSpec(spec)) + return newMap(fd, spec.Name, newMapABIFromSpec(spec)) } -func newMap(fd *bpfFD, abi *MapABI) (*Map, error) { +func newMap(fd *bpfFD, name string, abi *MapABI) (*Map, error) { m := &Map{ + name, fd, *abi, int(abi.ValueSize), @@ -179,7 +181,10 @@ func newMap(fd *bpfFD, abi *MapABI) (*Map, error) { } func (m *Map) String() string { - return fmt.Sprintf("%s#%d", m.abi.Type, m.fd) + 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) } // ABI gets the ABI of the Map @@ -424,7 +429,7 @@ func (m *Map) Clone() (*Map, error) { return nil, errors.Wrap(err, "can't clone map") } - return newMap(dup, &m.abi) + return newMap(dup, m.name, &m.abi) } // Pin persists the map past the lifetime of the process that created it. @@ -436,19 +441,19 @@ func (m *Map) Pin(fileName string) error { // LoadPinnedMap load a Map from a BPF file. // -// Requires at least Linux 4.13, and is not compatible with -// nested maps. Use LoadPinnedMapExplicit in these situations. +// The function 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 } - abi, err := newMapABIFromFd(fd) + name, abi, err := newMapABIFromFd(fd) if err != nil { _ = fd.close() return nil, err } - return newMap(fd, abi) + return newMap(fd, name, abi) } // LoadPinnedMapExplicit loads a map with explicit parameters. @@ -457,7 +462,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) { @@ -473,13 +478,13 @@ func unmarshalMap(buf []byte) (*Map, error) { return nil, err } - abi, err := newMapABIFromFd(fd) + name, abi, err := newMapABIFromFd(fd) if err != nil { _ = fd.close() return nil, err } - return newMap(fd, abi) + return newMap(fd, name, abi) } // MarshalBinary implements BinaryMarshaler. diff --git a/vendor/github.com/cilium/ebpf/prog.go b/vendor/github.com/cilium/ebpf/prog.go index 03b24fb950a..91b5b1b1530 100644 --- a/vendor/github.com/cilium/ebpf/prog.go +++ b/vendor/github.com/cilium/ebpf/prog.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "math" - "path/filepath" "strings" "time" "unsafe" @@ -145,20 +144,13 @@ func NewProgramFromFD(fd int) (*Program, error) { } bpfFd := newBPFFD(uint32(fd)) - info, err := bpfGetProgInfoByFD(bpfFd) + name, abi, err := newProgramABIFromFd(bpfFd) if err != nil { bpfFd.forget() return nil, err } - var name string - if bpfName := convertCString(info.name[:]); bpfName != "" { - name = bpfName - } else { - name = convertCString(info.tag[:]) - } - - return newProgram(bpfFd, name, newProgramABIFromInfo(info)), nil + return newProgram(bpfFd, name, abi), nil } func newProgram(fd *bpfFD, name string, abi *ProgramABI) *Program { @@ -209,9 +201,9 @@ func convertProgramSpec(spec *ProgramSpec, includeName bool) (*bpfProgLoadAttr, func (p *Program) String() string { if p.name != "" { - return fmt.Sprintf("%s(%s)#%s", p.abi.Type, p.name, p.fd) + return fmt.Sprintf("%s(%s)#%v", p.abi.Type, p.name, p.fd) } - return fmt.Sprintf("%s#%s", p.abi.Type, p.fd) + return fmt.Sprintf("%s#%v", p.abi.Type, p.fd) } // ABI gets the ABI of the Program @@ -392,13 +384,13 @@ func unmarshalProgram(buf []byte) (*Program, error) { return nil, err } - abi, err := newProgramABIFromFd(fd) + name, abi, err := newProgramABIFromFd(fd) if err != nil { _ = fd.close() return nil, err } - return newProgram(fd, "", abi), nil + return newProgram(fd, name, abi), nil } // MarshalBinary implements BinaryMarshaler. @@ -456,32 +448,19 @@ func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error { } // LoadPinnedProgram loads a Program from a BPF file. -// -// 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 } - abi, err := newProgramABIFromFd(fd) + name, abi, err := newProgramABIFromFd(fd) if err != nil { _ = fd.close() return nil, err } - 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 + return newProgram(fd, name, abi), nil } // SanitizeName replaces all invalid characters in name. diff --git a/vendor/github.com/cilium/ebpf/run-tests.sh b/vendor/github.com/cilium/ebpf/run-tests.sh index f92d489932d..9859e26dca5 100644 --- a/vendor/github.com/cilium/ebpf/run-tests.sh +++ b/vendor/github.com/cilium/ebpf/run-tests.sh @@ -50,7 +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}" --script-sh "$(realpath "$0") --in-vm /run/output" +$sudo virtme-run --kimg "${tmp_dir}/${kernel}" --memory 256M --pwd --rwdir=/run/output="${output}" --script-sh "$(realpath "$0") --in-vm /run/output" --qemu-opts -smp 2 if [[ ! -e "${output}/success" ]]; then echo "Test failed on ${kernel_version}" diff --git a/vendor/modules.txt b/vendor/modules.txt index 6f7b1f65db0..f8d77c5e9dd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -155,7 +155,7 @@ github.com/chai2010/gettext-go/gettext/plural github.com/chai2010/gettext-go/gettext/po # github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b => 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-20191113100448-d9fb101ca1fb => github.com/cilium/ebpf v0.0.0-20191025125908-95b36a581eed +# github.com/cilium/ebpf v0.0.0-20191113100448-d9fb101ca1fb => github.com/cilium/ebpf v0.0.0-20191113100448-d9fb101ca1fb github.com/cilium/ebpf github.com/cilium/ebpf/asm github.com/cilium/ebpf/internal