File 0002-CVE-2022-29162-Bump-runc-dependency-to-1.1.2.patch of Package kubevirt.26844
From 660ca5e367ed4f7eb0f35c903bac5815bb03f297 Mon Sep 17 00:00:00 2001
From: orenc1 <ocohen@redhat.com>
Date: Thu, 14 Jul 2022 19:44:23 +0300
Subject: [PATCH 2/3] [CVE-2022-29162] Bump runc dependency to 1.1.2
CVE-2022-29162 has been found in runc version that is currently being used. Bumping it to v1.1.2 as suggested in:
GHSA-f3fp-gc8g-vw66
runc v1.1.2 introduced some changes:
rootless flag is now embedded in the Cgroup config struct
runc_fs.NewManager() now returns also an error value.
This PR accommodates these updates.
Signed-off-by: orenc1 <ocohen@redhat.com>
---
cmd/virt-chroot/cgroup.go | 18 +-
go.mod | 12 +-
go.sum | 23 +-
pkg/virt-handler/cgroup/cgroup.go | 5 +-
pkg/virt-handler/cgroup/cgroup_v1_manager.go | 13 +-
pkg/virt-handler/cgroup/cgroup_v2_manager.go | 10 +-
vendor/github.com/cilium/ebpf/.gitignore | 1 +
vendor/github.com/cilium/ebpf/.golangci.yaml | 1 -
vendor/github.com/cilium/ebpf/ARCHITECTURE.md | 4 +-
vendor/github.com/cilium/ebpf/BUILD.bazel | 1 +
vendor/github.com/cilium/ebpf/CONTRIBUTING.md | 4 +-
vendor/github.com/cilium/ebpf/Makefile | 5 +-
vendor/github.com/cilium/ebpf/README.md | 62 ++-
vendor/github.com/cilium/ebpf/asm/func.go | 6 +
.../github.com/cilium/ebpf/asm/func_string.go | 10 +-
.../github.com/cilium/ebpf/asm/instruction.go | 5 +
.../cilium/ebpf/attachtype_string.go | 65 +++
vendor/github.com/cilium/ebpf/collection.go | 508 ++++++++++--------
vendor/github.com/cilium/ebpf/elf_reader.go | 180 ++++++-
.../github.com/cilium/ebpf/elf_reader_fuzz.go | 1 +
vendor/github.com/cilium/ebpf/info.go | 36 +-
.../cilium/ebpf/internal/BUILD.bazel | 1 +
.../github.com/cilium/ebpf/internal/align.go | 6 +
.../cilium/ebpf/internal/btf/BUILD.bazel | 2 +
.../cilium/ebpf/internal/btf/btf.go | 293 +++++-----
.../cilium/ebpf/internal/btf/btf_types.go | 11 +-
.../cilium/ebpf/internal/btf/core.go | 33 +-
.../cilium/ebpf/internal/btf/ext_info.go | 15 +-
.../cilium/ebpf/internal/btf/fuzz.go | 1 +
.../cilium/ebpf/internal/btf/info.go | 48 ++
.../cilium/ebpf/internal/btf/strings.go | 8 +-
.../cilium/ebpf/internal/btf/syscalls.go | 31 ++
.../cilium/ebpf/internal/btf/types.go | 188 ++++---
vendor/github.com/cilium/ebpf/internal/cpu.go | 4 +-
.../cilium/ebpf/internal/ptr_32_be.go | 1 +
.../cilium/ebpf/internal/ptr_32_le.go | 1 +
.../github.com/cilium/ebpf/internal/ptr_64.go | 4 +-
.../cilium/ebpf/internal/syscall.go | 59 ++
.../cilium/ebpf/internal/unix/types_linux.go | 16 +-
.../cilium/ebpf/internal/unix/types_other.go | 14 +-
.../cilium/ebpf/internal/version.go | 4 +-
.../github.com/cilium/ebpf/link/BUILD.bazel | 2 +
.../github.com/cilium/ebpf/link/freplace.go | 88 +++
vendor/github.com/cilium/ebpf/link/kprobe.go | 38 +-
vendor/github.com/cilium/ebpf/link/link.go | 14 +-
.../github.com/cilium/ebpf/link/perf_event.go | 7 +-
.../github.com/cilium/ebpf/link/syscalls.go | 9 +-
.../github.com/cilium/ebpf/link/tracepoint.go | 8 +-
vendor/github.com/cilium/ebpf/link/uprobe.go | 133 +++--
vendor/github.com/cilium/ebpf/linker.go | 23 +-
vendor/github.com/cilium/ebpf/map.go | 95 ++--
vendor/github.com/cilium/ebpf/marshalers.go | 63 ++-
vendor/github.com/cilium/ebpf/prog.go | 123 +++--
vendor/github.com/cilium/ebpf/run-tests.sh | 22 +-
vendor/github.com/cilium/ebpf/syscalls.go | 94 ++--
vendor/github.com/cilium/ebpf/types.go | 36 +-
vendor/github.com/cilium/ebpf/types_string.go | 69 +--
.../cyphar/filepath-securejoin/.travis.yml | 8 +-
.../cyphar/filepath-securejoin/BUILD.bazel | 1 -
.../cyphar/filepath-securejoin/README.md | 20 +-
.../cyphar/filepath-securejoin/VERSION | 2 +-
.../cyphar/filepath-securejoin/join.go | 25 +-
.../cyphar/filepath-securejoin/vendor.conf | 1 -
vendor/github.com/godbus/dbus/v5/BUILD.bazel | 1 +
.../dbus/v5/{README.markdown => README.md} | 12 +-
vendor/github.com/godbus/dbus/v5/auth.go | 15 +-
vendor/github.com/godbus/dbus/v5/conn.go | 36 +-
vendor/github.com/godbus/dbus/v5/decoder.go | 16 +-
vendor/github.com/godbus/dbus/v5/encoder.go | 61 ++-
vendor/github.com/godbus/dbus/v5/export.go | 37 +-
vendor/github.com/godbus/dbus/v5/message.go | 73 ++-
vendor/github.com/godbus/dbus/v5/sig.go | 66 ++-
.../godbus/dbus/v5/transport_generic.go | 10 +-
.../godbus/dbus/v5/transport_unix.go | 24 +-
.../dbus/v5/transport_unixcred_netbsd.go | 14 +
.../github.com/moby/sys/mountinfo/BUILD.bazel | 6 +
.../moby/sys/mountinfo/mounted_linux.go | 11 +-
.../moby/sys/mountinfo/mounted_unix.go | 16 +-
.../moby/sys/mountinfo/mountinfo.go | 9 +-
.../moby/sys/mountinfo/mountinfo_bsd.go | 9 +-
.../moby/sys/mountinfo/mountinfo_linux.go | 27 +-
.../sys/mountinfo/mountinfo_unsupported.go | 3 +-
.../runc/libcontainer/cgroups/BUILD.bazel | 17 +-
.../runc/libcontainer/cgroups/cgroups.go | 2 -
.../cgroups/cgroups_unsupported.go | 3 -
.../libcontainer/cgroups/devices/BUILD.bazel | 12 +-
.../cgroups/devices/devices_emulator.go | 66 +--
.../libcontainer/cgroups/ebpf/BUILD.bazel | 2 -
.../cgroups/ebpf/devicefilter/BUILD.bazel | 1 -
.../cgroups/ebpf/devicefilter/devicefilter.go | 22 +-
.../libcontainer/cgroups/ebpf/ebpf_linux.go | 4 +-
.../runc/libcontainer/cgroups/file.go | 60 ++-
.../runc/libcontainer/cgroups/fs/BUILD.bazel | 42 +-
.../runc/libcontainer/cgroups/fs/blkio.go | 18 +-
.../runc/libcontainer/cgroups/fs/cpu.go | 22 +-
.../runc/libcontainer/cgroups/fs/cpuacct.go | 46 +-
.../runc/libcontainer/cgroups/fs/cpuset.go | 47 +-
.../runc/libcontainer/cgroups/fs/devices.go | 13 +-
.../runc/libcontainer/cgroups/fs/error.go | 15 +
.../runc/libcontainer/cgroups/fs/freezer.go | 6 +-
.../runc/libcontainer/cgroups/fs/fs.go | 318 +++--------
.../runc/libcontainer/cgroups/fs/hugetlb.go | 17 +-
.../runc/libcontainer/cgroups/fs/memory.go | 56 +-
.../runc/libcontainer/cgroups/fs/name.go | 8 +-
.../runc/libcontainer/cgroups/fs/net_cls.go | 6 +-
.../runc/libcontainer/cgroups/fs/net_prio.go | 6 +-
.../runc/libcontainer/cgroups/fs/paths.go | 186 +++++++
.../libcontainer/cgroups/fs/perf_event.go | 6 +-
.../runc/libcontainer/cgroups/fs/pids.go | 28 +-
.../runc/libcontainer/cgroups/fs/rdma.go | 25 +
.../libcontainer/cgroups/fs/unsupported.go | 3 -
.../runc/libcontainer/cgroups/fs2/BUILD.bazel | 30 +-
.../runc/libcontainer/cgroups/fs2/cpu.go | 10 +-
.../runc/libcontainer/cgroups/fs2/cpuset.go | 2 -
.../libcontainer/cgroups/fs2/defaultpath.go | 26 +-
.../runc/libcontainer/cgroups/fs2/devices.go | 11 +-
.../runc/libcontainer/cgroups/fs2/freezer.go | 18 +-
.../runc/libcontainer/cgroups/fs2/fs2.go | 52 +-
.../runc/libcontainer/cgroups/fs2/hugetlb.go | 10 +-
.../runc/libcontainer/cgroups/fs2/io.go | 13 +-
.../runc/libcontainer/cgroups/fs2/memory.go | 29 +-
.../runc/libcontainer/cgroups/fs2/pids.go | 29 +-
.../libcontainer/cgroups/fscommon/BUILD.bazel | 19 +-
.../libcontainer/cgroups/fscommon/rdma.go | 121 +++++
.../libcontainer/cgroups/fscommon/utils.go | 34 +-
.../runc/libcontainer/cgroups/getallpids.go | 27 +
.../runc/libcontainer/cgroups/stats.go | 16 +-
.../runc/libcontainer/cgroups/utils.go | 115 ++--
.../runc/libcontainer/cgroups/v1_utils.go | 19 +-
.../runc/libcontainer/configs/BUILD.bazel | 5 +-
.../runc/libcontainer/configs/cgroup_linux.go | 20 +-
.../configs/cgroup_unsupported.go | 1 +
.../runc/libcontainer/configs/config.go | 34 +-
.../runc/libcontainer/configs/config_linux.go | 17 +-
.../libcontainer/configs/configs_fuzzer.go | 1 +
.../runc/libcontainer/configs/intelrdt.go | 3 +
.../runc/libcontainer/configs/mount.go | 9 +
.../configs/namespaces_syscall.go | 1 +
.../configs/namespaces_syscall_unsupported.go | 1 +
.../configs/namespaces_unsupported.go | 1 +
.../runc/libcontainer/configs/rdma.go | 9 +
.../runc/libcontainer/devices/device_unix.go | 12 +-
.../runc/libcontainer/user/lookup_unix.go | 1 +
.../runc/libcontainer/user/user.go | 21 +-
.../runc/libcontainer/user/user_fuzzer.go | 1 +
.../runc/libcontainer/userns/userns_fuzzer.go | 1 +
.../libcontainer/userns/userns_unsupported.go | 1 +
.../runc/libcontainer/utils/cmsg.go | 11 +-
.../runc/libcontainer/utils/utils.go | 14 +-
.../runc/libcontainer/utils/utils_unix.go | 5 +-
vendor/modules.txt | 20 +-
151 files changed, 3019 insertions(+), 1845 deletions(-)
create mode 100644 vendor/github.com/cilium/ebpf/attachtype_string.go
create mode 100644 vendor/github.com/cilium/ebpf/internal/align.go
create mode 100644 vendor/github.com/cilium/ebpf/internal/btf/info.go
create mode 100644 vendor/github.com/cilium/ebpf/internal/btf/syscalls.go
create mode 100644 vendor/github.com/cilium/ebpf/link/freplace.go
delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/vendor.conf
rename vendor/github.com/godbus/dbus/v5/{README.markdown => README.md} (81%)
create mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go
delete mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go
create mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/error.go
create mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/paths.go
create mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/rdma.go
delete mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/unsupported.go
create mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/rdma.go
create mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go
create mode 100644 vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go
diff --git a/cmd/virt-chroot/cgroup.go b/cmd/virt-chroot/cgroup.go
index 0b315177d..034c35229 100644
--- a/cmd/virt-chroot/cgroup.go
+++ b/cmd/virt-chroot/cgroup.go
@@ -54,15 +54,16 @@ func decodePaths(marshalledPathsHash string) (map[string]string, error) {
func setCgroupResources(paths map[string]string, resources *runc_configs.Resources, isRootless bool, isV2 bool) error {
config := &runc_configs.Cgroup{
Path: cgroup.HostCgroupBasePath,
- Resources: &runc_configs.Resources{},
+ Resources: resources,
+ Rootless: isRootless,
}
var err error
if isV2 {
- err = setCgroupResourcesV2(paths, resources, isRootless, config)
+ err = setCgroupResourcesV2(paths, resources, config)
} else {
- err = setCgroupResourcesV1(paths, resources, isRootless, config)
+ err = setCgroupResourcesV1(paths, resources, config)
}
if err != nil {
@@ -72,17 +73,20 @@ func setCgroupResources(paths map[string]string, resources *runc_configs.Resourc
return nil
}
-func setCgroupResourcesV1(paths map[string]string, resources *runc_configs.Resources, isRootless bool, config *runc_configs.Cgroup) error {
+func setCgroupResourcesV1(paths map[string]string, resources *runc_configs.Resources, config *runc_configs.Cgroup) error {
return RunWithChroot(cgroup.HostCgroupBasePath, func() error {
- cgroupManager := runc_fs.NewManager(config, paths, isRootless)
+ cgroupManager, err := runc_fs.NewManager(config, paths)
+ if err != nil {
+ return fmt.Errorf("cannot create cgroups v1 manager. err: %v", err)
+ }
return cgroupManager.Set(resources)
})
}
-func setCgroupResourcesV2(paths map[string]string, resources *runc_configs.Resources, isRootless bool, config *runc_configs.Cgroup) error {
+func setCgroupResourcesV2(paths map[string]string, resources *runc_configs.Resources, config *runc_configs.Cgroup) error {
cgroupDirPath := paths[""]
- cgroupManager, err := runc_fs2.NewManager(config, cgroupDirPath, isRootless)
+ cgroupManager, err := runc_fs2.NewManager(config, cgroupDirPath)
if err != nil {
return fmt.Errorf("cannot create cgroups v2 manager. err: %v", err)
}
diff --git a/go.mod b/go.mod
index 19a474ac3..1ca93ba9a 100644
--- a/go.mod
+++ b/go.mod
@@ -35,11 +35,11 @@ require (
github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed
- github.com/moby/sys/mountinfo v0.4.1
+ github.com/moby/sys/mountinfo v0.5.0
github.com/onsi/ginkgo/v2 v2.1.3
github.com/onsi/gomega v1.18.1
- github.com/opencontainers/runc v1.0.3
- github.com/opencontainers/selinux v1.8.2
+ github.com/opencontainers/runc v1.1.2
+ github.com/opencontainers/selinux v1.10.0
github.com/openshift/api v0.0.0
github.com/openshift/client-go v0.0.0
github.com/openshift/library-go v0.0.0-20210205203934-9eb0d970f2f4
@@ -95,9 +95,9 @@ require (
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
- github.com/cilium/ebpf v0.6.2 // indirect
+ github.com/cilium/ebpf v0.7.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
- github.com/cyphar/filepath-securejoin v0.2.2 // indirect
+ github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/go-logfmt/logfmt v0.5.0 // indirect
@@ -110,7 +110,7 @@ require (
github.com/go-openapi/swag v0.21.1 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
- github.com/godbus/dbus/v5 v5.0.4 // indirect
+ github.com/godbus/dbus/v5 v5.0.6 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/go-querystring v1.0.0 // indirect
diff --git a/go.sum b/go.sum
index 053375564..1a5ebddb8 100644
--- a/go.sum
+++ b/go.sum
@@ -192,6 +192,7 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
+github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -200,8 +201,9 @@ github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLI
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.6.1/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
-github.com/cilium/ebpf v0.6.2 h1:iHsfF/t4aW4heW2YKfeHrVPGdtYTL4C4KocpM8KTSnI=
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k=
+github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -235,6 +237,7 @@ github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
+github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
@@ -336,8 +339,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
+github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
+github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
@@ -607,8 +611,9 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
+github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -987,8 +992,9 @@ github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQ
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
-github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
+github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
+github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -1059,8 +1065,9 @@ github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rm
github.com/opencontainers/runc v1.0.0-rc90/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runc v1.0.0/go.mod h1:MU2S3KEB2ZExnhnAQYbwjdYV6HwKtDlNbA2Z2OeNDeA=
-github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
+github.com/opencontainers/runc v1.1.2 h1:2VSZwLx5k/BfsBxMMipG/LYUnmqOD/BPkIVgQUcTlLw=
+github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -1207,8 +1214,9 @@ github.com/satori/go.uuid v0.0.0-20160603004225-b111a074d5ef/go.mod h1:dA0hQrYB0
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sclevine/spec v1.0.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
-github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
+github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 h1:58EBmR2dMNL2n/FnbQewK3D14nXr0V9CObDSvMJLq+Y=
+github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@@ -1696,7 +1704,10 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/pkg/virt-handler/cgroup/cgroup.go b/pkg/virt-handler/cgroup/cgroup.go
index 113a8f8de..7a8e98058 100644
--- a/pkg/virt-handler/cgroup/cgroup.go
+++ b/pkg/virt-handler/cgroup/cgroup.go
@@ -72,12 +72,13 @@ func NewManagerFromPid(pid int) (manager Manager, err error) {
config := &configs.Cgroup{
Path: HostCgroupBasePath,
Resources: &configs.Resources{},
+ Rootless: isRootless,
}
if runc_cgroups.IsCgroup2UnifiedMode() {
version = V2
slicePath := filepath.Join(cgroupBasePath, controllerPaths[""])
- manager, err = newV2Manager(config, slicePath, isRootless)
+ manager, err = newV2Manager(config, slicePath)
} else {
version = V1
for subsystem, path := range controllerPaths {
@@ -87,7 +88,7 @@ func NewManagerFromPid(pid int) (manager Manager, err error) {
controllerPaths[subsystem] = filepath.Join("/", subsystem, path)
}
- manager, err = newV1Manager(config, controllerPaths, isRootless)
+ manager, err = newV1Manager(config, controllerPaths)
}
if err != nil {
diff --git a/pkg/virt-handler/cgroup/cgroup_v1_manager.go b/pkg/virt-handler/cgroup/cgroup_v1_manager.go
index 7d7af652c..97c690aec 100644
--- a/pkg/virt-handler/cgroup/cgroup_v1_manager.go
+++ b/pkg/virt-handler/cgroup/cgroup_v1_manager.go
@@ -23,17 +23,20 @@ type v1Manager struct {
getCurrentlyDefinedRules getCurrentlyDefinedRulesFunc
}
-func newV1Manager(config *runc_configs.Cgroup, controllerPaths map[string]string, rootless bool) (Manager, error) {
- return newCustomizedV1Manager(config, controllerPaths, rootless, execVirtChrootCgroups, getCurrentlyDefinedRules)
+func newV1Manager(config *runc_configs.Cgroup, controllerPaths map[string]string) (Manager, error) {
+ return newCustomizedV1Manager(config, controllerPaths, execVirtChrootCgroups, getCurrentlyDefinedRules)
}
-func newCustomizedV1Manager(config *runc_configs.Cgroup, controllerPaths map[string]string, rootless bool,
+func newCustomizedV1Manager(config *runc_configs.Cgroup, controllerPaths map[string]string,
execVirtChroot execVirtChrootFunc, getCurrentlyDefinedRules getCurrentlyDefinedRulesFunc) (Manager, error) {
- runcManager := runc_fs.NewManager(config, controllerPaths, rootless)
+ runcManager, err := runc_fs.NewManager(config, controllerPaths)
+ if err != nil {
+ return nil, fmt.Errorf("cannot initialize new cgroup manager. err: %v", err)
+ }
manager := v1Manager{
runcManager,
controllerPaths,
- rootless,
+ config.Rootless,
execVirtChroot,
getCurrentlyDefinedRules,
}
diff --git a/pkg/virt-handler/cgroup/cgroup_v2_manager.go b/pkg/virt-handler/cgroup/cgroup_v2_manager.go
index c4717912d..932cabf8f 100644
--- a/pkg/virt-handler/cgroup/cgroup_v2_manager.go
+++ b/pkg/virt-handler/cgroup/cgroup_v2_manager.go
@@ -16,16 +16,16 @@ type v2Manager struct {
execVirtChroot execVirtChrootFunc
}
-func newV2Manager(config *runc_configs.Cgroup, dirPath string, rootless bool) (Manager, error) {
- return newCustomizedV2Manager(config, dirPath, rootless, execVirtChrootCgroups)
+func newV2Manager(config *runc_configs.Cgroup, dirPath string) (Manager, error) {
+ return newCustomizedV2Manager(config, dirPath, execVirtChrootCgroups)
}
-func newCustomizedV2Manager(config *runc_configs.Cgroup, dirPath string, rootless bool, execVirtChroot execVirtChrootFunc) (Manager, error) {
- runcManager, err := runc_fs.NewManager(config, dirPath, rootless)
+func newCustomizedV2Manager(config *runc_configs.Cgroup, dirPath string, execVirtChroot execVirtChrootFunc) (Manager, error) {
+ runcManager, err := runc_fs.NewManager(config, dirPath)
manager := v2Manager{
runcManager,
dirPath,
- rootless,
+ config.Rootless,
execVirtChroot,
}
diff --git a/vendor/github.com/cilium/ebpf/.gitignore b/vendor/github.com/cilium/ebpf/.gitignore
index 38b15653c..b46162b8e 100644
--- a/vendor/github.com/cilium/ebpf/.gitignore
+++ b/vendor/github.com/cilium/ebpf/.gitignore
@@ -5,6 +5,7 @@
*.so
*.dylib
*.o
+!*_bpf*.o
# Test binary, build with `go test -c`
*.test
diff --git a/vendor/github.com/cilium/ebpf/.golangci.yaml b/vendor/github.com/cilium/ebpf/.golangci.yaml
index a88374197..dc62dd6d0 100644
--- a/vendor/github.com/cilium/ebpf/.golangci.yaml
+++ b/vendor/github.com/cilium/ebpf/.golangci.yaml
@@ -24,6 +24,5 @@ linters:
# Could be enabled later:
# - gocyclo
- # - prealloc
# - maligned
# - gosec
diff --git a/vendor/github.com/cilium/ebpf/ARCHITECTURE.md b/vendor/github.com/cilium/ebpf/ARCHITECTURE.md
index aee9c0a0d..6cbb31b64 100644
--- a/vendor/github.com/cilium/ebpf/ARCHITECTURE.md
+++ b/vendor/github.com/cilium/ebpf/ARCHITECTURE.md
@@ -57,7 +57,7 @@ Objects
loading a spec will fail because the kernel is too old, or a feature is not
enabled. There are multiple ways the library deals with that:
-* Fallback: older kernels don't allowing naming programs and maps. The library
+* Fallback: older kernels don't allow naming programs and maps. The library
automatically detects support for names, and omits them during load if
necessary. This works since name is primarily a debug aid.
@@ -68,7 +68,7 @@ enabled. There are multiple ways the library deals with that:
Once program and map objects are loaded they expose the kernel's low-level API,
e.g. `NextKey`. Often this API is awkward to use in Go, so there are safer
wrappers on top of the low-level API, like `MapIterator`. The low-level API is
-useful as an out when our higher-level API doesn't support a particular use case.
+useful when our higher-level API doesn't support a particular use case.
Links
---
diff --git a/vendor/github.com/cilium/ebpf/BUILD.bazel b/vendor/github.com/cilium/ebpf/BUILD.bazel
index 7ff348721..0a0bbbdbf 100644
--- a/vendor/github.com/cilium/ebpf/BUILD.bazel
+++ b/vendor/github.com/cilium/ebpf/BUILD.bazel
@@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
+ "attachtype_string.go",
"collection.go",
"doc.go",
"elf_reader.go",
diff --git a/vendor/github.com/cilium/ebpf/CONTRIBUTING.md b/vendor/github.com/cilium/ebpf/CONTRIBUTING.md
index 72ceb4378..0d29eae81 100644
--- a/vendor/github.com/cilium/ebpf/CONTRIBUTING.md
+++ b/vendor/github.com/cilium/ebpf/CONTRIBUTING.md
@@ -6,8 +6,8 @@ are welcome. Please take a look at [the architecture](ARCHITECTURE.md) to get
a better understanding for the high-level goals.
New features must be accompanied by tests. Before starting work on any large
-feature, please [join](https://cilium.herokuapp.com/) the
-[#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack to
+feature, please [join](https://ebpf.io/slack) the
+[#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack to
discuss the design first.
When submitting pull requests, consider writing details about what problem you
diff --git a/vendor/github.com/cilium/ebpf/Makefile b/vendor/github.com/cilium/ebpf/Makefile
index 5dd342c5b..0bc15c081 100644
--- a/vendor/github.com/cilium/ebpf/Makefile
+++ b/vendor/github.com/cilium/ebpf/Makefile
@@ -18,11 +18,14 @@ TARGETS := \
testdata/loader-clang-7 \
testdata/loader-clang-9 \
testdata/loader-$(CLANG) \
+ testdata/btf_map_init \
testdata/invalid_map \
testdata/raw_tracepoint \
testdata/invalid_map_static \
- testdata/initialized_btf_map \
+ testdata/invalid_btf_map_init \
testdata/strings \
+ testdata/freplace \
+ testdata/iproute2_map_compat \
internal/btf/testdata/relocs
.PHONY: all clean docker-all docker-shell
diff --git a/vendor/github.com/cilium/ebpf/README.md b/vendor/github.com/cilium/ebpf/README.md
index 76c3c303b..01e2fff92 100644
--- a/vendor/github.com/cilium/ebpf/README.md
+++ b/vendor/github.com/cilium/ebpf/README.md
@@ -2,28 +2,16 @@
[![PkgGoDev](https://pkg.go.dev/badge/github.com/cilium/ebpf)](https://pkg.go.dev/github.com/cilium/ebpf)
+![HoneyGopher](.github/images/cilium-ebpf.png)
+
eBPF is a pure Go library that provides utilities for loading, compiling, and
debugging eBPF programs. It has minimal external dependencies and is intended to
be used in long running processes.
-* [asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic
- assembler
-* [link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF
- to various hooks
-* [perf](https://pkg.go.dev/github.com/cilium/ebpf/perf) allows reading from a
- `PERF_EVENT_ARRAY`
-* [cmd/bpf2go](https://pkg.go.dev/github.com/cilium/ebpf/cmd/bpf2go) allows
- compiling and embedding eBPF programs in Go code
-
The library is maintained by [Cloudflare](https://www.cloudflare.com) and
-[Cilium](https://www.cilium.io). Feel free to
-[join](https://cilium.herokuapp.com/) the
-[#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack.
-
-## Current status
+[Cilium](https://www.cilium.io).
-The package is production ready, but **the API is explicitly unstable right
-now**. Expect to update your code if you want to follow along.
+See [ebpf.io](https://ebpf.io) for other projects from the eBPF ecosystem.
## Getting Started
@@ -33,21 +21,37 @@ your own tools can be found under [examples/](examples/).
Contributions are highly encouraged, as they highlight certain use cases of
eBPF and the library, and help shape the future of the project.
+## Getting Help
+
+Please
+[join](https://ebpf.io/slack) the
+[#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack if you
+have questions regarding the library.
+
+## Packages
+
+This library includes the following packages:
+
+* [asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic
+ assembler, allowing you to write eBPF assembly instructions directly
+ within your Go code. (You don't need to use this if you prefer to write your eBPF program in C.)
+* [cmd/bpf2go](https://pkg.go.dev/github.com/cilium/ebpf/cmd/bpf2go) allows
+ compiling and embedding eBPF programs written in C within Go code. As well as
+ compiling the C code, it auto-generates Go code for loading and manipulating
+ the eBPF program and map objects.
+* [link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF
+ to various hooks
+* [perf](https://pkg.go.dev/github.com/cilium/ebpf/perf) allows reading from a
+ `PERF_EVENT_ARRAY`
+* [ringbuf](https://pkg.go.dev/github.com/cilium/ebpf/ringbuf) allows reading from a
+ `BPF_MAP_TYPE_RINGBUF` map
+
+
## Requirements
* A version of Go that is [supported by
upstream](https://golang.org/doc/devel/release.html#policy)
-* Linux 4.9, 4.19 or 5.4 (versions in-between should work, but are not tested)
-
-## Useful resources
-
-* [eBPF.io](https://ebpf.io) (recommended)
-* [Cilium eBPF documentation](https://docs.cilium.io/en/latest/bpf/#bpf-guide)
- (recommended)
-* [Linux documentation on
- BPF](https://www.kernel.org/doc/html/latest/networking/filter.html)
-* [eBPF features by Linux
- version](https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md)
+* Linux >= 4.9. CI is run against LTS releases.
## Regenerating Testdata
@@ -60,3 +64,7 @@ The toolchain image build files are kept in [testdata/docker/](testdata/docker/)
## License
MIT
+
+### eBPF Gopher
+
+The eBPF honeygopher is based on the Go gopher designed by Renee French.
diff --git a/vendor/github.com/cilium/ebpf/asm/func.go b/vendor/github.com/cilium/ebpf/asm/func.go
index aee2c7ac8..bfa5d59c9 100644
--- a/vendor/github.com/cilium/ebpf/asm/func.go
+++ b/vendor/github.com/cilium/ebpf/asm/func.go
@@ -184,6 +184,12 @@ const (
FnKtimeGetCoarseNs
FnImaInodeHash
FnSockFromFile
+ FnCheckMtu
+ FnForEachMapElem
+ FnSnprintf
+ FnSysBpf
+ FnBtfFindByNameKind
+ FnSysClose
)
// Call emits a function call.
diff --git a/vendor/github.com/cilium/ebpf/asm/func_string.go b/vendor/github.com/cilium/ebpf/asm/func_string.go
index a712c5da8..5a0e33363 100644
--- a/vendor/github.com/cilium/ebpf/asm/func_string.go
+++ b/vendor/github.com/cilium/ebpf/asm/func_string.go
@@ -171,11 +171,17 @@ func _() {
_ = x[FnKtimeGetCoarseNs-160]
_ = x[FnImaInodeHash-161]
_ = x[FnSockFromFile-162]
+ _ = x[FnCheckMtu-163]
+ _ = x[FnForEachMapElem-164]
+ _ = x[FnSnprintf-165]
+ _ = x[FnSysBpf-166]
+ _ = x[FnBtfFindByNameKind-167]
+ _ = x[FnSysClose-168]
}
-const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFile"
+const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFileFnCheckMtuFnForEachMapElemFnSnprintfFnSysBpfFnBtfFindByNameKindFnSysClose"
-var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632, 1643, 1658, 1675, 1693, 1713, 1725, 1743, 1754, 1773, 1794, 1805, 1821, 1849, 1859, 1875, 1886, 1896, 1908, 1928, 1943, 1959, 1974, 1990, 2004, 2015, 2030, 2044, 2066, 2087, 2102, 2116, 2128, 2141, 2156, 2173, 2193, 2200, 2214, 2227, 2241, 2259, 2274, 2285, 2297, 2311, 2327, 2346, 2365, 2378, 2396, 2410, 2424}
+var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632, 1643, 1658, 1675, 1693, 1713, 1725, 1743, 1754, 1773, 1794, 1805, 1821, 1849, 1859, 1875, 1886, 1896, 1908, 1928, 1943, 1959, 1974, 1990, 2004, 2015, 2030, 2044, 2066, 2087, 2102, 2116, 2128, 2141, 2156, 2173, 2193, 2200, 2214, 2227, 2241, 2259, 2274, 2285, 2297, 2311, 2327, 2346, 2365, 2378, 2396, 2410, 2424, 2434, 2450, 2460, 2468, 2487, 2497}
func (i BuiltinFunc) String() string {
if i < 0 || i >= BuiltinFunc(len(_BuiltinFunc_index)-1) {
diff --git a/vendor/github.com/cilium/ebpf/asm/instruction.go b/vendor/github.com/cilium/ebpf/asm/instruction.go
index e7ac0109e..64d717d15 100644
--- a/vendor/github.com/cilium/ebpf/asm/instruction.go
+++ b/vendor/github.com/cilium/ebpf/asm/instruction.go
@@ -181,6 +181,11 @@ func (ins *Instruction) IsFunctionCall() bool {
return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall
}
+// IsBuiltinCall returns true if the instruction is a built-in call, i.e. BPF helper call.
+func (ins *Instruction) IsBuiltinCall() bool {
+ return ins.OpCode.JumpOp() == Call && ins.Src == R0 && ins.Dst == R0
+}
+
// IsConstantLoad returns true if the instruction loads a constant of the
// given size.
func (ins *Instruction) IsConstantLoad(size Size) bool {
diff --git a/vendor/github.com/cilium/ebpf/attachtype_string.go b/vendor/github.com/cilium/ebpf/attachtype_string.go
new file mode 100644
index 000000000..de355ed90
--- /dev/null
+++ b/vendor/github.com/cilium/ebpf/attachtype_string.go
@@ -0,0 +1,65 @@
+// Code generated by "stringer -type AttachType -trimprefix Attach"; DO NOT EDIT.
+
+package ebpf
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[AttachNone-0]
+ _ = x[AttachCGroupInetIngress-0]
+ _ = x[AttachCGroupInetEgress-1]
+ _ = x[AttachCGroupInetSockCreate-2]
+ _ = x[AttachCGroupSockOps-3]
+ _ = x[AttachSkSKBStreamParser-4]
+ _ = x[AttachSkSKBStreamVerdict-5]
+ _ = x[AttachCGroupDevice-6]
+ _ = x[AttachSkMsgVerdict-7]
+ _ = x[AttachCGroupInet4Bind-8]
+ _ = x[AttachCGroupInet6Bind-9]
+ _ = x[AttachCGroupInet4Connect-10]
+ _ = x[AttachCGroupInet6Connect-11]
+ _ = x[AttachCGroupInet4PostBind-12]
+ _ = x[AttachCGroupInet6PostBind-13]
+ _ = x[AttachCGroupUDP4Sendmsg-14]
+ _ = x[AttachCGroupUDP6Sendmsg-15]
+ _ = x[AttachLircMode2-16]
+ _ = x[AttachFlowDissector-17]
+ _ = x[AttachCGroupSysctl-18]
+ _ = x[AttachCGroupUDP4Recvmsg-19]
+ _ = x[AttachCGroupUDP6Recvmsg-20]
+ _ = x[AttachCGroupGetsockopt-21]
+ _ = x[AttachCGroupSetsockopt-22]
+ _ = x[AttachTraceRawTp-23]
+ _ = x[AttachTraceFEntry-24]
+ _ = x[AttachTraceFExit-25]
+ _ = x[AttachModifyReturn-26]
+ _ = x[AttachLSMMac-27]
+ _ = x[AttachTraceIter-28]
+ _ = x[AttachCgroupInet4GetPeername-29]
+ _ = x[AttachCgroupInet6GetPeername-30]
+ _ = x[AttachCgroupInet4GetSockname-31]
+ _ = x[AttachCgroupInet6GetSockname-32]
+ _ = x[AttachXDPDevMap-33]
+ _ = x[AttachCgroupInetSockRelease-34]
+ _ = x[AttachXDPCPUMap-35]
+ _ = x[AttachSkLookup-36]
+ _ = x[AttachXDP-37]
+ _ = x[AttachSkSKBVerdict-38]
+ _ = x[AttachSkReuseportSelect-39]
+ _ = x[AttachSkReuseportSelectOrMigrate-40]
+ _ = x[AttachPerfEvent-41]
+}
+
+const _AttachType_name = "NoneCGroupInetEgressCGroupInetSockCreateCGroupSockOpsSkSKBStreamParserSkSKBStreamVerdictCGroupDeviceSkMsgVerdictCGroupInet4BindCGroupInet6BindCGroupInet4ConnectCGroupInet6ConnectCGroupInet4PostBindCGroupInet6PostBindCGroupUDP4SendmsgCGroupUDP6SendmsgLircMode2FlowDissectorCGroupSysctlCGroupUDP4RecvmsgCGroupUDP6RecvmsgCGroupGetsockoptCGroupSetsockoptTraceRawTpTraceFEntryTraceFExitModifyReturnLSMMacTraceIterCgroupInet4GetPeernameCgroupInet6GetPeernameCgroupInet4GetSocknameCgroupInet6GetSocknameXDPDevMapCgroupInetSockReleaseXDPCPUMapSkLookupXDPSkSKBVerdictSkReuseportSelectSkReuseportSelectOrMigratePerfEvent"
+
+var _AttachType_index = [...]uint16{0, 4, 20, 40, 53, 70, 88, 100, 112, 127, 142, 160, 178, 197, 216, 233, 250, 259, 272, 284, 301, 318, 334, 350, 360, 371, 381, 393, 399, 408, 430, 452, 474, 496, 505, 526, 535, 543, 546, 558, 575, 601, 610}
+
+func (i AttachType) String() string {
+ if i >= AttachType(len(_AttachType_index)-1) {
+ return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]]
+}
diff --git a/vendor/github.com/cilium/ebpf/collection.go b/vendor/github.com/cilium/ebpf/collection.go
index 17cc69492..2ededc87a 100644
--- a/vendor/github.com/cilium/ebpf/collection.go
+++ b/vendor/github.com/cilium/ebpf/collection.go
@@ -1,6 +1,7 @@
package ebpf
import (
+ "encoding/binary"
"errors"
"fmt"
"io"
@@ -25,6 +26,10 @@ type CollectionOptions struct {
type CollectionSpec struct {
Maps map[string]*MapSpec
Programs map[string]*ProgramSpec
+
+ // ByteOrder specifies whether the ELF was compiled for
+ // big-endian or little-endian architectures.
+ ByteOrder binary.ByteOrder
}
// Copy returns a recursive copy of the spec.
@@ -34,8 +39,9 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
}
cpy := CollectionSpec{
- Maps: make(map[string]*MapSpec, len(cs.Maps)),
- Programs: make(map[string]*ProgramSpec, len(cs.Programs)),
+ Maps: make(map[string]*MapSpec, len(cs.Maps)),
+ Programs: make(map[string]*ProgramSpec, len(cs.Programs)),
+ ByteOrder: cs.ByteOrder,
}
for name, spec := range cs.Maps {
@@ -123,7 +129,7 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
buf := make([]byte, len(value))
copy(buf, value)
- err := patchValue(buf, btf.MapValue(rodata.BTF), consts)
+ err := patchValue(buf, rodata.BTF.Value, consts)
if err != nil {
return err
}
@@ -134,15 +140,15 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
// Assign the contents of a CollectionSpec to a struct.
//
-// This function is a short-cut to manually checking the presence
-// of maps and programs in a collection spec. Consider using bpf2go if this
-// sounds useful.
+// This function is a shortcut to manually checking the presence
+// of maps and programs in a CollectionSpec. Consider using bpf2go
+// if this sounds useful.
//
-// The argument to must be a pointer to a struct. A field of the
+// 'to' must be a pointer to a struct. A field of the
// struct is updated with values from Programs or Maps if it
// has an `ebpf` tag and its type is *ProgramSpec or *MapSpec.
-// The tag gives the name of the program or map as found in
-// the CollectionSpec.
+// The tag's value specifies the name of the program or map as
+// found in the CollectionSpec.
//
// struct {
// Foo *ebpf.ProgramSpec `ebpf:"xdp_foo"`
@@ -150,42 +156,47 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
// Ignored int
// }
//
-// Returns an error if any of the fields can't be found, or
-// if the same map or program is assigned multiple times.
+// Returns an error if any of the eBPF objects can't be found, or
+// if the same MapSpec or ProgramSpec is assigned multiple times.
func (cs *CollectionSpec) Assign(to interface{}) error {
- valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
+ // Assign() only supports assigning ProgramSpecs and MapSpecs,
+ // so doesn't load any resources into the kernel.
+ getValue := func(typ reflect.Type, name string) (interface{}, error) {
switch typ {
+
case reflect.TypeOf((*ProgramSpec)(nil)):
- p := cs.Programs[name]
- if p == nil {
- return reflect.Value{}, fmt.Errorf("missing program %q", name)
+ if p := cs.Programs[name]; p != nil {
+ return p, nil
}
- return reflect.ValueOf(p), nil
+ return nil, fmt.Errorf("missing program %q", name)
+
case reflect.TypeOf((*MapSpec)(nil)):
- m := cs.Maps[name]
- if m == nil {
- return reflect.Value{}, fmt.Errorf("missing map %q", name)
+ if m := cs.Maps[name]; m != nil {
+ return m, nil
}
- return reflect.ValueOf(m), nil
+ return nil, fmt.Errorf("missing map %q", name)
+
default:
- return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
+ return nil, fmt.Errorf("unsupported type %s", typ)
}
}
- return assignValues(to, valueOf)
+ return assignValues(to, getValue)
}
-// LoadAndAssign maps and programs into the kernel and assign them to a struct.
+// LoadAndAssign loads Maps and Programs into the kernel and assigns them
+// to a struct.
//
-// This function is a short-cut to manually checking the presence
-// of maps and programs in a collection spec. Consider using bpf2go if this
-// sounds useful.
+// This function is a shortcut to manually checking the presence
+// of maps and programs in a CollectionSpec. Consider using bpf2go
+// if this sounds useful.
//
-// The argument to must be a pointer to a struct. A field of the
-// struct is updated with values from Programs or Maps if it
-// has an `ebpf` tag and its type is *Program or *Map.
-// The tag gives the name of the program or map as found in
-// the CollectionSpec.
+// 'to' must be a pointer to a struct. A field of the struct is updated with
+// a Program or Map if it has an `ebpf` tag and its type is *Program or *Map.
+// The tag's value specifies the name of the program or map as found in the
+// CollectionSpec. Before updating the struct, the requested objects and their
+// dependent resources are loaded into the kernel and populated with values if
+// specified.
//
// struct {
// Foo *ebpf.Program `ebpf:"xdp_foo"`
@@ -196,39 +207,53 @@ func (cs *CollectionSpec) Assign(to interface{}) error {
// opts may be nil.
//
// Returns an error if any of the fields can't be found, or
-// if the same map or program is assigned multiple times.
+// if the same Map or Program is assigned multiple times.
func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) error {
- if opts == nil {
- opts = &CollectionOptions{}
- }
-
- loadMap, loadProgram, done, cleanup := lazyLoadCollection(cs, opts)
- defer cleanup()
+ loader := newCollectionLoader(cs, opts)
+ defer loader.cleanup()
- valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
+ // Support assigning Programs and Maps, lazy-loading the required objects.
+ assignedMaps := make(map[string]bool)
+ getValue := func(typ reflect.Type, name string) (interface{}, error) {
switch typ {
+
case reflect.TypeOf((*Program)(nil)):
- p, err := loadProgram(name)
- if err != nil {
- return reflect.Value{}, err
- }
- return reflect.ValueOf(p), nil
+ return loader.loadProgram(name)
+
case reflect.TypeOf((*Map)(nil)):
- m, err := loadMap(name)
- if err != nil {
- return reflect.Value{}, err
- }
- return reflect.ValueOf(m), nil
+ assignedMaps[name] = true
+ return loader.loadMap(name)
+
default:
- return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
+ return nil, fmt.Errorf("unsupported type %s", typ)
}
}
- if err := assignValues(to, valueOf); err != nil {
+ // Load the Maps and Programs requested by the annotated struct.
+ if err := assignValues(to, getValue); err != nil {
return err
}
- done()
+ // Populate the requested maps. Has a chance of lazy-loading other dependent maps.
+ if err := loader.populateMaps(); err != nil {
+ return err
+ }
+
+ // Evaluate the loader's objects after all (lazy)loading has taken place.
+ for n, m := range loader.maps {
+ switch m.typ {
+ case ProgramArray:
+ // Require all lazy-loaded ProgramArrays to be assigned to the given object.
+ // Without any references, they will be closed on the first GC and all tail
+ // calls into them will miss.
+ if !assignedMaps[n] {
+ return fmt.Errorf("ProgramArray %s must be assigned to prevent missed tail calls", n)
+ }
+ }
+ }
+
+ loader.finalize()
+
return nil
}
@@ -246,24 +271,32 @@ func NewCollection(spec *CollectionSpec) (*Collection, error) {
// NewCollectionWithOptions creates a Collection from a specification.
func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) {
- loadMap, loadProgram, done, cleanup := lazyLoadCollection(spec, &opts)
- defer cleanup()
+ loader := newCollectionLoader(spec, &opts)
+ defer loader.cleanup()
+ // Create maps first, as their fds need to be linked into programs.
for mapName := range spec.Maps {
- _, err := loadMap(mapName)
- if err != nil {
+ if _, err := loader.loadMap(mapName); err != nil {
return nil, err
}
}
for progName := range spec.Programs {
- _, err := loadProgram(progName)
- if err != nil {
+ if _, err := loader.loadProgram(progName); err != nil {
return nil, err
}
}
- maps, progs := done()
+ // Maps can contain Program and Map stubs, so populate them after
+ // all Maps and Programs have been successfully loaded.
+ if err := loader.populateMaps(); err != nil {
+ return nil, err
+ }
+
+ maps, progs := loader.maps, loader.programs
+
+ loader.finalize()
+
return &Collection{
progs,
maps,
@@ -314,113 +347,154 @@ func (hc handleCache) close() {
for _, handle := range hc.btfHandles {
handle.Close()
}
- hc.btfHandles = nil
- hc.btfSpecs = nil
}
-func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
- loadMap func(string) (*Map, error),
- loadProgram func(string) (*Program, error),
- done func() (map[string]*Map, map[string]*Program),
- cleanup func(),
-) {
- var (
- maps = make(map[string]*Map)
- progs = make(map[string]*Program)
- handles = newHandleCache()
- skipMapsAndProgs = false
- )
-
- cleanup = func() {
- handles.close()
-
- if skipMapsAndProgs {
- return
- }
+type collectionLoader struct {
+ coll *CollectionSpec
+ opts *CollectionOptions
+ maps map[string]*Map
+ programs map[string]*Program
+ handles *handleCache
+}
- for _, m := range maps {
- m.Close()
- }
+func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) *collectionLoader {
+ if opts == nil {
+ opts = &CollectionOptions{}
+ }
- for _, p := range progs {
- p.Close()
- }
+ return &collectionLoader{
+ coll,
+ opts,
+ make(map[string]*Map),
+ make(map[string]*Program),
+ newHandleCache(),
+ }
+}
+
+// finalize should be called when all the collectionLoader's resources
+// have been successfully loaded into the kernel and populated with values.
+func (cl *collectionLoader) finalize() {
+ cl.maps, cl.programs = nil, nil
+}
+
+// cleanup cleans up all resources left over in the collectionLoader.
+// Call finalize() when Map and Program creation/population is successful
+// to prevent them from getting closed.
+func (cl *collectionLoader) cleanup() {
+ cl.handles.close()
+ for _, m := range cl.maps {
+ m.Close()
+ }
+ for _, p := range cl.programs {
+ p.Close()
+ }
+}
+
+func (cl *collectionLoader) loadMap(mapName string) (*Map, error) {
+ if m := cl.maps[mapName]; m != nil {
+ return m, nil
+ }
+
+ mapSpec := cl.coll.Maps[mapName]
+ if mapSpec == nil {
+ return nil, fmt.Errorf("missing map %s", mapName)
}
- done = func() (map[string]*Map, map[string]*Program) {
- skipMapsAndProgs = true
- return maps, progs
+ m, err := newMapWithOptions(mapSpec, cl.opts.Maps, cl.handles)
+ if err != nil {
+ return nil, fmt.Errorf("map %s: %w", mapName, err)
}
- loadMap = func(mapName string) (*Map, error) {
- if m := maps[mapName]; m != nil {
- return m, nil
+ cl.maps[mapName] = m
+ return m, nil
+}
+
+func (cl *collectionLoader) loadProgram(progName string) (*Program, error) {
+ if prog := cl.programs[progName]; prog != nil {
+ return prog, nil
+ }
+
+ progSpec := cl.coll.Programs[progName]
+ if progSpec == nil {
+ return nil, fmt.Errorf("unknown program %s", progName)
+ }
+
+ progSpec = progSpec.Copy()
+
+ // Rewrite any reference to a valid map.
+ for i := range progSpec.Instructions {
+ ins := &progSpec.Instructions[i]
+
+ if !ins.IsLoadFromMap() || ins.Reference == "" {
+ continue
}
- mapSpec := coll.Maps[mapName]
- if mapSpec == nil {
- return nil, fmt.Errorf("missing map %s", mapName)
+ if uint32(ins.Constant) != math.MaxUint32 {
+ // Don't overwrite maps already rewritten, users can
+ // rewrite programs in the spec themselves
+ continue
}
- m, err := newMapWithOptions(mapSpec, opts.Maps, handles)
+ m, err := cl.loadMap(ins.Reference)
if err != nil {
- return nil, fmt.Errorf("map %s: %w", mapName, err)
+ return nil, fmt.Errorf("program %s: %w", progName, err)
}
- maps[mapName] = m
- return m, nil
- }
-
- loadProgram = func(progName string) (*Program, error) {
- if prog := progs[progName]; prog != nil {
- return prog, nil
+ fd := m.FD()
+ if fd < 0 {
+ return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
}
-
- progSpec := coll.Programs[progName]
- if progSpec == nil {
- return nil, fmt.Errorf("unknown program %s", progName)
+ if err := ins.RewriteMapPtr(m.FD()); err != nil {
+ return nil, fmt.Errorf("program %s: map %s: %w", progName, ins.Reference, err)
}
+ }
- progSpec = progSpec.Copy()
+ prog, err := newProgramWithOptions(progSpec, cl.opts.Programs, cl.handles)
+ if err != nil {
+ return nil, fmt.Errorf("program %s: %w", progName, err)
+ }
- // Rewrite any reference to a valid map.
- for i := range progSpec.Instructions {
- ins := &progSpec.Instructions[i]
+ cl.programs[progName] = prog
+ return prog, nil
+}
- if !ins.IsLoadFromMap() || ins.Reference == "" {
- continue
- }
+func (cl *collectionLoader) populateMaps() error {
+ for mapName, m := range cl.maps {
+ mapSpec, ok := cl.coll.Maps[mapName]
+ if !ok {
+ return fmt.Errorf("missing map spec %s", mapName)
+ }
- if uint32(ins.Constant) != math.MaxUint32 {
- // Don't overwrite maps already rewritten, users can
- // rewrite programs in the spec themselves
- continue
- }
+ mapSpec = mapSpec.Copy()
- m, err := loadMap(ins.Reference)
- if err != nil {
- return nil, fmt.Errorf("program %s: %w", progName, err)
- }
+ // Replace any object stubs with loaded objects.
+ for i, kv := range mapSpec.Contents {
+ switch v := kv.Value.(type) {
+ case programStub:
+ // loadProgram is idempotent and could return an existing Program.
+ prog, err := cl.loadProgram(string(v))
+ if err != nil {
+ return fmt.Errorf("loading program %s, for map %s: %w", v, mapName, err)
+ }
+ mapSpec.Contents[i] = MapKV{kv.Key, prog}
- fd := m.FD()
- if fd < 0 {
- return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
- }
- if err := ins.RewriteMapPtr(m.FD()); err != nil {
- return nil, fmt.Errorf("progam %s: map %s: %w", progName, ins.Reference, err)
+ case mapStub:
+ // loadMap is idempotent and could return an existing Map.
+ innerMap, err := cl.loadMap(string(v))
+ if err != nil {
+ return fmt.Errorf("loading inner map %s, for map %s: %w", v, mapName, err)
+ }
+ mapSpec.Contents[i] = MapKV{kv.Key, innerMap}
}
}
- prog, err := newProgramWithOptions(progSpec, opts.Programs, handles)
- if err != nil {
- return nil, fmt.Errorf("program %s: %w", progName, err)
+ // Populate and freeze the map if specified.
+ if err := m.finalize(mapSpec); err != nil {
+ return fmt.Errorf("populating map %s: %w", mapName, err)
}
-
- progs[progName] = prog
- return prog, nil
}
- return
+ return nil
}
// LoadCollection parses an object file and converts it to a collection.
@@ -466,108 +540,81 @@ func (coll *Collection) DetachProgram(name string) *Program {
return p
}
-// Assign the contents of a collection to a struct.
-//
-// Deprecated: use CollectionSpec.Assign instead. It provides the same
-// functionality but creates only the maps and programs requested.
-func (coll *Collection) Assign(to interface{}) error {
- assignedMaps := make(map[string]struct{})
- assignedPrograms := make(map[string]struct{})
- valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
- switch typ {
- case reflect.TypeOf((*Program)(nil)):
- p := coll.Programs[name]
- if p == nil {
- return reflect.Value{}, fmt.Errorf("missing program %q", name)
- }
- assignedPrograms[name] = struct{}{}
- return reflect.ValueOf(p), nil
- case reflect.TypeOf((*Map)(nil)):
- m := coll.Maps[name]
- if m == nil {
- return reflect.Value{}, fmt.Errorf("missing map %q", name)
- }
- assignedMaps[name] = struct{}{}
- return reflect.ValueOf(m), nil
- default:
- return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
- }
- }
-
- if err := assignValues(to, valueOf); err != nil {
- return err
- }
+// structField represents a struct field containing the ebpf struct tag.
+type structField struct {
+ reflect.StructField
+ value reflect.Value
+}
- for name := range assignedPrograms {
- coll.DetachProgram(name)
+// ebpfFields extracts field names tagged with 'ebpf' from a struct type.
+// Keep track of visited types to avoid infinite recursion.
+func ebpfFields(structVal reflect.Value, visited map[reflect.Type]bool) ([]structField, error) {
+ if visited == nil {
+ visited = make(map[reflect.Type]bool)
}
- for name := range assignedMaps {
- coll.DetachMap(name)
+ structType := structVal.Type()
+ if structType.Kind() != reflect.Struct {
+ return nil, fmt.Errorf("%s is not a struct", structType)
}
- return nil
-}
-
-func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Value, error)) error {
- type structField struct {
- reflect.StructField
- value reflect.Value
+ if visited[structType] {
+ return nil, fmt.Errorf("recursion on type %s", structType)
}
- var (
- fields []structField
- visitedTypes = make(map[reflect.Type]bool)
- flattenStruct func(reflect.Value) error
- )
+ fields := make([]structField, 0, structType.NumField())
+ for i := 0; i < structType.NumField(); i++ {
+ field := structField{structType.Field(i), structVal.Field(i)}
- flattenStruct = func(structVal reflect.Value) error {
- structType := structVal.Type()
- if structType.Kind() != reflect.Struct {
- return fmt.Errorf("%s is not a struct", structType)
- }
-
- if visitedTypes[structType] {
- return fmt.Errorf("recursion on type %s", structType)
+ // If the field is tagged, gather it and move on.
+ name := field.Tag.Get("ebpf")
+ if name != "" {
+ fields = append(fields, field)
+ continue
}
- for i := 0; i < structType.NumField(); i++ {
- field := structField{structType.Field(i), structVal.Field(i)}
-
- name := field.Tag.Get("ebpf")
- if name != "" {
- fields = append(fields, field)
+ // If the field does not have an ebpf tag, but is a struct or a pointer
+ // to a struct, attempt to gather its fields as well.
+ var v reflect.Value
+ switch field.Type.Kind() {
+ case reflect.Ptr:
+ if field.Type.Elem().Kind() != reflect.Struct {
continue
}
- var err error
- switch field.Type.Kind() {
- case reflect.Ptr:
- if field.Type.Elem().Kind() != reflect.Struct {
- continue
- }
-
- if field.value.IsNil() {
- return fmt.Errorf("nil pointer to %s", structType)
- }
+ if field.value.IsNil() {
+ return nil, fmt.Errorf("nil pointer to %s", structType)
+ }
- err = flattenStruct(field.value.Elem())
+ // Obtain the destination type of the pointer.
+ v = field.value.Elem()
- case reflect.Struct:
- err = flattenStruct(field.value)
+ case reflect.Struct:
+ // Reference the value's type directly.
+ v = field.value
- default:
- continue
- }
+ default:
+ continue
+ }
- if err != nil {
- return fmt.Errorf("field %s: %w", field.Name, err)
- }
+ inner, err := ebpfFields(v, visited)
+ if err != nil {
+ return nil, fmt.Errorf("field %s: %w", field.Name, err)
}
- return nil
+ fields = append(fields, inner...)
}
+ return fields, nil
+}
+
+// assignValues attempts to populate all fields of 'to' tagged with 'ebpf'.
+//
+// getValue is called for every tagged field of 'to' and must return the value
+// to be assigned to the field with the given typ and name.
+func assignValues(to interface{},
+ getValue func(typ reflect.Type, name string) (interface{}, error)) error {
+
toValue := reflect.ValueOf(to)
if toValue.Type().Kind() != reflect.Ptr {
return fmt.Errorf("%T is not a pointer to struct", to)
@@ -577,7 +624,8 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
return fmt.Errorf("nil pointer to %T", to)
}
- if err := flattenStruct(toValue.Elem()); err != nil {
+ fields, err := ebpfFields(toValue.Elem(), nil)
+ if err != nil {
return err
}
@@ -587,19 +635,23 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
name string
}
- assignedTo := make(map[elem]string)
+ assigned := make(map[elem]string)
for _, field := range fields {
- name := field.Tag.Get("ebpf")
- if strings.Contains(name, ",") {
+ // Get string value the field is tagged with.
+ tag := field.Tag.Get("ebpf")
+ if strings.Contains(tag, ",") {
return fmt.Errorf("field %s: ebpf tag contains a comma", field.Name)
}
- e := elem{field.Type, name}
- if assignedField := assignedTo[e]; assignedField != "" {
- return fmt.Errorf("field %s: %q was already assigned to %s", field.Name, name, assignedField)
+ // Check if the eBPF object with the requested
+ // type and tag was already assigned elsewhere.
+ e := elem{field.Type, tag}
+ if af := assigned[e]; af != "" {
+ return fmt.Errorf("field %s: object %q was already assigned to %s", field.Name, tag, af)
}
- value, err := valueOf(field.Type, name)
+ // Get the eBPF object referred to by the tag.
+ value, err := getValue(field.Type, tag)
if err != nil {
return fmt.Errorf("field %s: %w", field.Name, err)
}
@@ -607,9 +659,9 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
if !field.value.CanSet() {
return fmt.Errorf("field %s: can't set value", field.Name)
}
+ field.value.Set(reflect.ValueOf(value))
- field.value.Set(value)
- assignedTo[e] = field.Name
+ assigned[e] = field.Name
}
return nil
diff --git a/vendor/github.com/cilium/ebpf/elf_reader.go b/vendor/github.com/cilium/ebpf/elf_reader.go
index c2afbc36a..42010f43e 100644
--- a/vendor/github.com/cilium/ebpf/elf_reader.go
+++ b/vendor/github.com/cilium/ebpf/elf_reader.go
@@ -19,7 +19,7 @@ import (
)
// elfCode is a convenience to reduce the amount of arguments that have to
-// be passed around explicitly. You should treat it's contents as immutable.
+// be passed around explicitly. You should treat its contents as immutable.
type elfCode struct {
*internal.SafeELFFile
sections map[elf.SectionIndex]*elfSection
@@ -188,7 +188,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
return nil, fmt.Errorf("load programs: %w", err)
}
- return &CollectionSpec{maps, progs}, nil
+ return &CollectionSpec{maps, progs, ec.ByteOrder}, nil
}
func loadLicense(sec *elf.Section) (string, error) {
@@ -520,8 +520,12 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error {
return fmt.Errorf("map %s: missing flags", mapName)
}
- if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
- return fmt.Errorf("map %s: unknown and non-zero fields in definition", mapName)
+ extra, err := io.ReadAll(lr)
+ if err != nil {
+ return fmt.Errorf("map %s: reading map tail: %w", mapName, err)
+ }
+ if len(extra) > 0 {
+ spec.Extra = *bytes.NewReader(extra)
}
if err := spec.clampPerfEventArraySize(); err != nil {
@@ -535,6 +539,9 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error {
return nil
}
+// loadBTFMaps iterates over all ELF sections marked as BTF map sections
+// (like .maps) and parses them into MapSpecs. Dump the .maps section and
+// any relocations with `readelf -x .maps -r <elf_file>`.
func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
for _, sec := range ec.sections {
if sec.kind != btfMapSection {
@@ -545,33 +552,46 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
return fmt.Errorf("missing BTF")
}
- _, err := io.Copy(internal.DiscardZeroes{}, bufio.NewReader(sec.Open()))
- if err != nil {
- return fmt.Errorf("section %v: initializing BTF map definitions: %w", sec.Name, internal.ErrNotSupported)
- }
-
- var ds btf.Datasec
+ // Each section must appear as a DataSec in the ELF's BTF blob.
+ var ds *btf.Datasec
if err := ec.btf.FindType(sec.Name, &ds); err != nil {
return fmt.Errorf("cannot find section '%s' in BTF: %w", sec.Name, err)
}
+ // Open a Reader to the ELF's raw section bytes so we can assert that all
+ // of them are zero on a per-map (per-Var) basis. For now, the section's
+ // sole purpose is to receive relocations, so all must be zero.
+ rs := sec.Open()
+
for _, vs := range ds.Vars {
+ // BPF maps are declared as and assigned to global variables,
+ // so iterate over each Var in the DataSec and validate their types.
v, ok := vs.Type.(*btf.Var)
if !ok {
return fmt.Errorf("section %v: unexpected type %s", sec.Name, vs.Type)
}
name := string(v.Name)
+ // The BTF metadata for each Var contains the full length of the map
+ // declaration, so read the corresponding amount of bytes from the ELF.
+ // This way, we can pinpoint which map declaration contains unexpected
+ // (and therefore unsupported) data.
+ _, err := io.Copy(internal.DiscardZeroes{}, io.LimitReader(rs, int64(vs.Size)))
+ if err != nil {
+ return fmt.Errorf("section %v: map %s: initializing BTF map definitions: %w", sec.Name, name, internal.ErrNotSupported)
+ }
+
if maps[name] != nil {
return fmt.Errorf("section %v: map %s already exists", sec.Name, name)
}
+ // Each Var representing a BTF map definition contains a Struct.
mapStruct, ok := v.Type.(*btf.Struct)
if !ok {
return fmt.Errorf("expected struct, got %s", v.Type)
}
- mapSpec, err := mapSpecFromBTF(name, mapStruct, false, ec.btf)
+ mapSpec, err := mapSpecFromBTF(sec, &vs, mapStruct, ec.btf, name, false)
if err != nil {
return fmt.Errorf("map %v: %w", name, err)
}
@@ -582,32 +602,52 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
maps[name] = mapSpec
}
+
+ // Drain the ELF section reader to make sure all bytes are accounted for
+ // with BTF metadata.
+ i, err := io.Copy(io.Discard, rs)
+ if err != nil {
+ return fmt.Errorf("section %v: unexpected error reading remainder of ELF section: %w", sec.Name, err)
+ }
+ if i > 0 {
+ return fmt.Errorf("section %v: %d unexpected remaining bytes in ELF section, invalid BTF?", sec.Name, i)
+ }
}
return nil
}
+// A programStub is a placeholder for a Program to be inserted at a certain map key.
+// It needs to be resolved into a Program later on in the loader process.
+type programStub string
+
+// A mapStub is a placeholder for a Map to be inserted at a certain map key.
+// It needs to be resolved into a Map later on in the loader process.
+type mapStub string
+
// mapSpecFromBTF produces a MapSpec based on a btf.Struct def representing
// a BTF map definition. The name and spec arguments will be copied to the
// resulting MapSpec, and inner must be true on any resursive invocations.
-func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*MapSpec, error) {
-
+func mapSpecFromBTF(es *elfSection, vs *btf.VarSecinfo, def *btf.Struct, spec *btf.Spec, name string, inner bool) (*MapSpec, error) {
var (
- key, value btf.Type
- keySize, valueSize uint32
- mapType, flags, maxEntries uint32
- pinType PinType
- innerMapSpec *MapSpec
- err error
+ key, value btf.Type
+ keySize, valueSize uint32
+ mapType MapType
+ flags, maxEntries uint32
+ pinType PinType
+ innerMapSpec *MapSpec
+ contents []MapKV
+ err error
)
for i, member := range def.Members {
switch member.Name {
case "type":
- mapType, err = uintFromBTF(member.Type)
+ mt, err := uintFromBTF(member.Type)
if err != nil {
return nil, fmt.Errorf("can't get type: %w", err)
}
+ mapType = MapType(mt)
case "map_flags":
flags, err = uintFromBTF(member.Type)
@@ -717,7 +757,7 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
case *btf.Struct:
// The values member pointing to an array of structs means we're expecting
// a map-in-map declaration.
- if MapType(mapType) != ArrayOfMaps && MapType(mapType) != HashOfMaps {
+ if mapType != ArrayOfMaps && mapType != HashOfMaps {
return nil, errors.New("outer map needs to be an array or a hash of maps")
}
if inner {
@@ -731,21 +771,38 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
// on kernels 5.2 and up)
// Pass the BTF spec from the parent object, since both parent and
// child must be created from the same BTF blob (on kernels that support BTF).
- innerMapSpec, err = mapSpecFromBTF(name+"_inner", t, true, spec)
+ innerMapSpec, err = mapSpecFromBTF(es, vs, t, spec, name+"_inner", true)
if err != nil {
return nil, fmt.Errorf("can't parse BTF map definition of inner map: %w", err)
}
+ case *btf.FuncProto:
+ // The values member contains an array of function pointers, meaning an
+ // autopopulated PROG_ARRAY.
+ if mapType != ProgramArray {
+ return nil, errors.New("map needs to be a program array")
+ }
+
default:
return nil, fmt.Errorf("unsupported value type %q in 'values' field", t)
}
+ contents, err = resolveBTFValuesContents(es, vs, member)
+ if err != nil {
+ return nil, fmt.Errorf("resolving values contents: %w", err)
+ }
+
default:
return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name)
}
}
- bm := btf.NewMap(spec, key, value)
+ if key == nil {
+ key = &btf.Void{}
+ }
+ if value == nil {
+ value = &btf.Void{}
+ }
return &MapSpec{
Name: SanitizeName(name, -1),
@@ -754,9 +811,10 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
ValueSize: valueSize,
MaxEntries: maxEntries,
Flags: flags,
- BTF: &bm,
+ BTF: &btf.Map{Spec: spec, Key: key, Value: value},
Pinning: pinType,
InnerMap: innerMapSpec,
+ Contents: contents,
}, nil
}
@@ -793,6 +851,64 @@ func resolveBTFArrayMacro(typ btf.Type) (btf.Type, error) {
return ptr.Target, nil
}
+// resolveBTFValuesContents resolves relocations into ELF sections belonging
+// to btf.VarSecinfo's. This can be used on the 'values' member in BTF map
+// definitions to extract static declarations of map contents.
+func resolveBTFValuesContents(es *elfSection, vs *btf.VarSecinfo, member btf.Member) ([]MapKV, error) {
+ // The elements of a .values pointer array are not encoded in BTF.
+ // Instead, relocations are generated into each array index.
+ // However, it's possible to leave certain array indices empty, so all
+ // indices' offsets need to be checked for emitted relocations.
+
+ // The offset of the 'values' member within the _struct_ (in bits)
+ // is the starting point of the array. Convert to bytes. Add VarSecinfo
+ // offset to get the absolute position in the ELF blob.
+ start := (member.OffsetBits / 8) + vs.Offset
+ // 'values' is encoded in BTF as a zero (variable) length struct
+ // member, and its contents run until the end of the VarSecinfo.
+ // Add VarSecinfo offset to get the absolute position in the ELF blob.
+ end := vs.Size + vs.Offset
+ // The size of an address in this section. This determines the width of
+ // an index in the array.
+ align := uint32(es.SectionHeader.Addralign)
+
+ // Check if variable-length section is aligned.
+ if (end-start)%align != 0 {
+ return nil, errors.New("unaligned static values section")
+ }
+ elems := (end - start) / align
+
+ if elems == 0 {
+ return nil, nil
+ }
+
+ contents := make([]MapKV, 0, elems)
+
+ // k is the array index, off is its corresponding ELF section offset.
+ for k, off := uint32(0), start; k < elems; k, off = k+1, off+align {
+ r, ok := es.relocations[uint64(off)]
+ if !ok {
+ continue
+ }
+
+ // Relocation exists for the current offset in the ELF section.
+ // Emit a value stub based on the type of relocation to be replaced by
+ // a real fd later in the pipeline before populating the map.
+ // Map keys are encoded in MapKV entries, so empty array indices are
+ // skipped here.
+ switch t := elf.ST_TYPE(r.Info); t {
+ case elf.STT_FUNC:
+ contents = append(contents, MapKV{uint32(k), programStub(r.Name)})
+ case elf.STT_OBJECT:
+ contents = append(contents, MapKV{uint32(k), mapStub(r.Name)})
+ default:
+ return nil, fmt.Errorf("unknown relocation type %v", t)
+ }
+ }
+
+ return contents, nil
+}
+
func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
for _, sec := range ec.sections {
if sec.kind != dataSection {
@@ -809,9 +925,9 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
return errors.New("data sections require BTF, make sure all consts are marked as static")
}
- btfMap, err := ec.btf.Datasec(sec.Name)
- if err != nil {
- return err
+ var datasec *btf.Datasec
+ if err := ec.btf.FindType(sec.Name, &datasec); err != nil {
+ return fmt.Errorf("data section %s: can't get BTF: %w", sec.Name, err)
}
data, err := sec.Data()
@@ -830,7 +946,7 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
ValueSize: uint32(len(data)),
MaxEntries: 1,
Contents: []MapKV{{uint32(0), data}},
- BTF: btfMap,
+ BTF: &btf.Map{Spec: ec.btf, Key: &btf.Void{}, Value: datasec},
}
switch sec.Name {
@@ -855,6 +971,8 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
}{
// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c
"socket": {SocketFilter, AttachNone, 0},
+ "sk_reuseport/migrate": {SkReuseport, AttachSkReuseportSelectOrMigrate, 0},
+ "sk_reuseport": {SkReuseport, AttachSkReuseportSelect, 0},
"seccomp": {SocketFilter, AttachNone, 0},
"kprobe/": {Kprobe, AttachNone, 0},
"uprobe/": {Kprobe, AttachNone, 0},
@@ -884,6 +1002,7 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
"fmod_ret.s/": {Tracing, AttachModifyReturn, unix.BPF_F_SLEEPABLE},
"fexit.s/": {Tracing, AttachTraceFExit, unix.BPF_F_SLEEPABLE},
"sk_lookup/": {SkLookup, AttachSkLookup, 0},
+ "freplace/": {Extension, AttachNone, 0},
"lsm/": {LSM, AttachLSMMac, 0},
"lsm.s/": {LSM, AttachLSMMac, unix.BPF_F_SLEEPABLE},
@@ -907,6 +1026,11 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
"cgroup/setsockopt": {CGroupSockopt, AttachCGroupSetsockopt, 0},
"classifier": {SchedCLS, AttachNone, 0},
"action": {SchedACT, AttachNone, 0},
+
+ "cgroup/getsockname4": {CGroupSockAddr, AttachCgroupInet4GetSockname, 0},
+ "cgroup/getsockname6": {CGroupSockAddr, AttachCgroupInet6GetSockname, 0},
+ "cgroup/getpeername4": {CGroupSockAddr, AttachCgroupInet4GetPeername, 0},
+ "cgroup/getpeername6": {CGroupSockAddr, AttachCgroupInet6GetPeername, 0},
}
for prefix, t := range types {
diff --git a/vendor/github.com/cilium/ebpf/elf_reader_fuzz.go b/vendor/github.com/cilium/ebpf/elf_reader_fuzz.go
index d46d135f2..5f4e0a0ad 100644
--- a/vendor/github.com/cilium/ebpf/elf_reader_fuzz.go
+++ b/vendor/github.com/cilium/ebpf/elf_reader_fuzz.go
@@ -1,3 +1,4 @@
+//go:build gofuzz
// +build gofuzz
// Use with https://github.com/dvyukov/go-fuzz
diff --git a/vendor/github.com/cilium/ebpf/info.go b/vendor/github.com/cilium/ebpf/info.go
index b95131ef5..65fa4d7d8 100644
--- a/vendor/github.com/cilium/ebpf/info.go
+++ b/vendor/github.com/cilium/ebpf/info.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/cilium/ebpf/internal"
+ "github.com/cilium/ebpf/internal/btf"
)
// MapInfo describes a map.
@@ -87,12 +88,16 @@ type ProgramInfo struct {
Tag string
// Name as supplied by user space at load time.
Name string
+ // BTF for the program.
+ btf btf.ID
+ // IDS map ids related to program.
+ ids []MapID
stats *programStats
}
func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
- info, err := bpfGetProgInfoByFD(fd)
+ info, err := bpfGetProgInfoByFD(fd, nil)
if errors.Is(err, syscall.EINVAL) {
return newProgramInfoFromProc(fd)
}
@@ -100,6 +105,15 @@ func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
return nil, err
}
+ var mapIDs []MapID
+ if info.nr_map_ids > 0 {
+ mapIDs = make([]MapID, info.nr_map_ids)
+ info, err = bpfGetProgInfoByFD(fd, mapIDs)
+ if err != nil {
+ return nil, err
+ }
+ }
+
return &ProgramInfo{
Type: ProgramType(info.prog_type),
id: ProgramID(info.id),
@@ -107,6 +121,8 @@ func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
Tag: hex.EncodeToString(info.tag[:]),
// name is available from 4.15.
Name: internal.CString(info.name[:]),
+ btf: btf.ID(info.btf_id),
+ ids: mapIDs,
stats: &programStats{
runtime: time.Duration(info.run_time_ns),
runCount: info.run_cnt,
@@ -142,6 +158,17 @@ func (pi *ProgramInfo) ID() (ProgramID, bool) {
return pi.id, pi.id > 0
}
+// BTFID returns the BTF ID associated with the program.
+//
+// Available from 5.0.
+//
+// The bool return value indicates whether this optional field is available and
+// populated. (The field may be available but not populated if the kernel
+// supports the field but the program was loaded without BTF information.)
+func (pi *ProgramInfo) BTFID() (btf.ID, bool) {
+ return pi.btf, pi.btf > 0
+}
+
// RunCount returns the total number of times the program was called.
//
// Can return 0 if the collection of statistics is not enabled. See EnableStats().
@@ -164,6 +191,13 @@ func (pi *ProgramInfo) Runtime() (time.Duration, bool) {
return time.Duration(0), false
}
+// MapIDs returns the maps related to the program.
+//
+// The bool return value indicates whether this optional field is available.
+func (pi *ProgramInfo) MapIDs() ([]MapID, bool) {
+ return pi.ids, pi.ids != nil
+}
+
func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
raw, err := fd.Value()
if err != nil {
diff --git a/vendor/github.com/cilium/ebpf/internal/BUILD.bazel b/vendor/github.com/cilium/ebpf/internal/BUILD.bazel
index 4568f4c93..4079687fb 100644
--- a/vendor/github.com/cilium/ebpf/internal/BUILD.bazel
+++ b/vendor/github.com/cilium/ebpf/internal/BUILD.bazel
@@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
+ "align.go",
"cpu.go",
"elf.go",
"endian.go",
diff --git a/vendor/github.com/cilium/ebpf/internal/align.go b/vendor/github.com/cilium/ebpf/internal/align.go
new file mode 100644
index 000000000..8b4f2658e
--- /dev/null
+++ b/vendor/github.com/cilium/ebpf/internal/align.go
@@ -0,0 +1,6 @@
+package internal
+
+// Align returns 'n' updated to 'alignment' boundary.
+func Align(n, alignment int) int {
+ return (int(n) + alignment - 1) / alignment * alignment
+}
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/BUILD.bazel b/vendor/github.com/cilium/ebpf/internal/btf/BUILD.bazel
index f2e218e6a..0d7915fc4 100644
--- a/vendor/github.com/cilium/ebpf/internal/btf/BUILD.bazel
+++ b/vendor/github.com/cilium/ebpf/internal/btf/BUILD.bazel
@@ -9,7 +9,9 @@ go_library(
"core.go",
"doc.go",
"ext_info.go",
+ "info.go",
"strings.go",
+ "syscalls.go",
"types.go",
],
importmap = "kubevirt.io/kubevirt/vendor/github.com/cilium/ebpf/internal/btf",
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/btf.go b/vendor/github.com/cilium/ebpf/internal/btf/btf.go
index 5da9e1192..2b5f6d226 100644
--- a/vendor/github.com/cilium/ebpf/internal/btf/btf.go
+++ b/vendor/github.com/cilium/ebpf/internal/btf/btf.go
@@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"math"
"os"
"reflect"
@@ -27,12 +26,15 @@ var (
ErrNoExtendedInfo = errors.New("no extended info")
)
+// ID represents the unique ID of a BTF object.
+type ID uint32
+
// Spec represents decoded BTF.
type Spec struct {
rawTypes []rawType
strings stringTable
types []Type
- namedTypes map[string][]namedType
+ namedTypes map[string][]NamedType
funcInfos map[string]extInfo
lineInfos map[string]extInfo
coreRelos map[string]coreRelos
@@ -61,15 +63,6 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
}
defer file.Close()
- btfSection, btfExtSection, sectionSizes, err := findBtfSections(file)
- if err != nil {
- return nil, err
- }
-
- if btfSection == nil {
- return nil, fmt.Errorf("btf: %w", ErrNotFound)
- }
-
symbols, err := file.Symbols()
if err != nil {
return nil, fmt.Errorf("can't read symbols: %v", err)
@@ -87,10 +80,6 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
}
secName := file.Sections[symbol.Section].Name
- if _, ok := sectionSizes[secName]; !ok {
- continue
- }
-
if symbol.Value > math.MaxUint32 {
return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name)
}
@@ -98,24 +87,10 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value)
}
- spec, err := loadNakedSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets)
- if err != nil {
- return nil, err
- }
-
- if btfExtSection == nil {
- return spec, nil
- }
-
- spec.funcInfos, spec.lineInfos, spec.coreRelos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
- if err != nil {
- return nil, fmt.Errorf("can't read ext info: %w", err)
- }
-
- return spec, nil
+ return loadSpecFromELF(file, variableOffsets)
}
-func findBtfSections(file *internal.SafeELFFile) (*elf.Section, *elf.Section, map[string]uint32, error) {
+func loadSpecFromELF(file *internal.SafeELFFile, variableOffsets map[variable]uint32) (*Spec, error) {
var (
btfSection *elf.Section
btfExtSection *elf.Section
@@ -134,33 +109,45 @@ func findBtfSections(file *internal.SafeELFFile) (*elf.Section, *elf.Section, ma
}
if sec.Size > math.MaxUint32 {
- return nil, nil, nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
+ return nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
}
sectionSizes[sec.Name] = uint32(sec.Size)
}
}
- return btfSection, btfExtSection, sectionSizes, nil
-}
-func loadSpecFromVmlinux(rd io.ReaderAt) (*Spec, error) {
- file, err := internal.NewSafeELFFile(rd)
+ if btfSection == nil {
+ return nil, fmt.Errorf("btf: %w", ErrNotFound)
+ }
+
+ spec, err := loadRawSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets)
if err != nil {
return nil, err
}
- defer file.Close()
- btfSection, _, _, err := findBtfSections(file)
- if err != nil {
- return nil, fmt.Errorf(".BTF ELF section: %s", err)
+ if btfExtSection == nil {
+ return spec, nil
}
- if btfSection == nil {
- return nil, fmt.Errorf("unable to find .BTF ELF section")
+
+ spec.funcInfos, spec.lineInfos, spec.coreRelos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
+ if err != nil {
+ return nil, fmt.Errorf("can't read ext info: %w", err)
}
- return loadNakedSpec(btfSection.Open(), file.ByteOrder, nil, nil)
+
+ return spec, nil
+}
+
+// LoadRawSpec reads a blob of BTF data that isn't wrapped in an ELF file.
+//
+// Prefer using LoadSpecFromReader, since this function only supports a subset
+// of BTF.
+func LoadRawSpec(btf io.Reader, bo binary.ByteOrder) (*Spec, error) {
+ // This will return an error if we encounter a Datasec, since we can't fix
+ // it up.
+ return loadRawSpec(btf, bo, nil, nil)
}
-func loadNakedSpec(btf io.ReadSeeker, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) {
+func loadRawSpec(btf io.Reader, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) {
rawTypes, rawStrings, err := parseBTF(btf, bo)
if err != nil {
return nil, err
@@ -217,7 +204,7 @@ func loadKernelSpec() (*Spec, error) {
if err == nil {
defer fh.Close()
- return loadNakedSpec(fh, internal.NativeEndian, nil, nil)
+ return LoadRawSpec(fh, internal.NativeEndian)
}
// use same list of locations as libbpf
@@ -241,14 +228,20 @@ func loadKernelSpec() (*Spec, error) {
}
defer fh.Close()
- return loadSpecFromVmlinux(fh)
+ file, err := internal.NewSafeELFFile(fh)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ return loadSpecFromELF(file, nil)
}
return nil, fmt.Errorf("no BTF for kernel version %s: %w", release, internal.ErrNotSupported)
}
-func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) ([]rawType, stringTable, error) {
- rawBTF, err := ioutil.ReadAll(btf)
+func parseBTF(btf io.Reader, bo binary.ByteOrder) ([]rawType, stringTable, error) {
+ rawBTF, err := io.ReadAll(btf)
if err != nil {
return nil, nil, fmt.Errorf("can't read BTF: %v", err)
}
@@ -357,6 +350,30 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s
return nil
}
+// Copy creates a copy of Spec.
+func (s *Spec) Copy() *Spec {
+ types, _ := copyTypes(s.types, nil)
+ namedTypes := make(map[string][]NamedType)
+ for _, typ := range types {
+ if named, ok := typ.(NamedType); ok {
+ name := essentialName(named.TypeName())
+ namedTypes[name] = append(namedTypes[name], named)
+ }
+ }
+
+ // NB: Other parts of spec are not copied since they are immutable.
+ return &Spec{
+ s.rawTypes,
+ s.strings,
+ types,
+ namedTypes,
+ s.funcInfos,
+ s.lineInfos,
+ s.coreRelos,
+ s.byteOrder,
+ }
+}
+
type marshalOpts struct {
ByteOrder binary.ByteOrder
StripFuncLinkage bool
@@ -447,36 +464,37 @@ func (s *Spec) Program(name string, length uint64) (*Program, error) {
return &Program{s, length, funcInfos, lineInfos, relos}, nil
}
-// Datasec returns the BTF required to create maps which represent data sections.
-func (s *Spec) Datasec(name string) (*Map, error) {
- var datasec Datasec
- if err := s.FindType(name, &datasec); err != nil {
- return nil, fmt.Errorf("data section %s: can't get BTF: %w", name, err)
- }
-
- m := NewMap(s, &Void{}, &datasec)
- return &m, nil
-}
-
// FindType searches for a type with a specific name.
//
-// hint determines the type of the returned Type.
+// Called T a type that satisfies Type, typ must be a non-nil **T.
+// On success, the address of the found type will be copied in typ.
//
// Returns an error wrapping ErrNotFound if no matching
// type exists in spec.
-func (s *Spec) FindType(name string, typ Type) error {
- var (
- wanted = reflect.TypeOf(typ)
- candidate Type
- )
+func (s *Spec) FindType(name string, typ interface{}) error {
+ typValue := reflect.ValueOf(typ)
+ if typValue.Kind() != reflect.Ptr {
+ return fmt.Errorf("%T is not a pointer", typ)
+ }
+
+ typPtr := typValue.Elem()
+ if !typPtr.CanSet() {
+ return fmt.Errorf("%T cannot be set", typ)
+ }
+ wanted := typPtr.Type()
+ if !wanted.AssignableTo(reflect.TypeOf((*Type)(nil)).Elem()) {
+ return fmt.Errorf("%T does not satisfy Type interface", typ)
+ }
+
+ var candidate Type
for _, typ := range s.namedTypes[essentialName(name)] {
if reflect.TypeOf(typ) != wanted {
continue
}
// Match against the full name, not just the essential one.
- if typ.name() != name {
+ if typ.TypeName() != name {
continue
}
@@ -491,15 +509,15 @@ func (s *Spec) FindType(name string, typ Type) error {
return fmt.Errorf("type %s: %w", name, ErrNotFound)
}
- cpy, _ := copyType(candidate, nil)
- value := reflect.Indirect(reflect.ValueOf(cpy))
- reflect.Indirect(reflect.ValueOf(typ)).Set(value)
+ typPtr.Set(reflect.ValueOf(candidate))
+
return nil
}
// Handle is a reference to BTF loaded into the kernel.
type Handle struct {
- fd *internal.FD
+ spec *Spec
+ fd *internal.FD
}
// NewHandle loads BTF into the kernel.
@@ -541,7 +559,32 @@ func NewHandle(spec *Spec) (*Handle, error) {
return nil, internal.ErrorWithLog(err, logBuf, logErr)
}
- return &Handle{fd}, nil
+ return &Handle{spec.Copy(), fd}, nil
+}
+
+// NewHandleFromID returns the BTF handle for a given id.
+//
+// Returns ErrNotExist, if there is no BTF with the given id.
+//
+// Requires CAP_SYS_ADMIN.
+func NewHandleFromID(id ID) (*Handle, error) {
+ fd, err := internal.BPFObjGetFDByID(internal.BPF_BTF_GET_FD_BY_ID, uint32(id))
+ if err != nil {
+ return nil, fmt.Errorf("get BTF by id: %w", err)
+ }
+
+ info, err := newInfoFromFd(fd)
+ if err != nil {
+ _ = fd.Close()
+ return nil, fmt.Errorf("get BTF spec for handle: %w", err)
+ }
+
+ return &Handle{info.BTF, fd}, nil
+}
+
+// Spec returns the Spec that defined the BTF loaded into the kernel.
+func (h *Handle) Spec() *Spec {
+ return h.spec
}
// Close destroys the handle.
@@ -563,43 +606,8 @@ func (h *Handle) FD() int {
// Map is the BTF for a map.
type Map struct {
- spec *Spec
- key, value Type
-}
-
-// NewMap returns a new Map containing the given values.
-// The key and value arguments are initialized to Void if nil values are given.
-func NewMap(spec *Spec, key Type, value Type) Map {
- if key == nil {
- key = &Void{}
- }
- if value == nil {
- value = &Void{}
- }
-
- return Map{
- spec: spec,
- key: key,
- value: value,
- }
-}
-
-// 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
-}
-
-// 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
+ Spec *Spec
+ Key, Value Type
}
// Program is the BTF information for a stream of instructions.
@@ -610,68 +618,59 @@ type Program struct {
coreRelos coreRelos
}
-// 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
+// Spec returns the BTF spec of this program.
+func (p *Program) Spec() *Spec {
+ return p.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)
+// Append the information from other to the Program.
+func (p *Program) Append(other *Program) error {
+ if other.spec != p.spec {
+ return fmt.Errorf("can't append program with different BTF specs")
+ }
+
+ funcInfos, err := p.funcInfos.append(other.funcInfos, p.length)
if err != nil {
return fmt.Errorf("func infos: %w", err)
}
- lineInfos, err := s.lineInfos.append(other.lineInfos, s.length)
+ lineInfos, err := p.lineInfos.append(other.lineInfos, p.length)
if err != nil {
return fmt.Errorf("line infos: %w", err)
}
- s.funcInfos = funcInfos
- s.lineInfos = lineInfos
- s.coreRelos = s.coreRelos.append(other.coreRelos, s.length)
- s.length += other.length
+ p.funcInfos = funcInfos
+ p.lineInfos = lineInfos
+ p.coreRelos = p.coreRelos.append(other.coreRelos, p.length)
+ p.length += other.length
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()
+// FuncInfos returns the binary form of BTF function infos.
+func (p *Program) FuncInfos() (recordSize uint32, bytes []byte, err error) {
+ bytes, err = p.funcInfos.MarshalBinary()
if err != nil {
- return 0, nil, err
+ return 0, nil, fmt.Errorf("func infos: %w", err)
}
- return s.funcInfos.recordSize, bytes, nil
+ return p.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()
+// LineInfos returns the binary form of BTF line infos.
+func (p *Program) LineInfos() (recordSize uint32, bytes []byte, err error) {
+ bytes, err = p.lineInfos.MarshalBinary()
if err != nil {
- return 0, nil, err
+ return 0, nil, fmt.Errorf("line infos: %w", err)
}
- return s.lineInfos.recordSize, bytes, nil
+ return p.lineInfos.recordSize, bytes, nil
}
-// ProgramFixups returns the changes required to adjust the program to the target.
+// Fixups returns the changes required to adjust the program to the target.
//
-// This is a free function instead of a method to hide it from users
-// of package ebpf.
-func ProgramFixups(s *Program, target *Spec) (COREFixups, error) {
- if len(s.coreRelos) == 0 {
+// Passing a nil target will relocate against the running kernel.
+func (p *Program) Fixups(target *Spec) (COREFixups, error) {
+ if len(p.coreRelos) == 0 {
return nil, nil
}
@@ -683,7 +682,7 @@ func ProgramFixups(s *Program, target *Spec) (COREFixups, error) {
}
}
- return coreRelocate(s.spec, target, s.coreRelos)
+ return coreRelocate(p.spec, target, p.coreRelos)
}
type bpfLoadBTFAttr struct {
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go b/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
index a5ef94512..d98c73ca5 100644
--- a/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
+++ b/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
@@ -31,6 +31,8 @@ const (
// Added ~5.1
kindVar
kindDatasec
+ // Added ~5.13
+ kindFloat
)
// FuncLinkage describes BTF function linkage metadata.
@@ -54,7 +56,7 @@ const (
const (
btfTypeKindShift = 24
- btfTypeKindLen = 4
+ btfTypeKindLen = 5
btfTypeVlenShift = 0
btfTypeVlenMask = 16
btfTypeKindFlagShift = 31
@@ -67,8 +69,8 @@ type btfType struct {
/* "info" bits arrangement
* bits 0-15: vlen (e.g. # of struct's members), linkage
* bits 16-23: unused
- * bits 24-27: kind (e.g. int, ptr, array...etc)
- * bits 28-30: unused
+ * bits 24-28: kind (e.g. int, ptr, array...etc)
+ * bits 29-30: unused
* bit 31: kind_flag, currently used by
* struct, union and fwd
*/
@@ -117,6 +119,8 @@ func (k btfKind) String() string {
return "Variable"
case kindDatasec:
return "Section"
+ case kindFloat:
+ return "Float"
default:
return fmt.Sprintf("Unknown (%d)", k)
}
@@ -260,6 +264,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
data = new(btfVariable)
case kindDatasec:
data = make([]btfVarSecinfo, header.Vlen())
+ case kindFloat:
default:
return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
}
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/core.go b/vendor/github.com/cilium/ebpf/internal/btf/core.go
index 7c888f602..d02df9d50 100644
--- a/vendor/github.com/cilium/ebpf/internal/btf/core.go
+++ b/vendor/github.com/cilium/ebpf/internal/btf/core.go
@@ -234,13 +234,13 @@ func coreRelocate(local, target *Spec, relos coreRelos) (COREFixups, error) {
}
localType := local.types[id]
- named, ok := localType.(namedType)
- if !ok || named.name() == "" {
+ named, ok := localType.(NamedType)
+ if !ok || named.TypeName() == "" {
return nil, fmt.Errorf("relocate unnamed or anonymous type %s: %w", localType, ErrNotSupported)
}
relos := relosByID[id]
- targets := target.namedTypes[named.essentialName()]
+ targets := target.namedTypes[essentialName(named.TypeName())]
fixups, err := coreCalculateFixups(localType, targets, relos)
if err != nil {
return nil, fmt.Errorf("relocate %s: %w", localType, err)
@@ -262,7 +262,7 @@ var errImpossibleRelocation = errors.New("impossible relocation")
//
// The best target is determined by scoring: the less poisoning we have to do
// the better the target is.
-func coreCalculateFixups(local Type, targets []namedType, relos coreRelos) ([]COREFixup, error) {
+func coreCalculateFixups(local Type, targets []NamedType, relos coreRelos) ([]COREFixup, error) {
localID := local.ID()
local, err := copyType(local, skipQualifierAndTypedef)
if err != nil {
@@ -467,8 +467,8 @@ func parseCoreAccessor(accessor string) (coreAccessor, error) {
return nil, fmt.Errorf("empty accessor")
}
- var result coreAccessor
parts := strings.Split(accessor, ":")
+ result := make(coreAccessor, 0, len(parts))
for _, part := range parts {
// 31 bits to avoid overflowing int on 32 bit platforms.
index, err := strconv.ParseUint(part, 10, 31)
@@ -564,7 +564,7 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
// This is an anonymous struct or union, ignore it.
local = localMember.Type
- localOffset += localMember.Offset
+ localOffset += localMember.OffsetBits
localMaybeFlex = false
continue
}
@@ -585,10 +585,10 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
local = localMember.Type
localMaybeFlex = acc == len(localMembers)-1
- localOffset += localMember.Offset
+ localOffset += localMember.OffsetBits
target = targetMember.Type
targetMaybeFlex = last
- targetOffset += targetMember.Offset
+ targetOffset += targetMember.OffsetBits
case *Array:
// For arrays, acc is the index in the target.
@@ -639,7 +639,7 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
// coreFindMember finds a member in a composite type while handling anonymous
// structs and unions.
-func coreFindMember(typ composite, name Name) (Member, bool, error) {
+func coreFindMember(typ composite, name string) (Member, bool, error) {
if name == "" {
return Member{}, false, errors.New("can't search for anonymous member")
}
@@ -670,7 +670,7 @@ func coreFindMember(typ composite, name Name) (Member, bool, error) {
for j, member := range members {
if member.Name == name {
// NB: This is safe because member is a copy.
- member.Offset += target.offset
+ member.OffsetBits += target.offset
return member, j == len(members)-1, nil
}
@@ -685,7 +685,7 @@ func coreFindMember(typ composite, name Name) (Member, bool, error) {
return Member{}, false, fmt.Errorf("anonymous non-composite type %T not allowed", member.Type)
}
- targets = append(targets, offsetTarget{comp, target.offset + member.Offset})
+ targets = append(targets, offsetTarget{comp, target.offset + member.OffsetBits})
}
}
@@ -704,9 +704,9 @@ func coreFindEnumValue(local Type, localAcc coreAccessor, target Type) (localVal
return nil, nil, errImpossibleRelocation
}
- localName := localValue.Name.essentialName()
+ localName := essentialName(localValue.Name)
for i, targetValue := range targetEnum.Values {
- if targetValue.Name.essentialName() != localName {
+ if essentialName(targetValue.Name) != localName {
continue
}
@@ -813,6 +813,7 @@ func coreAreTypesCompatible(localType Type, targetType Type) error {
* least one of enums should be anonymous;
* - for ENUMs, check sizes, names are ignored;
* - for INT, size and signedness are ignored;
+ * - any two FLOATs are always compatible;
* - for ARRAY, dimensionality is ignored, element types are checked for
* compatibility recursively;
* [ NB: coreAreMembersCompatible doesn't recurse, this check is done
@@ -848,16 +849,16 @@ func coreAreMembersCompatible(localType Type, targetType Type) error {
}
switch lv := localType.(type) {
- case *Array, *Pointer:
+ case *Array, *Pointer, *Float:
return nil
case *Enum:
tv := targetType.(*Enum)
- return doNamesMatch(lv.name(), tv.name())
+ return doNamesMatch(lv.Name, tv.Name)
case *Fwd:
tv := targetType.(*Fwd)
- return doNamesMatch(lv.name(), tv.name())
+ return doNamesMatch(lv.Name, tv.Name)
case *Int:
tv := targetType.(*Int)
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go b/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
index beba1bce6..cdae2ec40 100644
--- a/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
+++ b/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
@@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"github.com/cilium/ebpf/asm"
"github.com/cilium/ebpf/internal"
@@ -64,7 +63,7 @@ func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (f
// 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)
+ _, err = io.CopyN(io.Discard, r, remainder)
if err != nil {
return nil, nil, nil, fmt.Errorf("header padding: %v", err)
}
@@ -114,11 +113,16 @@ type extInfoRecord struct {
}
type extInfo struct {
+ byteOrder binary.ByteOrder
recordSize uint32
records []extInfoRecord
}
func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
+ if other.byteOrder != ei.byteOrder {
+ return extInfo{}, fmt.Errorf("ext_info byte order mismatch, want %v (got %v)", ei.byteOrder, other.byteOrder)
+ }
+
if other.recordSize != ei.recordSize {
return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
}
@@ -131,10 +135,14 @@ func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
Opaque: info.Opaque,
})
}
- return extInfo{ei.recordSize, records}, nil
+ return extInfo{ei.byteOrder, ei.recordSize, records}, nil
}
func (ei extInfo) MarshalBinary() ([]byte, error) {
+ if ei.byteOrder != internal.NativeEndian {
+ return nil, fmt.Errorf("%s is not the native byte order", ei.byteOrder)
+ }
+
if len(ei.records) == 0 {
return nil, nil
}
@@ -197,6 +205,7 @@ func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[st
}
result[secName] = extInfo{
+ bo,
recordSize,
records,
}
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/fuzz.go b/vendor/github.com/cilium/ebpf/internal/btf/fuzz.go
index 37e043fd3..220b285af 100644
--- a/vendor/github.com/cilium/ebpf/internal/btf/fuzz.go
+++ b/vendor/github.com/cilium/ebpf/internal/btf/fuzz.go
@@ -1,3 +1,4 @@
+//go:build gofuzz
// +build gofuzz
// Use with https://github.com/dvyukov/go-fuzz
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/info.go b/vendor/github.com/cilium/ebpf/internal/btf/info.go
new file mode 100644
index 000000000..6a9b5d2e0
--- /dev/null
+++ b/vendor/github.com/cilium/ebpf/internal/btf/info.go
@@ -0,0 +1,48 @@
+package btf
+
+import (
+ "bytes"
+
+ "github.com/cilium/ebpf/internal"
+)
+
+// info describes a BTF object.
+type info struct {
+ BTF *Spec
+ ID ID
+ // Name is an identifying name for the BTF, currently only used by the
+ // kernel.
+ Name string
+ // KernelBTF is true if the BTf originated with the kernel and not
+ // userspace.
+ KernelBTF bool
+}
+
+func newInfoFromFd(fd *internal.FD) (*info, error) {
+ // We invoke the syscall once with a empty BTF and name buffers to get size
+ // information to allocate buffers. Then we invoke it a second time with
+ // buffers to receive the data.
+ bpfInfo, err := bpfGetBTFInfoByFD(fd, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ btfBuffer := make([]byte, bpfInfo.btfSize)
+ nameBuffer := make([]byte, bpfInfo.nameLen)
+ bpfInfo, err = bpfGetBTFInfoByFD(fd, btfBuffer, nameBuffer)
+ if err != nil {
+ return nil, err
+ }
+
+ spec, err := loadRawSpec(bytes.NewReader(btfBuffer), internal.NativeEndian, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return &info{
+ BTF: spec,
+ ID: ID(bpfInfo.id),
+ Name: internal.CString(nameBuffer),
+ KernelBTF: bpfInfo.kernelBTF != 0,
+ }, nil
+}
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/strings.go b/vendor/github.com/cilium/ebpf/internal/btf/strings.go
index 8782643a0..9876aa227 100644
--- a/vendor/github.com/cilium/ebpf/internal/btf/strings.go
+++ b/vendor/github.com/cilium/ebpf/internal/btf/strings.go
@@ -5,13 +5,12 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
)
type stringTable []byte
func readStringTable(r io.Reader) (stringTable, error) {
- contents, err := ioutil.ReadAll(r)
+ contents, err := io.ReadAll(r)
if err != nil {
return nil, fmt.Errorf("can't read string table: %v", err)
}
@@ -53,8 +52,3 @@ func (st stringTable) Lookup(offset uint32) (string, error) {
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/syscalls.go b/vendor/github.com/cilium/ebpf/internal/btf/syscalls.go
new file mode 100644
index 000000000..a4f80abd0
--- /dev/null
+++ b/vendor/github.com/cilium/ebpf/internal/btf/syscalls.go
@@ -0,0 +1,31 @@
+package btf
+
+import (
+ "fmt"
+ "unsafe"
+
+ "github.com/cilium/ebpf/internal"
+)
+
+type bpfBTFInfo struct {
+ btf internal.Pointer
+ btfSize uint32
+ id uint32
+ name internal.Pointer
+ nameLen uint32
+ kernelBTF uint32
+}
+
+func bpfGetBTFInfoByFD(fd *internal.FD, btf, name []byte) (*bpfBTFInfo, error) {
+ info := bpfBTFInfo{
+ btf: internal.NewSlicePointer(btf),
+ btfSize: uint32(len(btf)),
+ name: internal.NewSlicePointer(name),
+ nameLen: uint32(len(name)),
+ }
+ if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
+ return nil, fmt.Errorf("can't get program info: %w", err)
+ }
+
+ return &info, nil
+}
diff --git a/vendor/github.com/cilium/ebpf/internal/btf/types.go b/vendor/github.com/cilium/ebpf/internal/btf/types.go
index 62aa31bcd..5c8e7c6e5 100644
--- a/vendor/github.com/cilium/ebpf/internal/btf/types.go
+++ b/vendor/github.com/cilium/ebpf/internal/btf/types.go
@@ -30,27 +30,26 @@ type Type interface {
walk(*typeDeque)
}
-// namedType is a type with a name.
-//
-// Most named types simply embed Name.
-type namedType interface {
+// NamedType is a type with a name.
+type NamedType interface {
Type
- name() string
- essentialName() string
-}
-
-// Name identifies a type.
-//
-// Anonymous types have an empty name.
-type Name string
-func (n Name) name() string {
- return string(n)
+ // Name of the type, empty for anonymous types.
+ TypeName() string
}
-func (n Name) essentialName() string {
- return essentialName(string(n))
-}
+var (
+ _ NamedType = (*Int)(nil)
+ _ NamedType = (*Struct)(nil)
+ _ NamedType = (*Union)(nil)
+ _ NamedType = (*Enum)(nil)
+ _ NamedType = (*Fwd)(nil)
+ _ NamedType = (*Func)(nil)
+ _ NamedType = (*Typedef)(nil)
+ _ NamedType = (*Var)(nil)
+ _ NamedType = (*Datasec)(nil)
+ _ NamedType = (*Float)(nil)
+)
// Void is the unit type of BTF.
type Void struct{}
@@ -72,19 +71,17 @@ const (
// Int is an integer of a given length.
type Int struct {
TypeID
- Name
+ Name string
// The size of the integer in bytes.
Size uint32
Encoding IntEncoding
- // Offset is the starting bit offset. Currently always 0.
+ // OffsetBits is the starting bit offset. Currently always 0.
// See https://www.kernel.org/doc/html/latest/bpf/btf.html#btf-kind-int
- Offset uint32
- Bits byte
+ OffsetBits uint32
+ Bits byte
}
-var _ namedType = (*Int)(nil)
-
func (i *Int) String() string {
var s strings.Builder
@@ -110,15 +107,16 @@ func (i *Int) String() string {
return s.String()
}
-func (i *Int) size() uint32 { return i.Size }
-func (i *Int) walk(*typeDeque) {}
+func (i *Int) TypeName() string { return i.Name }
+func (i *Int) size() uint32 { return i.Size }
+func (i *Int) walk(*typeDeque) {}
func (i *Int) copy() Type {
cpy := *i
return &cpy
}
func (i *Int) isBitfield() bool {
- return i.Offset > 0
+ return i.OffsetBits > 0
}
// Pointer is a pointer to another type.
@@ -158,7 +156,7 @@ func (arr *Array) copy() Type {
// Struct is a compound type of consecutive members.
type Struct struct {
TypeID
- Name
+ Name string
// The size of the struct including padding, in bytes
Size uint32
Members []Member
@@ -168,6 +166,8 @@ func (s *Struct) String() string {
return fmt.Sprintf("struct#%d[%q]", s.TypeID, s.Name)
}
+func (s *Struct) TypeName() string { return s.Name }
+
func (s *Struct) size() uint32 { return s.Size }
func (s *Struct) walk(tdq *typeDeque) {
@@ -189,7 +189,7 @@ func (s *Struct) members() []Member {
// Union is a compound type where members occupy the same memory.
type Union struct {
TypeID
- Name
+ Name string
// The size of the union including padding, in bytes.
Size uint32
Members []Member
@@ -199,6 +199,8 @@ func (u *Union) String() string {
return fmt.Sprintf("union#%d[%q]", u.TypeID, u.Name)
}
+func (u *Union) TypeName() string { return u.Name }
+
func (u *Union) size() uint32 { return u.Size }
func (u *Union) walk(tdq *typeDeque) {
@@ -236,17 +238,17 @@ var (
//
// It is not a valid Type.
type Member struct {
- Name
+ Name string
Type Type
- // Offset is the bit offset of this member
- Offset uint32
+ // OffsetBits is the bit offset of this member.
+ OffsetBits uint32
BitfieldSize uint32
}
// Enum lists possible values.
type Enum struct {
TypeID
- Name
+ Name string
Values []EnumValue
}
@@ -254,11 +256,13 @@ func (e *Enum) String() string {
return fmt.Sprintf("enum#%d[%q]", e.TypeID, e.Name)
}
+func (e *Enum) TypeName() string { return e.Name }
+
// EnumValue is part of an Enum
//
// Is is not a valid Type
type EnumValue struct {
- Name
+ Name string
Value int32
}
@@ -294,7 +298,7 @@ func (fk FwdKind) String() string {
// Fwd is a forward declaration of a Type.
type Fwd struct {
TypeID
- Name
+ Name string
Kind FwdKind
}
@@ -302,6 +306,8 @@ func (f *Fwd) String() string {
return fmt.Sprintf("fwd#%d[%s %q]", f.TypeID, f.Kind, f.Name)
}
+func (f *Fwd) TypeName() string { return f.Name }
+
func (f *Fwd) walk(*typeDeque) {}
func (f *Fwd) copy() Type {
cpy := *f
@@ -311,7 +317,7 @@ func (f *Fwd) copy() Type {
// Typedef is an alias of a Type.
type Typedef struct {
TypeID
- Name
+ Name string
Type Type
}
@@ -319,6 +325,8 @@ func (td *Typedef) String() string {
return fmt.Sprintf("typedef#%d[%q #%d]", td.TypeID, td.Name, td.Type.ID())
}
+func (td *Typedef) TypeName() string { return td.Name }
+
func (td *Typedef) walk(tdq *typeDeque) { tdq.push(&td.Type) }
func (td *Typedef) copy() Type {
cpy := *td
@@ -379,7 +387,7 @@ func (r *Restrict) copy() Type {
// Func is a function definition.
type Func struct {
TypeID
- Name
+ Name string
Type Type
Linkage FuncLinkage
}
@@ -388,6 +396,8 @@ func (f *Func) String() string {
return fmt.Sprintf("func#%d[%s %q proto=#%d]", f.TypeID, f.Linkage, f.Name, f.Type.ID())
}
+func (f *Func) TypeName() string { return f.Name }
+
func (f *Func) walk(tdq *typeDeque) { tdq.push(&f.Type) }
func (f *Func) copy() Type {
cpy := *f
@@ -426,14 +436,14 @@ func (fp *FuncProto) copy() Type {
}
type FuncParam struct {
- Name
+ Name string
Type Type
}
// Var is a global variable.
type Var struct {
TypeID
- Name
+ Name string
Type Type
Linkage VarLinkage
}
@@ -442,6 +452,8 @@ func (v *Var) String() string {
return fmt.Sprintf("var#%d[%s %q]", v.TypeID, v.Linkage, v.Name)
}
+func (v *Var) TypeName() string { return v.Name }
+
func (v *Var) walk(tdq *typeDeque) { tdq.push(&v.Type) }
func (v *Var) copy() Type {
cpy := *v
@@ -451,7 +463,7 @@ func (v *Var) copy() Type {
// Datasec is a global program section containing data.
type Datasec struct {
TypeID
- Name
+ Name string
Size uint32
Vars []VarSecinfo
}
@@ -460,6 +472,8 @@ func (ds *Datasec) String() string {
return fmt.Sprintf("section#%d[%q]", ds.TypeID, ds.Name)
}
+func (ds *Datasec) TypeName() string { return ds.Name }
+
func (ds *Datasec) size() uint32 { return ds.Size }
func (ds *Datasec) walk(tdq *typeDeque) {
@@ -475,7 +489,7 @@ func (ds *Datasec) copy() Type {
return &cpy
}
-// VarSecinfo describes variable in a Datasec
+// VarSecinfo describes variable in a Datasec.
//
// It is not a valid Type.
type VarSecinfo struct {
@@ -484,6 +498,27 @@ type VarSecinfo struct {
Size uint32
}
+// Float is a float of a given length.
+type Float struct {
+ TypeID
+ Name string
+
+ // The size of the float in bytes.
+ Size uint32
+}
+
+func (f *Float) String() string {
+ return fmt.Sprintf("float%d#%d[%q]", f.Size*8, f.TypeID, f.Name)
+}
+
+func (f *Float) TypeName() string { return f.Name }
+func (f *Float) size() uint32 { return f.Size }
+func (f *Float) walk(*typeDeque) {}
+func (f *Float) copy() Type {
+ cpy := *f
+ return &cpy
+}
+
type sizer interface {
size() uint32
}
@@ -565,14 +600,36 @@ func Sizeof(typ Type) (int, error) {
//
// Returns any errors from transform verbatim.
func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
- var (
- copies = make(map[Type]Type)
- work typeDeque
- )
+ copies := make(copier)
+ return typ, copies.copy(&typ, transform)
+}
- for t := &typ; t != nil; t = work.pop() {
+// copy a slice of Types recursively.
+//
+// Types may form a cycle.
+//
+// Returns any errors from transform verbatim.
+func copyTypes(types []Type, transform func(Type) (Type, error)) ([]Type, error) {
+ result := make([]Type, len(types))
+ copy(result, types)
+
+ copies := make(copier)
+ for i := range result {
+ if err := copies.copy(&result[i], transform); err != nil {
+ return nil, err
+ }
+ }
+
+ return result, nil
+}
+
+type copier map[Type]Type
+
+func (c copier) copy(typ *Type, transform func(Type) (Type, error)) error {
+ var work typeDeque
+ for t := typ; t != nil; t = work.pop() {
// *t is the identity of the type.
- if cpy := copies[*t]; cpy != nil {
+ if cpy := c[*t]; cpy != nil {
*t = cpy
continue
}
@@ -581,21 +638,21 @@ func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
if transform != nil {
tf, err := transform(*t)
if err != nil {
- return nil, fmt.Errorf("copy %s: %w", typ, err)
+ return fmt.Errorf("copy %s: %w", *t, err)
}
cpy = tf.copy()
} else {
cpy = (*t).copy()
}
- copies[*t] = cpy
+ c[*t] = cpy
*t = cpy
// Mark any nested types for copying.
cpy.walk(&work)
}
- return typ, nil
+ return nil
}
// typeDeque keeps track of pointers to types which still
@@ -606,6 +663,10 @@ type typeDeque struct {
mask uint64
}
+func (dq *typeDeque) empty() bool {
+ return dq.read == dq.write
+}
+
// push adds a type to the stack.
func (dq *typeDeque) push(t *Type) {
if dq.write-dq.read < uint64(len(dq.types)) {
@@ -632,7 +693,7 @@ func (dq *typeDeque) push(t *Type) {
// shift returns the first element or null.
func (dq *typeDeque) shift() *Type {
- if dq.read == dq.write {
+ if dq.empty() {
return nil
}
@@ -645,7 +706,7 @@ func (dq *typeDeque) shift() *Type {
// pop returns the last element or null.
func (dq *typeDeque) pop() *Type {
- if dq.read == dq.write {
+ if dq.empty() {
return nil
}
@@ -674,7 +735,7 @@ func (dq *typeDeque) all() []*Type {
// Returns a map of named types (so, where NameOff is non-zero) and a slice of types
// indexed by TypeID. 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) (types []Type, namedTypes map[string][]namedType, err error) {
+func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, namedTypes map[string][]NamedType, err error) {
type fixupDef struct {
id TypeID
expectedKind btfKind
@@ -691,17 +752,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
// 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)
+ name, err := rawStrings.Lookup(btfMember.NameOff)
if err != nil {
return nil, fmt.Errorf("can't get name for member %d: %w", i, err)
}
m := Member{
- Name: name,
- Offset: btfMember.Offset,
+ Name: name,
+ OffsetBits: btfMember.Offset,
}
if kindFlag {
m.BitfieldSize = btfMember.Offset >> 24
- m.Offset &= 0xffffff
+ m.OffsetBits &= 0xffffff
}
members = append(members, m)
}
@@ -713,7 +774,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
types = make([]Type, 0, len(rawTypes))
types = append(types, (*Void)(nil))
- namedTypes = make(map[string][]namedType)
+ namedTypes = make(map[string][]NamedType)
for i, raw := range rawTypes {
var (
@@ -723,7 +784,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
typ Type
)
- name, err := rawStrings.LookupName(raw.NameOff)
+ name, err := rawStrings.Lookup(raw.NameOff)
if err != nil {
return nil, nil, fmt.Errorf("get name for type id %d: %w", id, err)
}
@@ -765,7 +826,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
rawvals := raw.data.([]btfEnum)
vals := make([]EnumValue, 0, len(rawvals))
for i, btfVal := range rawvals {
- name, err := rawStrings.LookupName(btfVal.NameOff)
+ name, err := rawStrings.Lookup(btfVal.NameOff)
if err != nil {
return nil, nil, fmt.Errorf("get name for enum value %d: %s", i, err)
}
@@ -812,7 +873,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
rawparams := raw.data.([]btfParam)
params := make([]FuncParam, 0, len(rawparams))
for i, param := range rawparams {
- name, err := rawStrings.LookupName(param.NameOff)
+ name, err := rawStrings.Lookup(param.NameOff)
if err != nil {
return nil, nil, fmt.Errorf("get name for func proto parameter %d: %s", i, err)
}
@@ -848,14 +909,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
}
typ = &Datasec{id, name, raw.SizeType, vars}
+ case kindFloat:
+ typ = &Float{id, name, raw.Size()}
+
default:
return nil, nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
}
types = append(types, typ)
- if named, ok := typ.(namedType); ok {
- if name := essentialName(named.name()); name != "" {
+ if named, ok := typ.(NamedType); ok {
+ if name := essentialName(named.TypeName()); name != "" {
namedTypes[name] = append(namedTypes[name], named)
}
}
diff --git a/vendor/github.com/cilium/ebpf/internal/cpu.go b/vendor/github.com/cilium/ebpf/internal/cpu.go
index d3424ba43..3affa1efb 100644
--- a/vendor/github.com/cilium/ebpf/internal/cpu.go
+++ b/vendor/github.com/cilium/ebpf/internal/cpu.go
@@ -2,7 +2,7 @@ package internal
import (
"fmt"
- "io/ioutil"
+ "os"
"strings"
"sync"
)
@@ -24,7 +24,7 @@ func PossibleCPUs() (int, error) {
}
func parseCPUsFromFile(path string) (int, error) {
- spec, err := ioutil.ReadFile(path)
+ spec, err := os.ReadFile(path)
if err != nil {
return 0, err
}
diff --git a/vendor/github.com/cilium/ebpf/internal/ptr_32_be.go b/vendor/github.com/cilium/ebpf/internal/ptr_32_be.go
index a56fbcc8e..8c114ddf4 100644
--- a/vendor/github.com/cilium/ebpf/internal/ptr_32_be.go
+++ b/vendor/github.com/cilium/ebpf/internal/ptr_32_be.go
@@ -1,3 +1,4 @@
+//go:build armbe || mips || mips64p32
// +build armbe mips mips64p32
package internal
diff --git a/vendor/github.com/cilium/ebpf/internal/ptr_32_le.go b/vendor/github.com/cilium/ebpf/internal/ptr_32_le.go
index be2ecfca7..e65a61e45 100644
--- a/vendor/github.com/cilium/ebpf/internal/ptr_32_le.go
+++ b/vendor/github.com/cilium/ebpf/internal/ptr_32_le.go
@@ -1,3 +1,4 @@
+//go:build 386 || amd64p32 || arm || mipsle || mips64p32le
// +build 386 amd64p32 arm mipsle mips64p32le
package internal
diff --git a/vendor/github.com/cilium/ebpf/internal/ptr_64.go b/vendor/github.com/cilium/ebpf/internal/ptr_64.go
index 69452dceb..71a3afe30 100644
--- a/vendor/github.com/cilium/ebpf/internal/ptr_64.go
+++ b/vendor/github.com/cilium/ebpf/internal/ptr_64.go
@@ -1,5 +1,5 @@
-// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le
-// +build !armbe,!mips,!mips64p32
+//go:build !386 && !amd64p32 && !arm && !mipsle && !mips64p32le && !armbe && !mips && !mips64p32
+// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le,!armbe,!mips,!mips64p32
package internal
diff --git a/vendor/github.com/cilium/ebpf/internal/syscall.go b/vendor/github.com/cilium/ebpf/internal/syscall.go
index b766e643e..b75037bb9 100644
--- a/vendor/github.com/cilium/ebpf/internal/syscall.go
+++ b/vendor/github.com/cilium/ebpf/internal/syscall.go
@@ -1,6 +1,7 @@
package internal
import (
+ "errors"
"fmt"
"path/filepath"
"runtime"
@@ -68,6 +69,48 @@ func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
return r1, err
}
+type BPFProgLoadAttr struct {
+ ProgType uint32
+ InsCount uint32
+ Instructions Pointer
+ License Pointer
+ LogLevel uint32
+ LogSize uint32
+ LogBuf Pointer
+ 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 uint32 // since 4.17 5e43f899b03a
+ ProgBTFFd uint32
+ FuncInfoRecSize uint32
+ FuncInfo Pointer
+ FuncInfoCnt uint32
+ LineInfoRecSize uint32
+ LineInfo Pointer
+ LineInfoCnt uint32
+ AttachBTFID uint32
+ AttachProgFd uint32
+}
+
+// BPFProgLoad wraps BPF_PROG_LOAD.
+func BPFProgLoad(attr *BPFProgLoadAttr) (*FD, error) {
+ for {
+ fd, err := BPF(BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
+ // As of ~4.20 the verifier can be interrupted by a signal,
+ // and returns EAGAIN in that case.
+ if errors.Is(err, unix.EAGAIN) {
+ continue
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ return NewFD(uint32(fd)), nil
+ }
+}
+
type BPFProgAttachAttr struct {
TargetFd uint32
AttachBpfFd uint32
@@ -180,6 +223,22 @@ func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error {
return nil
}
+type bpfGetFDByIDAttr struct {
+ id uint32
+ next uint32
+}
+
+// BPFObjGetInfoByFD wraps BPF_*_GET_FD_BY_ID.
+//
+// Available from 4.13.
+func BPFObjGetFDByID(cmd BPFCmd, id uint32) (*FD, error) {
+ attr := bpfGetFDByIDAttr{
+ id: id,
+ }
+ ptr, err := BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
+ return NewFD(uint32(ptr)), err
+}
+
// BPFObjName is a null-terminated string made up of
// 'A-Za-z0-9_' characters.
type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte
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 0a18eaf0c..9aa70fa78 100644
--- a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
+++ b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package unix
@@ -20,10 +21,11 @@ const (
EPERM = linux.EPERM
ESRCH = linux.ESRCH
ENODEV = linux.ENODEV
+ EBADF = linux.EBADF
+ E2BIG = linux.E2BIG
// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
ENOTSUPP = syscall.Errno(0x20c)
- EBADF = linux.EBADF
BPF_F_NO_PREALLOC = linux.BPF_F_NO_PREALLOC
BPF_F_NUMA_NODE = linux.BPF_F_NUMA_NODE
BPF_F_RDONLY = linux.BPF_F_RDONLY
@@ -35,6 +37,9 @@ const (
BPF_F_INNER_MAP = linux.BPF_F_INNER_MAP
BPF_OBJ_NAME_LEN = linux.BPF_OBJ_NAME_LEN
BPF_TAG_SIZE = linux.BPF_TAG_SIZE
+ BPF_RINGBUF_BUSY_BIT = linux.BPF_RINGBUF_BUSY_BIT
+ BPF_RINGBUF_DISCARD_BIT = linux.BPF_RINGBUF_DISCARD_BIT
+ BPF_RINGBUF_HDR_SZ = linux.BPF_RINGBUF_HDR_SZ
SYS_BPF = linux.SYS_BPF
F_DUPFD_CLOEXEC = linux.F_DUPFD_CLOEXEC
EPOLL_CTL_ADD = linux.EPOLL_CTL_ADD
@@ -69,11 +74,6 @@ type Statfs_t = linux.Statfs_t
// Rlimit is a wrapper
type Rlimit = linux.Rlimit
-// Setrlimit is a wrapper
-func Setrlimit(resource int, rlim *Rlimit) (err error) {
- return linux.Setrlimit(resource, rlim)
-}
-
// Syscall is a wrapper
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
return linux.Syscall(trap, a1, a2, a3)
@@ -202,3 +202,7 @@ func KernelRelease() (string, error) {
release := string(uname.Release[:end])
return release, nil
}
+
+func Prlimit(pid, resource int, new, old *Rlimit) error {
+ return linux.Prlimit(pid, resource, new, old)
+}
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 1b06defc0..4f50d896e 100644
--- a/vendor/github.com/cilium/ebpf/internal/unix/types_other.go
+++ b/vendor/github.com/cilium/ebpf/internal/unix/types_other.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package unix
@@ -21,6 +22,7 @@ const (
ESRCH = syscall.ESRCH
ENODEV = syscall.ENODEV
EBADF = syscall.Errno(0)
+ E2BIG = syscall.Errno(0)
// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
ENOTSUPP = syscall.Errno(0x20c)
@@ -35,6 +37,9 @@ const (
BPF_F_INNER_MAP = 0
BPF_OBJ_NAME_LEN = 0x10
BPF_TAG_SIZE = 0x8
+ BPF_RINGBUF_BUSY_BIT = 0
+ BPF_RINGBUF_DISCARD_BIT = 0
+ BPF_RINGBUF_HDR_SZ = 0
SYS_BPF = 321
F_DUPFD_CLOEXEC = 0x406
EPOLLIN = 0x1
@@ -86,11 +91,6 @@ type Rlimit struct {
Max uint64
}
-// Setrlimit is a wrapper
-func Setrlimit(resource int, rlim *Rlimit) (err error) {
- return errNonLinux
-}
-
// Syscall is a wrapper
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
return 0, 0, syscall.Errno(1)
@@ -261,3 +261,7 @@ func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags
func KernelRelease() (string, error) {
return "", errNonLinux
}
+
+func Prlimit(pid, resource int, new, old *Rlimit) error {
+ return errNonLinux
+}
diff --git a/vendor/github.com/cilium/ebpf/internal/version.go b/vendor/github.com/cilium/ebpf/internal/version.go
index 1a678bfe6..4915e5837 100644
--- a/vendor/github.com/cilium/ebpf/internal/version.go
+++ b/vendor/github.com/cilium/ebpf/internal/version.go
@@ -2,7 +2,7 @@ package internal
import (
"fmt"
- "io/ioutil"
+ "os"
"regexp"
"sync"
@@ -109,7 +109,7 @@ func detectKernelVersion() (Version, error) {
// Example format: Ubuntu 4.15.0-91.92-generic 4.15.18
// This method exists in the kernel itself, see d18acd15c
// ("perf tools: Fix kernel version error in ubuntu").
- if pvs, err := ioutil.ReadFile("/proc/version_signature"); err == nil {
+ if pvs, err := os.ReadFile("/proc/version_signature"); err == nil {
// If /proc/version_signature exists, failing to parse it is an error.
// It only exists on Ubuntu, where the real patch level is not obtainable
// through any other method.
diff --git a/vendor/github.com/cilium/ebpf/link/BUILD.bazel b/vendor/github.com/cilium/ebpf/link/BUILD.bazel
index b50621bbc..02492f319 100644
--- a/vendor/github.com/cilium/ebpf/link/BUILD.bazel
+++ b/vendor/github.com/cilium/ebpf/link/BUILD.bazel
@@ -5,6 +5,7 @@ go_library(
srcs = [
"cgroup.go",
"doc.go",
+ "freplace.go",
"iter.go",
"kprobe.go",
"link.go",
@@ -24,6 +25,7 @@ go_library(
"//vendor/github.com/cilium/ebpf:go_default_library",
"//vendor/github.com/cilium/ebpf/asm:go_default_library",
"//vendor/github.com/cilium/ebpf/internal:go_default_library",
+ "//vendor/github.com/cilium/ebpf/internal/btf:go_default_library",
"//vendor/github.com/cilium/ebpf/internal/unix:go_default_library",
],
)
diff --git a/vendor/github.com/cilium/ebpf/link/freplace.go b/vendor/github.com/cilium/ebpf/link/freplace.go
new file mode 100644
index 000000000..a698e1a9d
--- /dev/null
+++ b/vendor/github.com/cilium/ebpf/link/freplace.go
@@ -0,0 +1,88 @@
+package link
+
+import (
+ "fmt"
+
+ "github.com/cilium/ebpf"
+ "github.com/cilium/ebpf/internal/btf"
+)
+
+type FreplaceLink struct {
+ RawLink
+}
+
+// AttachFreplace attaches the given eBPF program to the function it replaces.
+//
+// The program and name can either be provided at link time, or can be provided
+// at program load time. If they were provided at load time, they should be nil
+// and empty respectively here, as they will be ignored by the kernel.
+// Examples:
+//
+// AttachFreplace(dispatcher, "function", replacement)
+// AttachFreplace(nil, "", replacement)
+func AttachFreplace(targetProg *ebpf.Program, name string, prog *ebpf.Program) (*FreplaceLink, error) {
+ if (name == "") != (targetProg == nil) {
+ return nil, fmt.Errorf("must provide both or neither of name and targetProg: %w", errInvalidInput)
+ }
+ if prog == nil {
+ return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
+ }
+ if prog.Type() != ebpf.Extension {
+ return nil, fmt.Errorf("eBPF program type %s is not an Extension: %w", prog.Type(), errInvalidInput)
+ }
+
+ var (
+ target int
+ typeID btf.TypeID
+ )
+ if targetProg != nil {
+ info, err := targetProg.Info()
+ if err != nil {
+ return nil, err
+ }
+ btfID, ok := info.BTFID()
+ if !ok {
+ return nil, fmt.Errorf("could not get BTF ID for program %s: %w", info.Name, errInvalidInput)
+ }
+ btfHandle, err := btf.NewHandleFromID(btfID)
+ if err != nil {
+ return nil, err
+ }
+ defer btfHandle.Close()
+
+ var function *btf.Func
+ if err := btfHandle.Spec().FindType(name, &function); err != nil {
+ return nil, err
+ }
+
+ target = targetProg.FD()
+ typeID = function.ID()
+ }
+
+ link, err := AttachRawLink(RawLinkOptions{
+ Target: target,
+ Program: prog,
+ Attach: ebpf.AttachNone,
+ BTF: typeID,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return &FreplaceLink{*link}, nil
+}
+
+// Update implements the Link interface.
+func (f *FreplaceLink) Update(new *ebpf.Program) error {
+ return fmt.Errorf("freplace update: %w", ErrNotSupported)
+}
+
+// LoadPinnedFreplace loads a pinned iterator from a bpffs.
+func LoadPinnedFreplace(fileName string, opts *ebpf.LoadPinOptions) (*FreplaceLink, error) {
+ link, err := LoadPinnedRawLink(fileName, TracingType, opts)
+ if err != nil {
+ return nil, err
+ }
+
+ return &FreplaceLink{*link}, err
+}
diff --git a/vendor/github.com/cilium/ebpf/link/kprobe.go b/vendor/github.com/cilium/ebpf/link/kprobe.go
index ea71d6d60..b6577b5a9 100644
--- a/vendor/github.com/cilium/ebpf/link/kprobe.go
+++ b/vendor/github.com/cilium/ebpf/link/kprobe.go
@@ -5,7 +5,6 @@ import (
"crypto/rand"
"errors"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -72,10 +71,11 @@ func (pt probeType) RetprobeBit() (uint64, error) {
// given kernel symbol starts executing. See /proc/kallsyms for available
// symbols. For example, printk():
//
-// Kprobe("printk", prog)
+// kp, err := Kprobe("printk", prog)
//
-// The resulting Link must be Closed during program shutdown to avoid leaking
-// system resources.
+// Losing the reference to the resulting Link (kp) will close the Kprobe
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
k, err := kprobe(symbol, prog, false)
if err != nil {
@@ -95,10 +95,11 @@ func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
// before the given kernel symbol exits, with the function stack left intact.
// See /proc/kallsyms for available symbols. For example, printk():
//
-// Kretprobe("printk", prog)
+// kp, err := Kretprobe("printk", prog)
//
-// The resulting Link must be Closed during program shutdown to avoid leaking
-// system resources.
+// Losing the reference to the resulting Link (kp) will close the Kretprobe
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
func Kretprobe(symbol string, prog *ebpf.Program) (Link, error) {
k, err := kprobe(symbol, prog, true)
if err != nil {
@@ -157,7 +158,7 @@ func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) {
// pmuKprobe opens a perf event based on the kprobe PMU.
// Returns os.ErrNotExist if the given symbol does not exist in the kernel.
func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
- return pmuProbe(kprobeType, symbol, "", 0, ret)
+ return pmuProbe(kprobeType, symbol, "", 0, perfAllThreads, ret)
}
// pmuProbe opens a perf event based on a Performance Monitoring Unit.
@@ -167,7 +168,7 @@ func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
// 33ea4b24277b "perf/core: Implement the 'perf_uprobe' PMU"
//
// Returns ErrNotSupported if the kernel doesn't support perf_[k,u]probe PMU
-func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
+func pmuProbe(typ probeType, symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
// Getting the PMU type will fail if the kernel doesn't support
// the perf_[k,u]probe PMU.
et, err := getPMUEventType(typ)
@@ -191,7 +192,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
switch typ {
case kprobeType:
// Create a pointer to a NUL-terminated string for the kernel.
- sp, err := unsafeStringPtr(symbol)
+ sp, err = unsafeStringPtr(symbol)
if err != nil {
return nil, err
}
@@ -202,7 +203,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
Config: config, // Retprobe flag
}
case uprobeType:
- sp, err := unsafeStringPtr(path)
+ sp, err = unsafeStringPtr(path)
if err != nil {
return nil, err
}
@@ -220,7 +221,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
}
}
- fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
+ fd, err := unix.PerfEventOpen(&attr, pid, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
@@ -228,6 +229,11 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, os.ErrNotExist)
}
+ // Since at least commit cb9a19fe4aa51, ENOTSUPP is returned
+ // when attempting to set a uprobe on a trap instruction.
+ if errors.Is(err, unix.ENOTSUPP) {
+ return nil, fmt.Errorf("failed setting uprobe on offset %#x (possible trap insn): %w", offset, err)
+ }
if err != nil {
return nil, fmt.Errorf("opening perf event: %w", err)
}
@@ -246,7 +252,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
// tracefsKprobe creates a Kprobe tracefs entry.
func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
- return tracefsProbe(kprobeType, symbol, "", 0, ret)
+ return tracefsProbe(kprobeType, symbol, "", 0, perfAllThreads, ret)
}
// tracefsProbe creates a trace event by writing an entry to <tracefs>/[k,u]probe_events.
@@ -255,7 +261,7 @@ func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
// Path and offset are only set in the case of uprobe(s) and are used to set
// the executable/library path on the filesystem and the offset where the probe is inserted.
// A perf event is then opened on the newly-created trace event and returned to the caller.
-func tracefsProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
+func tracefsProbe(typ probeType, symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
// Generate a random string for each trace event we attempt to create.
// This value is used as the 'group' token in tracefs to allow creating
// multiple kprobe trace events with the same name.
@@ -288,7 +294,7 @@ func tracefsProbe(typ probeType, symbol, path string, offset uint64, ret bool) (
}
// Kprobes are ephemeral tracepoints and share the same perf event type.
- fd, err := openTracepointPerfEvent(tid)
+ fd, err := openTracepointPerfEvent(tid, pid)
if err != nil {
return nil, err
}
@@ -413,7 +419,7 @@ func probePrefix(ret bool) string {
func determineRetprobeBit(typ probeType) (uint64, error) {
p := filepath.Join("/sys/bus/event_source/devices/", typ.String(), "/format/retprobe")
- data, err := ioutil.ReadFile(p)
+ data, err := os.ReadFile(p)
if err != nil {
return 0, err
}
diff --git a/vendor/github.com/cilium/ebpf/link/link.go b/vendor/github.com/cilium/ebpf/link/link.go
index 16cfff415..492658469 100644
--- a/vendor/github.com/cilium/ebpf/link/link.go
+++ b/vendor/github.com/cilium/ebpf/link/link.go
@@ -6,6 +6,7 @@ import (
"github.com/cilium/ebpf"
"github.com/cilium/ebpf/internal"
+ "github.com/cilium/ebpf/internal/btf"
)
var ErrNotSupported = internal.ErrNotSupported
@@ -29,8 +30,8 @@ type Link interface {
// Close frees resources.
//
- // The link will be broken unless it has been pinned. A link
- // may continue past the lifetime of the process if Close is
+ // The link will be broken unless it has been successfully pinned.
+ // A link may continue past the lifetime of the process if Close is
// not called.
Close() error
@@ -49,6 +50,8 @@ type RawLinkOptions struct {
Program *ebpf.Program
// Attach must match the attach type of Program.
Attach ebpf.AttachType
+ // BTF is the BTF of the attachment target.
+ BTF btf.TypeID
}
// RawLinkInfo contains metadata on a link.
@@ -83,9 +86,10 @@ func AttachRawLink(opts RawLinkOptions) (*RawLink, error) {
}
attr := bpfLinkCreateAttr{
- targetFd: uint32(opts.Target),
- progFd: uint32(progFd),
- attachType: opts.Attach,
+ targetFd: uint32(opts.Target),
+ progFd: uint32(progFd),
+ attachType: opts.Attach,
+ targetBTFID: uint32(opts.BTF),
}
fd, err := bpfLinkCreate(&attr)
if err != nil {
diff --git a/vendor/github.com/cilium/ebpf/link/perf_event.go b/vendor/github.com/cilium/ebpf/link/perf_event.go
index 5267a47ec..7e0443a75 100644
--- a/vendor/github.com/cilium/ebpf/link/perf_event.go
+++ b/vendor/github.com/cilium/ebpf/link/perf_event.go
@@ -4,7 +4,6 @@ import (
"bytes"
"errors"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"regexp"
@@ -236,7 +235,7 @@ func getPMUEventType(typ probeType) (uint64, error) {
// openTracepointPerfEvent opens a tracepoint-type perf event. System-wide
// [k,u]probes created by writing to <tracefs>/[k,u]probe_events are tracepoints
// behind the scenes, and can be attached to using these perf events.
-func openTracepointPerfEvent(tid uint64) (*internal.FD, error) {
+func openTracepointPerfEvent(tid uint64, pid int) (*internal.FD, error) {
attr := unix.PerfEventAttr{
Type: unix.PERF_TYPE_TRACEPOINT,
Config: tid,
@@ -245,7 +244,7 @@ func openTracepointPerfEvent(tid uint64) (*internal.FD, error) {
Wakeup: 1,
}
- fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
+ fd, err := unix.PerfEventOpen(&attr, pid, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
if err != nil {
return nil, fmt.Errorf("opening tracepoint perf event: %w", err)
}
@@ -263,7 +262,7 @@ func uint64FromFile(base string, path ...string) (uint64, error) {
return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput)
}
- data, err := ioutil.ReadFile(p)
+ data, err := os.ReadFile(p)
if err != nil {
return 0, fmt.Errorf("reading file %s: %w", p, err)
}
diff --git a/vendor/github.com/cilium/ebpf/link/syscalls.go b/vendor/github.com/cilium/ebpf/link/syscalls.go
index 30e8a8805..a61499438 100644
--- a/vendor/github.com/cilium/ebpf/link/syscalls.go
+++ b/vendor/github.com/cilium/ebpf/link/syscalls.go
@@ -88,10 +88,11 @@ var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replace
})
type bpfLinkCreateAttr struct {
- progFd uint32
- targetFd uint32
- attachType ebpf.AttachType
- flags uint32
+ progFd uint32
+ targetFd uint32
+ attachType ebpf.AttachType
+ flags uint32
+ targetBTFID uint32
}
func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {
diff --git a/vendor/github.com/cilium/ebpf/link/tracepoint.go b/vendor/github.com/cilium/ebpf/link/tracepoint.go
index b8ae04bf0..7423df86b 100644
--- a/vendor/github.com/cilium/ebpf/link/tracepoint.go
+++ b/vendor/github.com/cilium/ebpf/link/tracepoint.go
@@ -11,7 +11,11 @@ import (
// tracepoints. The top-level directory is the group, the event's subdirectory
// is the name. Example:
//
-// Tracepoint("syscalls", "sys_enter_fork", prog)
+// tp, err := Tracepoint("syscalls", "sys_enter_fork", prog)
+//
+// Losing the reference to the resulting Link (tp) will close the Tracepoint
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
//
// Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is
// only possible as of kernel 4.14 (commit cf5f5ce).
@@ -34,7 +38,7 @@ func Tracepoint(group, name string, prog *ebpf.Program) (Link, error) {
return nil, err
}
- fd, err := openTracepointPerfEvent(tid)
+ fd, err := openTracepointPerfEvent(tid, perfAllThreads)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/cilium/ebpf/link/uprobe.go b/vendor/github.com/cilium/ebpf/link/uprobe.go
index 2bc395ee3..59170ce04 100644
--- a/vendor/github.com/cilium/ebpf/link/uprobe.go
+++ b/vendor/github.com/cilium/ebpf/link/uprobe.go
@@ -25,14 +25,18 @@ var (
value uint64
err error
}{}
+
+ // ErrNoSymbol indicates that the given symbol was not found
+ // in the ELF symbols table.
+ ErrNoSymbol = errors.New("not found")
)
// Executable defines an executable program on the filesystem.
type Executable struct {
// Path of the executable on the filesystem.
path string
- // Parsed ELF symbols and dynamic symbols.
- symbols map[string]elf.Symbol
+ // Parsed ELF symbols and dynamic symbols offsets.
+ offsets map[string]uint64
}
// UprobeOptions defines additional parameters that will be used
@@ -41,6 +45,9 @@ type UprobeOptions struct {
// Symbol offset. Must be provided in case of external symbols (shared libs).
// If set, overrides the offset eventually parsed from the executable.
Offset uint64
+ // Only set the uprobe on the given process ID. Useful when tracing
+ // shared library calls or programs that have many running instances.
+ PID int
}
// To open a new Executable, use:
@@ -64,42 +71,84 @@ func OpenExecutable(path string) (*Executable, error) {
return nil, fmt.Errorf("parse ELF file: %w", err)
}
- var ex = Executable{
- path: path,
- symbols: make(map[string]elf.Symbol),
+ if se.Type != elf.ET_EXEC && se.Type != elf.ET_DYN {
+ // ELF is not an executable or a shared object.
+ return nil, errors.New("the given file is not an executable or a shared object")
}
- if err := ex.addSymbols(se.Symbols); err != nil {
- return nil, err
+
+ ex := Executable{
+ path: path,
+ offsets: make(map[string]uint64),
}
- if err := ex.addSymbols(se.DynamicSymbols); err != nil {
+ if err := ex.load(se); err != nil {
return nil, err
}
return &ex, nil
}
-func (ex *Executable) addSymbols(f func() ([]elf.Symbol, error)) error {
- // elf.Symbols and elf.DynamicSymbols return ErrNoSymbols if the section is not found.
- syms, err := f()
+func (ex *Executable) load(f *internal.SafeELFFile) error {
+ syms, err := f.Symbols()
if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
return err
}
+
+ dynsyms, err := f.DynamicSymbols()
+ if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
+ return err
+ }
+
+ syms = append(syms, dynsyms...)
+
for _, s := range syms {
if elf.ST_TYPE(s.Info) != elf.STT_FUNC {
// Symbol not associated with a function or other executable code.
continue
}
- ex.symbols[s.Name] = s
+
+ off := s.Value
+
+ // Loop over ELF segments.
+ for _, prog := range f.Progs {
+ // Skip uninteresting segments.
+ if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 {
+ continue
+ }
+
+ if prog.Vaddr <= s.Value && s.Value < (prog.Vaddr+prog.Memsz) {
+ // If the symbol value is contained in the segment, calculate
+ // the symbol offset.
+ //
+ // fn symbol offset = fn symbol VA - .text VA + .text offset
+ //
+ // stackoverflow.com/a/40249502
+ off = s.Value - prog.Vaddr + prog.Off
+ break
+ }
+ }
+
+ ex.offsets[s.Name] = off
}
+
return nil
}
-func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) {
- if s, ok := ex.symbols[symbol]; ok {
- return &s, nil
+func (ex *Executable) offset(symbol string) (uint64, error) {
+ if off, ok := ex.offsets[symbol]; ok {
+ // Symbols with location 0 from section undef are shared library calls and
+ // are relocated before the binary is executed. Dynamic linking is not
+ // implemented by the library, so mark this as unsupported for now.
+ //
+ // Since only offset values are stored and not elf.Symbol, if the value is 0,
+ // assume it's an external symbol.
+ if off == 0 {
+ return 0, fmt.Errorf("cannot resolve %s library call '%s', "+
+ "consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported)
+ }
+ return off, nil
}
- return nil, fmt.Errorf("symbol %s not found", symbol)
+ return 0, fmt.Errorf("symbol %s: %w", symbol, ErrNoSymbol)
}
// Uprobe attaches the given eBPF program to a perf event that fires when the
@@ -112,11 +161,14 @@ func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) {
// When using symbols which belongs to shared libraries,
// an offset must be provided via options:
//
-// ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
+// up, err := ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
+//
+// Losing the reference to the resulting Link (up) will close the Uprobe
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
//
-// The resulting Link must be Closed during program shutdown to avoid leaking
-// system resources. Functions provided by shared libraries can currently not
-// be traced and will result in an ErrNotSupported.
+// Functions provided by shared libraries can currently not be traced and
+// will result in an ErrNotSupported.
func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
u, err := ex.uprobe(symbol, prog, opts, false)
if err != nil {
@@ -141,11 +193,14 @@ func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
// When using symbols which belongs to shared libraries,
// an offset must be provided via options:
//
-// ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
+// up, err := ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
+//
+// Losing the reference to the resulting Link (up) will close the Uprobe
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
//
-// The resulting Link must be Closed during program shutdown to avoid leaking
-// system resources. Functions provided by shared libraries can currently not
-// be traced and will result in an ErrNotSupported.
+// Functions provided by shared libraries can currently not be traced and
+// will result in an ErrNotSupported.
func (ex *Executable) Uretprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
u, err := ex.uprobe(symbol, prog, opts, true)
if err != nil {
@@ -175,24 +230,20 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
if opts != nil && opts.Offset != 0 {
offset = opts.Offset
} else {
- sym, err := ex.symbol(symbol)
+ off, err := ex.offset(symbol)
if err != nil {
- return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, err)
- }
-
- // Symbols with location 0 from section undef are shared library calls and
- // are relocated before the binary is executed. Dynamic linking is not
- // implemented by the library, so mark this as unsupported for now.
- if sym.Section == elf.SHN_UNDEF && sym.Value == 0 {
- return nil, fmt.Errorf("cannot resolve %s library call '%s', "+
- "consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported)
+ return nil, err
}
+ offset = off
+ }
- offset = sym.Value
+ pid := perfAllThreads
+ if opts != nil && opts.PID != 0 {
+ pid = opts.PID
}
// Use uprobe PMU if the kernel has it available.
- tp, err := pmuUprobe(symbol, ex.path, offset, ret)
+ tp, err := pmuUprobe(symbol, ex.path, offset, pid, ret)
if err == nil {
return tp, nil
}
@@ -201,7 +252,7 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
}
// Use tracefs if uprobe PMU is missing.
- tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, ret)
+ tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, pid, ret)
if err != nil {
return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err)
}
@@ -210,13 +261,13 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
}
// pmuUprobe opens a perf event based on the uprobe PMU.
-func pmuUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
- return pmuProbe(uprobeType, symbol, path, offset, ret)
+func pmuUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
+ return pmuProbe(uprobeType, symbol, path, offset, pid, ret)
}
// tracefsUprobe creates a Uprobe tracefs entry.
-func tracefsUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
- return tracefsProbe(uprobeType, symbol, path, offset, ret)
+func tracefsUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
+ return tracefsProbe(uprobeType, symbol, path, offset, pid, ret)
}
// uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore.
diff --git a/vendor/github.com/cilium/ebpf/linker.go b/vendor/github.com/cilium/ebpf/linker.go
index 6c2efef9e..f3b1629e7 100644
--- a/vendor/github.com/cilium/ebpf/linker.go
+++ b/vendor/github.com/cilium/ebpf/linker.go
@@ -4,7 +4,6 @@ import (
"fmt"
"github.com/cilium/ebpf/asm"
- "github.com/cilium/ebpf/internal/btf"
)
// link resolves bpf-to-bpf calls.
@@ -40,7 +39,7 @@ func link(prog *ProgramSpec, libs []*ProgramSpec) error {
pending = append(pending, lib.Instructions)
if prog.BTF != nil && lib.BTF != nil {
- if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil {
+ if err := prog.BTF.Append(lib.BTF); err != nil {
return fmt.Errorf("linking BTF of %s: %w", lib.Name, err)
}
}
@@ -136,5 +135,25 @@ func fixupJumpsAndCalls(insns asm.Instructions) error {
}
}
+ // fixupBPFCalls replaces bpf_probe_read_{kernel,user}[_str] with bpf_probe_read[_str] on older kernels
+ // https://github.com/libbpf/libbpf/blob/master/src/libbpf.c#L6009
+ iter = insns.Iterate()
+ for iter.Next() {
+ ins := iter.Ins
+ if !ins.IsBuiltinCall() {
+ continue
+ }
+ switch asm.BuiltinFunc(ins.Constant) {
+ case asm.FnProbeReadKernel, asm.FnProbeReadUser:
+ if err := haveProbeReadKernel(); err != nil {
+ ins.Constant = int64(asm.FnProbeRead)
+ }
+ case asm.FnProbeReadKernelStr, asm.FnProbeReadUserStr:
+ if err := haveProbeReadKernel(); err != nil {
+ ins.Constant = int64(asm.FnProbeReadStr)
+ }
+ }
+ }
+
return nil
}
diff --git a/vendor/github.com/cilium/ebpf/map.go b/vendor/github.com/cilium/ebpf/map.go
index f257d88c0..cca387ead 100644
--- a/vendor/github.com/cilium/ebpf/map.go
+++ b/vendor/github.com/cilium/ebpf/map.go
@@ -1,6 +1,7 @@
package ebpf
import (
+ "bytes"
"errors"
"fmt"
"io"
@@ -65,6 +66,11 @@ type MapSpec struct {
// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
InnerMap *MapSpec
+ // Extra trailing bytes found in the ELF map definition when using structs
+ // larger than libbpf's bpf_map_def. Must be empty before instantiating
+ // the MapSpec into a Map.
+ Extra bytes.Reader
+
// The BTF associated with this map.
BTF *btf.Map
}
@@ -82,9 +88,12 @@ func (ms *MapSpec) Copy() *MapSpec {
}
cpy := *ms
+
cpy.Contents = make([]MapKV, len(ms.Contents))
copy(cpy.Contents, ms.Contents)
+
cpy.InnerMap = ms.InnerMap.Copy()
+
return &cpy
}
@@ -188,14 +197,24 @@ func NewMap(spec *MapSpec) (*Map, error) {
//
// The caller is responsible for ensuring the process' rlimit is set
// sufficiently high for locking memory during map creation. This can be done
-// by calling unix.Setrlimit with unix.RLIMIT_MEMLOCK prior to calling NewMapWithOptions.
+// by calling rlimit.RemoveMemlock() prior to calling NewMapWithOptions.
//
// May return an error wrapping ErrMapIncompatible.
func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) {
handles := newHandleCache()
defer handles.close()
- return newMapWithOptions(spec, opts, handles)
+ m, err := newMapWithOptions(spec, opts, handles)
+ if err != nil {
+ return nil, fmt.Errorf("creating map: %w", err)
+ }
+
+ err = m.finalize(spec)
+ if err != nil {
+ return nil, fmt.Errorf("populating map: %w", err)
+ }
+
+ return m, nil
}
func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) {
@@ -207,8 +226,12 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
switch spec.Pinning {
case PinByName:
- if spec.Name == "" || opts.PinPath == "" {
- return nil, fmt.Errorf("pin by name: missing Name or PinPath")
+ if spec.Name == "" {
+ return nil, fmt.Errorf("pin by name: missing Name")
+ }
+
+ if opts.PinPath == "" {
+ return nil, fmt.Errorf("pin by name: missing MapOptions.PinPath")
}
path := filepath.Join(opts.PinPath, spec.Name)
@@ -244,16 +267,19 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
return nil, errors.New("inner maps cannot be pinned")
}
- template, err := createMap(spec.InnerMap, nil, opts, handles)
+ template, err := spec.InnerMap.createMap(nil, opts, handles)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("inner map: %w", err)
}
defer template.Close()
+ // Intentionally skip populating and freezing (finalizing)
+ // the inner map template since it will be removed shortly.
+
innerFd = template.fd
}
- m, err := createMap(spec, innerFd, opts, handles)
+ m, err := spec.createMap(innerFd, opts, handles)
if err != nil {
return nil, err
}
@@ -269,7 +295,9 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
return m, nil
}
-func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) {
+// createMap validates the spec's properties and creates the map in the kernel
+// using the given opts. It does not populate or freeze the map.
+func (spec *MapSpec) createMap(inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) {
closeOnError := func(closer io.Closer) {
if err != nil {
closer.Close()
@@ -278,10 +306,16 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
spec = spec.Copy()
+ // Kernels 4.13 through 5.4 used a struct bpf_map_def that contained
+ // additional 'inner_map_idx' and later 'numa_node' fields.
+ // In order to support loading these definitions, tolerate the presence of
+ // extra bytes, but require them to be zeroes.
+ if _, err := io.Copy(internal.DiscardZeroes{}, &spec.Extra); err != nil {
+ return nil, errors.New("extra contains unhandled non-zero bytes, drain before creating map")
+ }
+
switch spec.Type {
- case ArrayOfMaps:
- fallthrough
- case HashOfMaps:
+ case ArrayOfMaps, HashOfMaps:
if err := haveNestedMaps(); err != nil {
return nil, err
}
@@ -350,7 +384,7 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
var btfDisabled bool
if spec.BTF != nil {
- handle, err := handles.btfHandle(btf.MapSpec(spec.BTF))
+ handle, err := handles.btfHandle(spec.BTF.Spec)
btfDisabled = errors.Is(err, btf.ErrNotSupported)
if err != nil && !btfDisabled {
return nil, fmt.Errorf("load BTF: %w", err)
@@ -358,15 +392,15 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
if handle != nil {
attr.BTFFd = uint32(handle.FD())
- attr.BTFKeyTypeID = uint32(btf.MapKey(spec.BTF).ID())
- attr.BTFValueTypeID = uint32(btf.MapValue(spec.BTF).ID())
+ attr.BTFKeyTypeID = uint32(spec.BTF.Key.ID())
+ attr.BTFValueTypeID = uint32(spec.BTF.Value.ID())
}
}
fd, err := internal.BPFMapCreate(&attr)
if err != nil {
if errors.Is(err, unix.EPERM) {
- return nil, fmt.Errorf("map create: RLIMIT_MEMLOCK may be too low: %w", err)
+ return nil, fmt.Errorf("map create: %w (MEMLOCK bay be too low, consider rlimit.RemoveMemlock)", err)
}
if btfDisabled {
return nil, fmt.Errorf("map create without BTF: %w", err)
@@ -380,19 +414,11 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
return nil, fmt.Errorf("map create: %w", err)
}
- if err := m.populate(spec.Contents); err != nil {
- return nil, fmt.Errorf("map create: can't set initial contents: %w", err)
- }
-
- if spec.Freeze {
- if err := m.Freeze(); err != nil {
- return nil, fmt.Errorf("can't freeze map: %w", err)
- }
- }
-
return m, nil
}
+// newMap allocates and returns a new Map structure.
+// Sets the fullValueSize on per-CPU maps.
func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEntries, flags uint32) (*Map, error) {
m := &Map{
name,
@@ -415,7 +441,7 @@ func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEn
return nil, err
}
- m.fullValueSize = align(int(valueSize), 8) * possibleCPUs
+ m.fullValueSize = internal.Align(int(valueSize), 8) * possibleCPUs
return m, nil
}
@@ -892,12 +918,21 @@ func (m *Map) Freeze() error {
return nil
}
-func (m *Map) populate(contents []MapKV) error {
- for _, kv := range contents {
+// finalize populates the Map according to the Contents specified
+// in spec and freezes the Map if requested by spec.
+func (m *Map) finalize(spec *MapSpec) error {
+ for _, kv := range spec.Contents {
if err := m.Put(kv.Key, kv.Value); err != nil {
- return fmt.Errorf("key %v: %w", kv.Key, err)
+ return fmt.Errorf("putting value: key %v: %w", kv.Key, err)
}
}
+
+ if spec.Freeze {
+ if err := m.Freeze(); err != nil {
+ return fmt.Errorf("freezing map: %w", err)
+ }
+ }
+
return nil
}
@@ -1212,7 +1247,7 @@ func MapGetNextID(startID MapID) (MapID, error) {
//
// Returns ErrNotExist, if there is no eBPF map with the given id.
func NewMapFromID(id MapID) (*Map, error) {
- fd, err := bpfObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id))
+ fd, err := internal.BPFObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id))
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/cilium/ebpf/marshalers.go b/vendor/github.com/cilium/ebpf/marshalers.go
index f2610eff9..e461d673d 100644
--- a/vendor/github.com/cilium/ebpf/marshalers.go
+++ b/vendor/github.com/cilium/ebpf/marshalers.go
@@ -8,6 +8,7 @@ import (
"fmt"
"reflect"
"runtime"
+ "sync"
"unsafe"
"github.com/cilium/ebpf/internal"
@@ -39,6 +40,10 @@ func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
// Returns an error if the given value isn't representable in exactly
// length bytes.
func marshalBytes(data interface{}, length int) (buf []byte, err error) {
+ if data == nil {
+ return nil, errors.New("can't marshal a nil value")
+ }
+
switch value := data.(type) {
case encoding.BinaryMarshaler:
buf, err = value.MarshalBinary()
@@ -77,22 +82,30 @@ func makeBuffer(dst interface{}, length int) (internal.Pointer, []byte) {
return internal.NewSlicePointer(buf), buf
}
+var bytesReaderPool = sync.Pool{
+ New: func() interface{} {
+ return new(bytes.Reader)
+ },
+}
+
// unmarshalBytes converts a byte buffer into an arbitrary value.
//
// Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
// those have special cases that allow more types to be encoded.
+//
+// The common int32 and int64 types are directly handled to avoid
+// unnecessary heap allocations as happening in the default case.
func unmarshalBytes(data interface{}, buf []byte) error {
switch value := data.(type) {
case unsafe.Pointer:
- // This could be solved in Go 1.17 by unsafe.Slice instead. (https://github.com/golang/go/issues/19367)
- // We could opt for removing unsafe.Pointer support in the lib as well.
- sh := &reflect.SliceHeader{ //nolint:govet
- Data: uintptr(value),
- Len: len(buf),
- Cap: len(buf),
- }
+ var dst []byte
+ // Use unsafe.Slice when we drop support for pre1.17 (https://github.com/golang/go/issues/19367)
+ // We could opt for removing unsafe.Pointer support in the lib as well
+ sh := (*reflect.SliceHeader)(unsafe.Pointer(&dst))
+ sh.Data = uintptr(value)
+ sh.Len = len(buf)
+ sh.Cap = len(buf)
- dst := *(*[]byte)(unsafe.Pointer(sh))
copy(dst, buf)
runtime.KeepAlive(value)
return nil
@@ -106,12 +119,38 @@ func unmarshalBytes(data interface{}, buf []byte) error {
case *[]byte:
*value = buf
return nil
+ case *int32:
+ if len(buf) < 4 {
+ return errors.New("int32 requires 4 bytes")
+ }
+ *value = int32(internal.NativeEndian.Uint32(buf))
+ return nil
+ case *uint32:
+ if len(buf) < 4 {
+ return errors.New("uint32 requires 4 bytes")
+ }
+ *value = internal.NativeEndian.Uint32(buf)
+ return nil
+ case *int64:
+ if len(buf) < 8 {
+ return errors.New("int64 requires 8 bytes")
+ }
+ *value = int64(internal.NativeEndian.Uint64(buf))
+ return nil
+ case *uint64:
+ if len(buf) < 8 {
+ return errors.New("uint64 requires 8 bytes")
+ }
+ *value = internal.NativeEndian.Uint64(buf)
+ return nil
case string:
return errors.New("require pointer to string")
case []byte:
return errors.New("require pointer to []byte")
default:
- rd := bytes.NewReader(buf)
+ rd := bytesReaderPool.Get().(*bytes.Reader)
+ rd.Reset(buf)
+ defer bytesReaderPool.Put(rd)
if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
return fmt.Errorf("decoding %T: %v", value, err)
}
@@ -142,7 +181,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er
return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
}
- alignedElemLength := align(elemLength, 8)
+ alignedElemLength := internal.Align(elemLength, 8)
buf := make([]byte, alignedElemLength*possibleCPUs)
for i := 0; i < sliceLen; i++ {
@@ -212,7 +251,3 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro
reflect.ValueOf(slicePtr).Elem().Set(slice)
return nil
}
-
-func align(n, alignment int) int {
- return (int(n) + alignment - 1) / alignment * alignment
-}
diff --git a/vendor/github.com/cilium/ebpf/prog.go b/vendor/github.com/cilium/ebpf/prog.go
index 13bdb6dda..3549a3fe3 100644
--- a/vendor/github.com/cilium/ebpf/prog.go
+++ b/vendor/github.com/cilium/ebpf/prog.go
@@ -57,16 +57,21 @@ type ProgramSpec struct {
// Name is passed to the kernel as a debug aid. Must only contain
// alpha numeric and '_' characters.
Name string
+
// Type determines at which hook in the kernel a program will run.
Type ProgramType
AttachType AttachType
- // Name of a kernel data structure to attach to. It's interpretation
- // depends on Type and AttachType.
- AttachTo string
+ // Name of a kernel data structure or function to attach to. Its
+ // interpretation depends on Type and AttachType.
+ AttachTo string
+ // The program to attach to. Must be provided manually.
+ AttachTarget *Program
Instructions asm.Instructions
+
// Flags is passed to the kernel and specifies additional program
// load attributes.
Flags uint32
+
// License of the program. Some helpers are only available if
// the license is deemed compatible with the GPL.
//
@@ -146,7 +151,7 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *handleCache) (*Program, error) {
if len(spec.Instructions) == 0 {
- return nil, errors.New("Instructions cannot be empty")
+ return nil, errors.New("instructions cannot be empty")
}
if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
@@ -166,16 +171,16 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
kv = v.Kernel()
}
- attr := &bpfProgLoadAttr{
- progType: spec.Type,
- progFlags: spec.Flags,
- expectedAttachType: spec.AttachType,
- license: internal.NewStringPointer(spec.License),
- kernelVersion: kv,
+ attr := &internal.BPFProgLoadAttr{
+ ProgType: uint32(spec.Type),
+ ProgFlags: spec.Flags,
+ ExpectedAttachType: uint32(spec.AttachType),
+ License: internal.NewStringPointer(spec.License),
+ KernelVersion: kv,
}
if haveObjName() == nil {
- attr.progName = internal.NewBPFObjName(spec.Name)
+ attr.ProgName = internal.NewBPFObjName(spec.Name)
}
var err error
@@ -190,35 +195,35 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
var btfDisabled bool
var core btf.COREFixups
if spec.BTF != nil {
- core, err = btf.ProgramFixups(spec.BTF, targetBTF)
+ core, err = spec.BTF.Fixups(targetBTF)
if err != nil {
return nil, fmt.Errorf("CO-RE relocations: %w", err)
}
- handle, err := handles.btfHandle(btf.ProgramSpec(spec.BTF))
+ handle, err := handles.btfHandle(spec.BTF.Spec())
btfDisabled = errors.Is(err, btf.ErrNotSupported)
if err != nil && !btfDisabled {
return nil, fmt.Errorf("load BTF: %w", err)
}
if handle != nil {
- attr.progBTFFd = uint32(handle.FD())
+ attr.ProgBTFFd = uint32(handle.FD())
- recSize, bytes, err := btf.ProgramLineInfos(spec.BTF)
+ recSize, bytes, err := spec.BTF.LineInfos()
if err != nil {
return nil, fmt.Errorf("get BTF line infos: %w", err)
}
- attr.lineInfoRecSize = recSize
- attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
- attr.lineInfo = internal.NewSlicePointer(bytes)
+ attr.LineInfoRecSize = recSize
+ attr.LineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
+ attr.LineInfo = internal.NewSlicePointer(bytes)
- recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF)
+ recSize, bytes, err = spec.BTF.FuncInfos()
if err != nil {
return nil, fmt.Errorf("get BTF function infos: %w", err)
}
- attr.funcInfoRecSize = recSize
- attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
- attr.funcInfo = internal.NewSlicePointer(bytes)
+ attr.FuncInfoRecSize = recSize
+ attr.FuncInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
+ attr.FuncInfo = internal.NewSlicePointer(bytes)
}
}
@@ -238,16 +243,41 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
}
bytecode := buf.Bytes()
- attr.instructions = internal.NewSlicePointer(bytecode)
- attr.insCount = uint32(len(bytecode) / asm.InstructionSize)
+ attr.Instructions = internal.NewSlicePointer(bytecode)
+ attr.InsCount = uint32(len(bytecode) / asm.InstructionSize)
if spec.AttachTo != "" {
+ if spec.AttachTarget != nil {
+ info, err := spec.AttachTarget.Info()
+ if err != nil {
+ return nil, fmt.Errorf("load target BTF: %w", err)
+ }
+
+ btfID, ok := info.BTFID()
+ if !ok {
+ return nil, fmt.Errorf("load target BTF: no BTF info available")
+ }
+ btfHandle, err := btf.NewHandleFromID(btfID)
+ if err != nil {
+ return nil, fmt.Errorf("load target BTF: %w", err)
+ }
+ defer btfHandle.Close()
+
+ targetBTF = btfHandle.Spec()
+ if err != nil {
+ return nil, fmt.Errorf("load target BTF: %w", err)
+ }
+ }
+
target, err := resolveBTFType(targetBTF, spec.AttachTo, spec.Type, spec.AttachType)
if err != nil {
return nil, err
}
if target != nil {
- attr.attachBTFID = target.ID()
+ attr.AttachBTFID = uint32(target.ID())
+ }
+ if spec.AttachTarget != nil {
+ attr.AttachProgFd = uint32(spec.AttachTarget.FD())
}
}
@@ -259,12 +289,12 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
var logBuf []byte
if opts.LogLevel > 0 {
logBuf = make([]byte, logSize)
- attr.logLevel = opts.LogLevel
- attr.logSize = uint32(len(logBuf))
- attr.logBuf = internal.NewSlicePointer(logBuf)
+ attr.LogLevel = opts.LogLevel
+ attr.LogSize = uint32(len(logBuf))
+ attr.LogBuf = internal.NewSlicePointer(logBuf)
}
- fd, err := bpfProgLoad(attr)
+ fd, err := internal.BPFProgLoad(attr)
if err == nil {
return &Program{internal.CString(logBuf), fd, spec.Name, "", spec.Type}, nil
}
@@ -273,17 +303,20 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
if opts.LogLevel == 0 && opts.LogSize >= 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.LogLevel = 1
+ attr.LogSize = uint32(len(logBuf))
+ attr.LogBuf = internal.NewSlicePointer(logBuf)
- _, logErr = bpfProgLoad(attr)
+ fd, logErr = internal.BPFProgLoad(attr)
+ if logErr == nil {
+ fd.Close()
+ }
}
if errors.Is(logErr, unix.EPERM) && logBuf[0] == 0 {
// EPERM due to RLIMIT_MEMLOCK happens before the verifier, so we can
// check that the log is empty to reduce false positives.
- return nil, fmt.Errorf("load program: RLIMIT_MEMLOCK may be too low: %w", logErr)
+ return nil, fmt.Errorf("load program: %w (MEMLOCK bay be too low, consider rlimit.RemoveMemlock)", logErr)
}
err = internal.ErrorWithLog(err, logBuf, logErr)
@@ -310,7 +343,7 @@ func NewProgramFromFD(fd int) (*Program, error) {
//
// Returns ErrNotExist, if there is no eBPF program with the given id.
func NewProgramFromID(id ProgramID) (*Program, error) {
- fd, err := bpfObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id))
+ fd, err := internal.BPFObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id))
if err != nil {
return nil, fmt.Errorf("get program by id: %w", err)
}
@@ -677,45 +710,44 @@ func ProgramGetNextID(startID ProgramID) (ProgramID, error) {
//
// Deprecated: use ProgramInfo.ID() instead.
func (p *Program) ID() (ProgramID, error) {
- info, err := bpfGetProgInfoByFD(p.fd)
+ info, err := bpfGetProgInfoByFD(p.fd, nil)
if err != nil {
return ProgramID(0), err
}
return ProgramID(info.id), nil
}
-func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
+func resolveBTFType(spec *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
type match struct {
p ProgramType
a AttachType
}
- var target btf.Type
var typeName, featureName string
switch (match{progType, attachType}) {
case match{LSM, AttachLSMMac}:
- target = new(btf.Func)
typeName = "bpf_lsm_" + name
featureName = name + " LSM hook"
-
case match{Tracing, AttachTraceIter}:
- target = new(btf.Func)
typeName = "bpf_iter_" + name
featureName = name + " iterator"
-
+ case match{Extension, AttachNone}:
+ typeName = name
+ featureName = fmt.Sprintf("freplace %s", name)
default:
return nil, nil
}
- if kernel == nil {
+ if spec == nil {
var err error
- kernel, err = btf.LoadKernelSpec()
+ spec, err = btf.LoadKernelSpec()
if err != nil {
return nil, fmt.Errorf("load kernel spec: %w", err)
}
}
- err := kernel.FindType(typeName, target)
+ var target *btf.Func
+ err := spec.FindType(typeName, &target)
if errors.Is(err, btf.ErrNotFound) {
return nil, &internal.UnsupportedFeatureError{
Name: featureName,
@@ -724,5 +756,6 @@ func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachT
if err != nil {
return nil, fmt.Errorf("resolve BTF for %s: %w", featureName, err)
}
+
return target, nil
}
diff --git a/vendor/github.com/cilium/ebpf/run-tests.sh b/vendor/github.com/cilium/ebpf/run-tests.sh
index e2437beed..a079edc7e 100644
--- a/vendor/github.com/cilium/ebpf/run-tests.sh
+++ b/vendor/github.com/cilium/ebpf/run-tests.sh
@@ -5,7 +5,7 @@
# Run all tests on a 5.4 kernel
# $ ./run-tests.sh 5.4
# Run a subset of tests:
-# $ ./run-tests.sh 5.4 go test ./link
+# $ ./run-tests.sh 5.4 ./link
set -euo pipefail
@@ -48,15 +48,17 @@ if [[ "${1:-}" = "--exec-vm" ]]; then
rm "${output}/fake-stdin"
fi
- $sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \
- --rwdir="${testdir}=${testdir}" \
- --rodir=/run/input="${input}" \
- --rwdir=/run/output="${output}" \
- --script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \
- --qemu-opts -smp 2 # need at least two CPUs for some tests
+ if ! $sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \
+ --rwdir="${testdir}=${testdir}" \
+ --rodir=/run/input="${input}" \
+ --rwdir=/run/output="${output}" \
+ --script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \
+ --kopt possible_cpus=2; then # need at least two CPUs for some tests
+ exit 23
+ fi
if [[ ! -e "${output}/success" ]]; then
- exit 1
+ exit 42
fi
$sudo rm -r "$output"
@@ -74,7 +76,7 @@ elif [[ "${1:-}" = "--exec-test" ]]; then
dmesg -C
if ! "$@"; then
dmesg
- exit 1
+ exit 1 # this return code is "swallowed" by qemu
fi
touch "/run/output/success"
exit 0
@@ -108,7 +110,7 @@ else
echo "No selftests found, disabling"
fi
-args=(-v -short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...)
+args=(-short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...)
if (( $# > 0 )); then
args=("$@")
fi
diff --git a/vendor/github.com/cilium/ebpf/syscalls.go b/vendor/github.com/cilium/ebpf/syscalls.go
index f5a38549b..f8cb5f0e0 100644
--- a/vendor/github.com/cilium/ebpf/syscalls.go
+++ b/vendor/github.com/cilium/ebpf/syscalls.go
@@ -1,13 +1,14 @@
package ebpf
import (
+ "bytes"
"errors"
"fmt"
"os"
"unsafe"
+ "github.com/cilium/ebpf/asm"
"github.com/cilium/ebpf/internal"
- "github.com/cilium/ebpf/internal/btf"
"github.com/cilium/ebpf/internal/unix"
)
@@ -73,30 +74,6 @@ type bpfMapInfo struct {
btf_value_type_id uint32
}
-type bpfProgLoadAttr struct {
- progType ProgramType
- insCount uint32
- instructions internal.Pointer
- license internal.Pointer
- logLevel uint32
- logSize uint32
- logBuf internal.Pointer
- kernelVersion uint32 // since 4.1 2541517c32be
- progFlags uint32 // since 4.11 e07b98d9bffe
- progName internal.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
- attachBTFID btf.TypeID
- attachProgFd uint32
-}
-
type bpfProgInfo struct {
prog_type uint32
id uint32
@@ -107,7 +84,7 @@ type bpfProgInfo struct {
xlated_prog_insns internal.Pointer
load_time uint64 // since 4.15 cb4d2b3f03d8
created_by_uid uint32
- nr_map_ids uint32
+ nr_map_ids uint32 // since 4.15 cb4d2b3f03d8
map_ids internal.Pointer
name internal.BPFObjName // since 4.15 067cae47771c
ifindex uint32
@@ -145,11 +122,6 @@ type bpfProgTestRunAttr struct {
duration uint32
}
-type bpfGetFDByIDAttr struct {
- id uint32
- next uint32
-}
-
type bpfMapFreezeAttr struct {
mapFd uint32
}
@@ -160,23 +132,6 @@ type bpfObjGetNextIDAttr struct {
openFlags uint32
}
-func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
- for {
- fd, err := internal.BPF(internal.BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
- // As of ~4.20 the verifier can be interrupted by a signal,
- // and returns EAGAIN in that case.
- if errors.Is(err, unix.EAGAIN) {
- continue
- }
-
- if err != nil {
- return nil, err
- }
-
- return internal.NewFD(uint32(fd)), nil
- }
-}
-
func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
_, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
return err
@@ -372,6 +327,10 @@ func wrapMapError(err error) error {
return internal.SyscallError(ErrNotSupported, unix.ENOTSUPP)
}
+ if errors.Is(err, unix.E2BIG) {
+ return fmt.Errorf("key too big for map: %w", err)
+ }
+
return err
}
@@ -388,8 +347,13 @@ func bpfMapFreeze(m *internal.FD) error {
return err
}
-func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) {
+func bpfGetProgInfoByFD(fd *internal.FD, ids []MapID) (*bpfProgInfo, error) {
var info bpfProgInfo
+ if len(ids) > 0 {
+ info.nr_map_ids = uint32(len(ids))
+ info.map_ids = internal.NewPointer(unsafe.Pointer(&ids[0]))
+ }
+
if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
return nil, fmt.Errorf("can't get program info: %w", err)
}
@@ -471,10 +435,30 @@ var haveBatchAPI = internal.FeatureTest("map batch api", "5.6", func() error {
return nil
})
-func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) {
- attr := bpfGetFDByIDAttr{
- id: id,
+var haveProbeReadKernel = internal.FeatureTest("bpf_probe_read_kernel", "5.5", func() error {
+ insns := asm.Instructions{
+ asm.Mov.Reg(asm.R1, asm.R10),
+ asm.Add.Imm(asm.R1, -8),
+ asm.Mov.Imm(asm.R2, 8),
+ asm.Mov.Imm(asm.R3, 0),
+ asm.FnProbeReadKernel.Call(),
+ asm.Return(),
+ }
+ buf := bytes.NewBuffer(make([]byte, 0, len(insns)*asm.InstructionSize))
+ if err := insns.Marshal(buf, internal.NativeEndian); err != nil {
+ return err
}
- ptr, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
- return internal.NewFD(uint32(ptr)), err
-}
+ bytecode := buf.Bytes()
+
+ fd, err := internal.BPFProgLoad(&internal.BPFProgLoadAttr{
+ ProgType: uint32(Kprobe),
+ License: internal.NewStringPointer("GPL"),
+ Instructions: internal.NewSlicePointer(bytecode),
+ InsCount: uint32(len(bytecode) / asm.InstructionSize),
+ })
+ if err != nil {
+ return internal.ErrNotSupported
+ }
+ _ = fd.Close()
+ return nil
+})
diff --git a/vendor/github.com/cilium/ebpf/types.go b/vendor/github.com/cilium/ebpf/types.go
index 441a82fe4..84b83f9f9 100644
--- a/vendor/github.com/cilium/ebpf/types.go
+++ b/vendor/github.com/cilium/ebpf/types.go
@@ -4,12 +4,17 @@ import (
"github.com/cilium/ebpf/internal/unix"
)
-//go:generate stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType
+//go:generate stringer -output types_string.go -type=MapType,ProgramType,PinType
// MapType indicates the type map structure
// that will be initialized in the kernel.
type MapType uint32
+// Max returns the latest supported MapType.
+func (_ MapType) Max() MapType {
+ return maxMapType - 1
+}
+
// All the various map types that can be created
const (
UnspecifiedMap MapType = iota
@@ -85,15 +90,28 @@ const (
SkStorage
// DevMapHash - Hash-based indexing scheme for references to network devices.
DevMapHash
- StructOpts
+ // StructOpsMap - This map holds a kernel struct with its function pointer implemented in a BPF
+ // program.
+ StructOpsMap
+ // RingBuf - Similar to PerfEventArray, but shared across all CPUs.
RingBuf
+ // InodeStorage - Specialized local storage map for inodes.
InodeStorage
+ // TaskStorage - Specialized local storage map for task_struct.
TaskStorage
+ // maxMapType - Bound enum of MapTypes, has to be last in enum.
+ maxMapType
)
+// Deprecated: StructOpts was a typo, use StructOpsMap instead.
+//
+// Declared as a variable to prevent stringer from picking it up
+// as an enum value.
+var StructOpts MapType = StructOpsMap
+
// hasPerCPUValue returns true if the Map stores a value per CPU.
func (mt MapType) hasPerCPUValue() bool {
- return mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash
+ return mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash || mt == PerCPUCGroupStorage
}
// canStoreMap returns true if the map type accepts a map fd
@@ -111,6 +129,11 @@ func (mt MapType) canStoreProgram() bool {
// ProgramType of the eBPF program
type ProgramType uint32
+// Max return the latest supported ProgramType.
+func (_ ProgramType) Max() ProgramType {
+ return maxProgramType - 1
+}
+
// eBPF program types
const (
UnspecifiedProgram ProgramType = iota
@@ -144,6 +167,7 @@ const (
Extension
LSM
SkLookup
+ maxProgramType
)
// AttachType of the eBPF program, needed to differentiate allowed context accesses in
@@ -151,6 +175,8 @@ const (
// Will cause invalid argument (EINVAL) at program load time if set incorrectly.
type AttachType uint32
+//go:generate stringer -type AttachType -trimprefix Attach
+
// AttachNone is an alias for AttachCGroupInetIngress for readability reasons.
const AttachNone AttachType = 0
@@ -193,6 +219,10 @@ const (
AttachXDPCPUMap
AttachSkLookup
AttachXDP
+ AttachSkSKBVerdict
+ AttachSkReuseportSelect
+ AttachSkReuseportSelectOrMigrate
+ AttachPerfEvent
)
// 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 c25f76564..81cbc9efd 100644
--- a/vendor/github.com/cilium/ebpf/types_string.go
+++ b/vendor/github.com/cilium/ebpf/types_string.go
@@ -1,4 +1,4 @@
-// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType"; DO NOT EDIT.
+// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,PinType"; DO NOT EDIT.
package ebpf
@@ -34,15 +34,16 @@ func _() {
_ = x[Stack-23]
_ = x[SkStorage-24]
_ = x[DevMapHash-25]
- _ = x[StructOpts-26]
+ _ = x[StructOpsMap-26]
_ = x[RingBuf-27]
_ = x[InodeStorage-28]
_ = x[TaskStorage-29]
+ _ = x[maxMapType-30]
}
-const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOptsRingBufInodeStorageTaskStorage"
+const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOpsMapRingBufInodeStorageTaskStoragemaxMapType"
-var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 258, 265, 277, 288}
+var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 260, 267, 279, 290, 300}
func (i MapType) String() string {
if i >= MapType(len(_MapType_index)-1) {
@@ -85,11 +86,12 @@ func _() {
_ = x[Extension-28]
_ = x[LSM-29]
_ = x[SkLookup-30]
+ _ = x[maxProgramType-31]
}
-const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracingStructOpsExtensionLSMSkLookup"
+const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracingStructOpsExtensionLSMSkLookupmaxProgramType"
-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, 274, 283, 286, 294}
+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, 274, 283, 286, 294, 308}
func (i ProgramType) String() string {
if i >= ProgramType(len(_ProgramType_index)-1) {
@@ -97,61 +99,6 @@ func (i ProgramType) String() string {
}
return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]]
}
-func _() {
- // An "invalid array index" compiler error signifies that the constant values have changed.
- // Re-run the stringer command to generate them again.
- var x [1]struct{}
- _ = x[AttachNone-0]
- _ = x[AttachCGroupInetIngress-0]
- _ = x[AttachCGroupInetEgress-1]
- _ = x[AttachCGroupInetSockCreate-2]
- _ = x[AttachCGroupSockOps-3]
- _ = x[AttachSkSKBStreamParser-4]
- _ = x[AttachSkSKBStreamVerdict-5]
- _ = x[AttachCGroupDevice-6]
- _ = x[AttachSkMsgVerdict-7]
- _ = x[AttachCGroupInet4Bind-8]
- _ = x[AttachCGroupInet6Bind-9]
- _ = x[AttachCGroupInet4Connect-10]
- _ = x[AttachCGroupInet6Connect-11]
- _ = x[AttachCGroupInet4PostBind-12]
- _ = x[AttachCGroupInet6PostBind-13]
- _ = x[AttachCGroupUDP4Sendmsg-14]
- _ = x[AttachCGroupUDP6Sendmsg-15]
- _ = x[AttachLircMode2-16]
- _ = x[AttachFlowDissector-17]
- _ = x[AttachCGroupSysctl-18]
- _ = x[AttachCGroupUDP4Recvmsg-19]
- _ = x[AttachCGroupUDP6Recvmsg-20]
- _ = x[AttachCGroupGetsockopt-21]
- _ = x[AttachCGroupSetsockopt-22]
- _ = x[AttachTraceRawTp-23]
- _ = x[AttachTraceFEntry-24]
- _ = x[AttachTraceFExit-25]
- _ = x[AttachModifyReturn-26]
- _ = x[AttachLSMMac-27]
- _ = x[AttachTraceIter-28]
- _ = x[AttachCgroupInet4GetPeername-29]
- _ = x[AttachCgroupInet6GetPeername-30]
- _ = x[AttachCgroupInet4GetSockname-31]
- _ = x[AttachCgroupInet6GetSockname-32]
- _ = x[AttachXDPDevMap-33]
- _ = x[AttachCgroupInetSockRelease-34]
- _ = x[AttachXDPCPUMap-35]
- _ = x[AttachSkLookup-36]
- _ = x[AttachXDP-37]
-}
-
-const _AttachType_name = "AttachNoneAttachCGroupInetEgressAttachCGroupInetSockCreateAttachCGroupSockOpsAttachSkSKBStreamParserAttachSkSKBStreamVerdictAttachCGroupDeviceAttachSkMsgVerdictAttachCGroupInet4BindAttachCGroupInet6BindAttachCGroupInet4ConnectAttachCGroupInet6ConnectAttachCGroupInet4PostBindAttachCGroupInet6PostBindAttachCGroupUDP4SendmsgAttachCGroupUDP6SendmsgAttachLircMode2AttachFlowDissectorAttachCGroupSysctlAttachCGroupUDP4RecvmsgAttachCGroupUDP6RecvmsgAttachCGroupGetsockoptAttachCGroupSetsockoptAttachTraceRawTpAttachTraceFEntryAttachTraceFExitAttachModifyReturnAttachLSMMacAttachTraceIterAttachCgroupInet4GetPeernameAttachCgroupInet6GetPeernameAttachCgroupInet4GetSocknameAttachCgroupInet6GetSocknameAttachXDPDevMapAttachCgroupInetSockReleaseAttachXDPCPUMapAttachSkLookupAttachXDP"
-
-var _AttachType_index = [...]uint16{0, 10, 32, 58, 77, 100, 124, 142, 160, 181, 202, 226, 250, 275, 300, 323, 346, 361, 380, 398, 421, 444, 466, 488, 504, 521, 537, 555, 567, 582, 610, 638, 666, 694, 709, 736, 751, 765, 774}
-
-func (i AttachType) String() string {
- if i >= AttachType(len(_AttachType_index)-1) {
- return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")"
- }
- return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]]
-}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
diff --git a/vendor/github.com/cyphar/filepath-securejoin/.travis.yml b/vendor/github.com/cyphar/filepath-securejoin/.travis.yml
index 3938f3834..b94ff8cf9 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/.travis.yml
+++ b/vendor/github.com/cyphar/filepath-securejoin/.travis.yml
@@ -4,10 +4,12 @@
language: go
go:
- - 1.7.x
- - 1.8.x
+ - 1.13.x
+ - 1.16.x
- tip
-
+arch:
+ - AMD64
+ - ppc64le
os:
- linux
- osx
diff --git a/vendor/github.com/cyphar/filepath-securejoin/BUILD.bazel b/vendor/github.com/cyphar/filepath-securejoin/BUILD.bazel
index 4dcb35975..8d1d42328 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/BUILD.bazel
+++ b/vendor/github.com/cyphar/filepath-securejoin/BUILD.bazel
@@ -9,5 +9,4 @@ go_library(
importmap = "kubevirt.io/kubevirt/vendor/github.com/cyphar/filepath-securejoin",
importpath = "github.com/cyphar/filepath-securejoin",
visibility = ["//visibility:public"],
- deps = ["//vendor/github.com/pkg/errors:go_default_library"],
)
diff --git a/vendor/github.com/cyphar/filepath-securejoin/README.md b/vendor/github.com/cyphar/filepath-securejoin/README.md
index 49b2baa9f..3624617c8 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/README.md
+++ b/vendor/github.com/cyphar/filepath-securejoin/README.md
@@ -7,6 +7,19 @@ standard library][go#20126]. The purpose of this function is to be a "secure"
alternative to `filepath.Join`, and in particular it provides certain
guarantees that are not provided by `filepath.Join`.
+> **NOTE**: This code is *only* safe if you are not at risk of other processes
+> modifying path components after you've used `SecureJoin`. If it is possible
+> for a malicious process to modify path components of the resolved path, then
+> you will be vulnerable to some fairly trivial TOCTOU race conditions. [There
+> are some Linux kernel patches I'm working on which might allow for a better
+> solution.][lwn-obeneath]
+>
+> In addition, with a slightly modified API it might be possible to use
+> `O_PATH` and verify that the opened path is actually the resolved one -- but
+> I have not done that yet. I might add it in the future as a helper function
+> to help users verify the path (we can't just return `/proc/self/fd/<foo>`
+> because that doesn't always work transparently for all users).
+
This is the function prototype:
```go
@@ -16,8 +29,8 @@ func SecureJoin(root, unsafePath string) (string, error)
This library **guarantees** the following:
* If no error is set, the resulting string **must** be a child path of
- `SecureJoin` and will not contain any symlink path components (they will all
- be expanded).
+ `root` and will not contain any symlink path components (they will all be
+ expanded).
* When expanding symlinks, all symlink path components **must** be resolved
relative to the provided root. In particular, this can be considered a
@@ -25,7 +38,7 @@ This library **guarantees** the following:
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
called on the input before processing).
-* Non-existant path components are unaffected by `SecureJoin` (similar to
+* Non-existent path components are unaffected by `SecureJoin` (similar to
`filepath.EvalSymlinks`'s semantics).
* The returned path will always be `filepath.Clean`ed and thus not contain any
@@ -57,6 +70,7 @@ func SecureJoin(root, unsafePath string) (string, error) {
}
```
+[lwn-obeneath]: https://lwn.net/Articles/767547/
[go#20126]: https://github.com/golang/go/issues/20126
### License ###
diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION
index ee1372d33..717903969 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/VERSION
+++ b/vendor/github.com/cyphar/filepath-securejoin/VERSION
@@ -1 +1 @@
-0.2.2
+0.2.3
diff --git a/vendor/github.com/cyphar/filepath-securejoin/join.go b/vendor/github.com/cyphar/filepath-securejoin/join.go
index c4ca3d713..7dd08dbbd 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/join.go
+++ b/vendor/github.com/cyphar/filepath-securejoin/join.go
@@ -12,39 +12,20 @@ package securejoin
import (
"bytes"
+ "errors"
"os"
"path/filepath"
"strings"
"syscall"
-
- "github.com/pkg/errors"
)
-// ErrSymlinkLoop is returned by SecureJoinVFS when too many symlinks have been
-// evaluated in attempting to securely join the two given paths.
-var ErrSymlinkLoop = errors.Wrap(syscall.ELOOP, "secure join")
-
// IsNotExist tells you if err is an error that implies that either the path
// accessed does not exist (or path components don't exist). This is
// effectively a more broad version of os.IsNotExist.
func IsNotExist(err error) bool {
- // If it's a bone-fide ENOENT just bail.
- if os.IsNotExist(errors.Cause(err)) {
- return true
- }
-
// Check that it's not actually an ENOTDIR, which in some cases is a more
// convoluted case of ENOENT (usually involving weird paths).
- var errno error
- switch err := errors.Cause(err).(type) {
- case *os.PathError:
- errno = err.Err
- case *os.LinkError:
- errno = err.Err
- case *os.SyscallError:
- errno = err.Err
- }
- return errno == syscall.ENOTDIR || errno == syscall.ENOENT
+ return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT)
}
// SecureJoinVFS joins the two given path components (similar to Join) except
@@ -68,7 +49,7 @@ func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) {
n := 0
for unsafePath != "" {
if n > 255 {
- return "", ErrSymlinkLoop
+ return "", &os.PathError{Op: "SecureJoin", Path: root + "/" + unsafePath, Err: syscall.ELOOP}
}
// Next path component, p.
diff --git a/vendor/github.com/cyphar/filepath-securejoin/vendor.conf b/vendor/github.com/cyphar/filepath-securejoin/vendor.conf
deleted file mode 100644
index 66bb574b9..000000000
--- a/vendor/github.com/cyphar/filepath-securejoin/vendor.conf
+++ /dev/null
@@ -1 +0,0 @@
-github.com/pkg/errors v0.8.0
diff --git a/vendor/github.com/godbus/dbus/v5/BUILD.bazel b/vendor/github.com/godbus/dbus/v5/BUILD.bazel
index 742a02801..97a6b49f1 100644
--- a/vendor/github.com/godbus/dbus/v5/BUILD.bazel
+++ b/vendor/github.com/godbus/dbus/v5/BUILD.bazel
@@ -36,6 +36,7 @@ go_library(
"transport_unixcred_dragonfly.go",
"transport_unixcred_freebsd.go",
"transport_unixcred_linux.go",
+ "transport_unixcred_netbsd.go",
"transport_unixcred_openbsd.go",
"variant.go",
"variant_lexer.go",
diff --git a/vendor/github.com/godbus/dbus/v5/README.markdown b/vendor/github.com/godbus/dbus/v5/README.md
similarity index 81%
rename from vendor/github.com/godbus/dbus/v5/README.markdown
rename to vendor/github.com/godbus/dbus/v5/README.md
index 1fb2eacaa..5c2412583 100644
--- a/vendor/github.com/godbus/dbus/v5/README.markdown
+++ b/vendor/github.com/godbus/dbus/v5/README.md
@@ -14,14 +14,12 @@ D-Bus message bus system.
### Installation
-This packages requires Go 1.7. If you installed it and set up your GOPATH, just run:
+This packages requires Go 1.12 or later. It can be installed by running the command below:
```
-go get github.com/godbus/dbus
+go get github.com/godbus/dbus/v5
```
-If you want to use the subpackages, you can install them the same way.
-
### Usage
The complete package documentation and some simple examples are available at
@@ -30,10 +28,12 @@ The complete package documentation and some simple examples are available at
gives a short overview over the basic usage.
#### Projects using godbus
-- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
+- [fyne](https://github.com/fyne-io/fyne) a cross platform GUI in Go inspired by Material Design.
+- [fynedesk](https://github.com/fyne-io/fynedesk) a full desktop environment for Linux/Unix using Fyne.
- [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
-- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
- [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
+- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
+- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
Please note that the API is considered unstable for now and may change without
further notice.
diff --git a/vendor/github.com/godbus/dbus/v5/auth.go b/vendor/github.com/godbus/dbus/v5/auth.go
index 283487a0e..a59b4c0eb 100644
--- a/vendor/github.com/godbus/dbus/v5/auth.go
+++ b/vendor/github.com/godbus/dbus/v5/auth.go
@@ -53,7 +53,7 @@ type Auth interface {
// bus. Auth must not be called on shared connections.
func (conn *Conn) Auth(methods []Auth) error {
if methods == nil {
- uid := strconv.Itoa(os.Getuid())
+ uid := strconv.Itoa(os.Geteuid())
methods = []Auth{AuthExternal(uid), AuthCookieSha1(uid, getHomeDir())}
}
in := bufio.NewReader(conn.transport)
@@ -75,9 +75,9 @@ func (conn *Conn) Auth(methods []Auth) error {
s = s[1:]
for _, v := range s {
for _, m := range methods {
- if name, data, status := m.FirstData(); bytes.Equal(v, name) {
+ if name, _, status := m.FirstData(); bytes.Equal(v, name) {
var ok bool
- err = authWriteLine(conn.transport, []byte("AUTH"), v, data)
+ err = authWriteLine(conn.transport, []byte("AUTH"), v)
if err != nil {
return err
}
@@ -194,11 +194,14 @@ func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, boo
}
conn.uuid = string(s[1])
return nil, true
+ case state == waitingForOk && string(s[0]) == "DATA":
+ err = authWriteLine(conn.transport, []byte("DATA"))
+ if err != nil {
+ return err, false
+ }
case state == waitingForOk && string(s[0]) == "REJECTED":
return nil, false
- case state == waitingForOk && (string(s[0]) == "DATA" ||
- string(s[0]) == "ERROR"):
-
+ case state == waitingForOk && string(s[0]) == "ERROR":
err = authWriteLine(conn.transport, []byte("CANCEL"))
if err != nil {
return err, false
diff --git a/vendor/github.com/godbus/dbus/v5/conn.go b/vendor/github.com/godbus/dbus/v5/conn.go
index 29fe018ad..76fc5cde3 100644
--- a/vendor/github.com/godbus/dbus/v5/conn.go
+++ b/vendor/github.com/godbus/dbus/v5/conn.go
@@ -73,7 +73,7 @@ func SessionBus() (conn *Conn, err error) {
return
}
-func getSessionBusAddress() (string, error) {
+func getSessionBusAddress(autolaunch bool) (string, error) {
if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" {
return address, nil
@@ -81,12 +81,26 @@ func getSessionBusAddress() (string, error) {
os.Setenv("DBUS_SESSION_BUS_ADDRESS", address)
return address, nil
}
+ if !autolaunch {
+ return "", errors.New("dbus: couldn't determine address of session bus")
+ }
return getSessionBusPlatformAddress()
}
// SessionBusPrivate returns a new private connection to the session bus.
func SessionBusPrivate(opts ...ConnOption) (*Conn, error) {
- address, err := getSessionBusAddress()
+ address, err := getSessionBusAddress(true)
+ if err != nil {
+ return nil, err
+ }
+
+ return Dial(address, opts...)
+}
+
+// SessionBusPrivate returns a new private connection to the session bus. If
+// the session bus is not already open, do not attempt to launch it.
+func SessionBusPrivateNoAutoStartup(opts ...ConnOption) (*Conn, error) {
+ address, err := getSessionBusAddress(false)
if err != nil {
return nil, err
}
@@ -121,7 +135,7 @@ func SystemBus() (conn *Conn, err error) {
// ConnectSessionBus connects to the session bus.
func ConnectSessionBus(opts ...ConnOption) (*Conn, error) {
- address, err := getSessionBusAddress()
+ address, err := getSessionBusAddress(true)
if err != nil {
return nil, err
}
@@ -180,7 +194,7 @@ func Dial(address string, opts ...ConnOption) (*Conn, error) {
//
// Deprecated: use Dial with options instead.
func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) {
- return Dial(address, WithSignalHandler(signalHandler))
+ return Dial(address, WithHandler(handler), WithSignalHandler(signalHandler))
}
// ConnOption is a connection option.
@@ -478,14 +492,24 @@ func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
conn.outInt(msg)
}
err := conn.outHandler.sendAndIfClosed(msg, ifClosed)
- conn.calls.handleSendError(msg, err)
if err != nil {
- conn.serialGen.RetireSerial(msg.serial)
+ conn.handleSendError(msg, err)
} else if msg.Type != TypeMethodCall {
conn.serialGen.RetireSerial(msg.serial)
}
}
+func (conn *Conn) handleSendError(msg *Message, err error) {
+ if msg.Type == TypeMethodCall {
+ conn.calls.handleSendError(msg, err)
+ } else if msg.Type == TypeMethodReply {
+ if _, ok := err.(FormatError); ok {
+ conn.sendError(err, msg.Headers[FieldDestination].value.(string), msg.Headers[FieldReplySerial].value.(uint32))
+ }
+ }
+ conn.serialGen.RetireSerial(msg.serial)
+}
+
// Send sends the given message to the message bus. You usually don't need to
// use this; use the higher-level equivalents (Call / Go, Emit and Export)
// instead. If msg is a method call and NoReplyExpected is not set, a non-nil
diff --git a/vendor/github.com/godbus/dbus/v5/decoder.go b/vendor/github.com/godbus/dbus/v5/decoder.go
index ede91575b..89bfed9d1 100644
--- a/vendor/github.com/godbus/dbus/v5/decoder.go
+++ b/vendor/github.com/godbus/dbus/v5/decoder.go
@@ -10,14 +10,16 @@ type decoder struct {
in io.Reader
order binary.ByteOrder
pos int
+ fds []int
}
// newDecoder returns a new decoder that reads values from in. The input is
// expected to be in the given byte order.
-func newDecoder(in io.Reader, order binary.ByteOrder) *decoder {
+func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder {
dec := new(decoder)
dec.in = in
dec.order = order
+ dec.fds = fds
return dec
}
@@ -53,7 +55,7 @@ func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
vs = make([]interface{}, 0)
s := sig.str
for s != "" {
- err, rem := validSingle(s, 0)
+ err, rem := validSingle(s, &depthCounter{})
if err != nil {
return nil, err
}
@@ -150,7 +152,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
if len(sig.str) == 0 {
panic(FormatError("variant signature is empty"))
}
- err, rem := validSingle(sig.str, 0)
+ err, rem := validSingle(sig.str, &depthCounter{})
if err != nil {
panic(err)
}
@@ -161,7 +163,11 @@ func (dec *decoder) decode(s string, depth int) interface{} {
variant.value = dec.decode(sig.str, depth+1)
return variant
case 'h':
- return UnixFDIndex(dec.decode("u", depth).(uint32))
+ idx := dec.decode("u", depth).(uint32)
+ if int(idx) < len(dec.fds) {
+ return UnixFD(dec.fds[idx])
+ }
+ return UnixFDIndex(idx)
case 'a':
if len(s) > 1 && s[1] == '{' {
ksig := s[2:3]
@@ -219,7 +225,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
v := make([]interface{}, 0)
s = s[1 : len(s)-1]
for s != "" {
- err, rem := validSingle(s, 0)
+ err, rem := validSingle(s, &depthCounter{})
if err != nil {
panic(err)
}
diff --git a/vendor/github.com/godbus/dbus/v5/encoder.go b/vendor/github.com/godbus/dbus/v5/encoder.go
index adfbb75c5..015b26cd5 100644
--- a/vendor/github.com/godbus/dbus/v5/encoder.go
+++ b/vendor/github.com/godbus/dbus/v5/encoder.go
@@ -5,28 +5,33 @@ import (
"encoding/binary"
"io"
"reflect"
+ "strings"
+ "unicode/utf8"
)
// An encoder encodes values to the D-Bus wire format.
type encoder struct {
out io.Writer
+ fds []int
order binary.ByteOrder
pos int
}
// NewEncoder returns a new encoder that writes to out in the given byte order.
-func newEncoder(out io.Writer, order binary.ByteOrder) *encoder {
- return newEncoderAtOffset(out, 0, order)
+func newEncoder(out io.Writer, order binary.ByteOrder, fds []int) *encoder {
+ enc := newEncoderAtOffset(out, 0, order, fds)
+ return enc
}
// newEncoderAtOffset returns a new encoder that writes to out in the given
// byte order. Specify the offset to initialize pos for proper alignment
// computation.
-func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder) *encoder {
+func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder, fds []int) *encoder {
enc := new(encoder)
enc.out = out
enc.order = order
enc.pos = offset
+ enc.fds = fds
return enc
}
@@ -75,6 +80,9 @@ func (enc *encoder) Encode(vs ...interface{}) (err error) {
// encode encodes the given value to the writer and panics on error. depth holds
// the depth of the container nesting.
func (enc *encoder) encode(v reflect.Value, depth int) {
+ if depth > 64 {
+ panic(FormatError("input exceeds depth limitation"))
+ }
enc.align(alignment(v.Type()))
switch v.Kind() {
case reflect.Uint8:
@@ -97,7 +105,14 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
enc.binwrite(uint16(v.Uint()))
enc.pos += 2
case reflect.Int, reflect.Int32:
- enc.binwrite(int32(v.Int()))
+ if v.Type() == unixFDType {
+ fd := v.Int()
+ idx := len(enc.fds)
+ enc.fds = append(enc.fds, int(fd))
+ enc.binwrite(uint32(idx))
+ } else {
+ enc.binwrite(int32(v.Int()))
+ }
enc.pos += 4
case reflect.Uint, reflect.Uint32:
enc.binwrite(uint32(v.Uint()))
@@ -112,9 +127,21 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
enc.binwrite(v.Float())
enc.pos += 8
case reflect.String:
- enc.encode(reflect.ValueOf(uint32(len(v.String()))), depth)
+ str := v.String()
+ if !utf8.ValidString(str) {
+ panic(FormatError("input has a not-utf8 char in string"))
+ }
+ if strings.IndexByte(str, byte(0)) != -1 {
+ panic(FormatError("input has a null char('\\000') in string"))
+ }
+ if v.Type() == objectPathType {
+ if !ObjectPath(str).IsValid() {
+ panic(FormatError("invalid object path"))
+ }
+ }
+ enc.encode(reflect.ValueOf(uint32(len(str))), depth)
b := make([]byte, v.Len()+1)
- copy(b, v.String())
+ copy(b, str)
b[len(b)-1] = 0
n, err := enc.out.Write(b)
if err != nil {
@@ -124,20 +151,23 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
case reflect.Ptr:
enc.encode(v.Elem(), depth)
case reflect.Slice, reflect.Array:
- if depth >= 64 {
- panic(FormatError("input exceeds container depth limit"))
- }
// Lookahead offset: 4 bytes for uint32 length (with alignment),
// plus alignment for elements.
n := enc.padding(0, 4) + 4
offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
var buf bytes.Buffer
- bufenc := newEncoderAtOffset(&buf, offset, enc.order)
+ bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
for i := 0; i < v.Len(); i++ {
bufenc.encode(v.Index(i), depth+1)
}
+
+ if buf.Len() > 1<<26 {
+ panic(FormatError("input exceeds array size limitation"))
+ }
+
+ enc.fds = bufenc.fds
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
length := buf.Len()
enc.align(alignment(v.Type().Elem()))
@@ -146,13 +176,10 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
}
enc.pos += length
case reflect.Struct:
- if depth >= 64 && v.Type() != signatureType {
- panic(FormatError("input exceeds container depth limit"))
- }
switch t := v.Type(); t {
case signatureType:
str := v.Field(0)
- enc.encode(reflect.ValueOf(byte(str.Len())), depth+1)
+ enc.encode(reflect.ValueOf(byte(str.Len())), depth)
b := make([]byte, str.Len()+1)
copy(b, str.String())
b[len(b)-1] = 0
@@ -176,9 +203,6 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
case reflect.Map:
// Maps are arrays of structures, so they actually increase the depth by
// 2.
- if depth >= 63 {
- panic(FormatError("input exceeds container depth limit"))
- }
if !isKeyType(v.Type().Key()) {
panic(InvalidTypeError{v.Type()})
}
@@ -189,12 +213,13 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
offset := enc.pos + n + enc.padding(n, 8)
var buf bytes.Buffer
- bufenc := newEncoderAtOffset(&buf, offset, enc.order)
+ bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
for _, k := range keys {
bufenc.align(8)
bufenc.encode(k, depth+2)
bufenc.encode(v.MapIndex(k), depth+2)
}
+ enc.fds = bufenc.fds
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
length := buf.Len()
enc.align(8)
diff --git a/vendor/github.com/godbus/dbus/v5/export.go b/vendor/github.com/godbus/dbus/v5/export.go
index 2447b51d4..522334715 100644
--- a/vendor/github.com/godbus/dbus/v5/export.go
+++ b/vendor/github.com/godbus/dbus/v5/export.go
@@ -26,6 +26,27 @@ var (
}
)
+func MakeNoObjectError(path ObjectPath) Error {
+ return Error{
+ "org.freedesktop.DBus.Error.NoSuchObject",
+ []interface{}{fmt.Sprintf("No such object '%s'", string(path))},
+ }
+}
+
+func MakeUnknownMethodError(methodName string) Error {
+ return Error{
+ "org.freedesktop.DBus.Error.UnknownMethod",
+ []interface{}{fmt.Sprintf("Unknown / invalid method '%s'", methodName)},
+ }
+}
+
+func MakeUnknownInterfaceError(ifaceName string) Error {
+ return Error{
+ "org.freedesktop.DBus.Error.UnknownInterface",
+ []interface{}{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)},
+ }
+}
+
func MakeFailedError(err error) *Error {
return &Error{
"org.freedesktop.DBus.Error.Failed",
@@ -128,6 +149,11 @@ func (conn *Conn) handleCall(msg *Message) {
ifaceName, _ := msg.Headers[FieldInterface].value.(string)
sender, hasSender := msg.Headers[FieldSender].value.(string)
serial := msg.serial
+
+ if len(name) == 0 {
+ conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ }
+
if ifaceName == "org.freedesktop.DBus.Peer" {
switch name {
case "Ping":
@@ -135,29 +161,26 @@ func (conn *Conn) handleCall(msg *Message) {
case "GetMachineId":
conn.sendReply(sender, serial, conn.uuid)
default:
- conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ conn.sendError(MakeUnknownMethodError(name), sender, serial)
}
return
}
- if len(name) == 0 {
- conn.sendError(ErrMsgUnknownMethod, sender, serial)
- }
object, ok := conn.handler.LookupObject(path)
if !ok {
- conn.sendError(ErrMsgNoObject, sender, serial)
+ conn.sendError(MakeNoObjectError(path), sender, serial)
return
}
iface, exists := object.LookupInterface(ifaceName)
if !exists {
- conn.sendError(ErrMsgUnknownInterface, sender, serial)
+ conn.sendError(MakeUnknownInterfaceError(ifaceName), sender, serial)
return
}
m, exists := iface.LookupMethod(name)
if !exists {
- conn.sendError(ErrMsgUnknownMethod, sender, serial)
+ conn.sendError(MakeUnknownMethodError(name), sender, serial)
return
}
args, err := conn.decodeArguments(m, sender, msg)
diff --git a/vendor/github.com/godbus/dbus/v5/message.go b/vendor/github.com/godbus/dbus/v5/message.go
index 6a925367e..16693eb30 100644
--- a/vendor/github.com/godbus/dbus/v5/message.go
+++ b/vendor/github.com/godbus/dbus/v5/message.go
@@ -118,11 +118,7 @@ type header struct {
Variant
}
-// DecodeMessage tries to decode a single message in the D-Bus wire format
-// from the given reader. The byte order is figured out from the first byte.
-// The possibly returned error can be an error of the underlying reader, an
-// InvalidMessageError or a FormatError.
-func DecodeMessage(rd io.Reader) (msg *Message, err error) {
+func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) {
var order binary.ByteOrder
var hlength, length uint32
var typ, flags, proto byte
@@ -142,7 +138,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
return nil, InvalidMessageError("invalid byte order")
}
- dec := newDecoder(rd, order)
+ dec := newDecoder(rd, order, fds)
dec.pos = 1
msg = new(Message)
@@ -166,7 +162,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
if hlength+length+16 > 1<<27 {
return nil, InvalidMessageError("message is too long")
}
- dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order)
+ dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order, fds)
dec.pos = 12
vs, err = dec.Decode(Signature{"a(yv)"})
if err != nil {
@@ -196,7 +192,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
sig, _ := msg.Headers[FieldSignature].value.(Signature)
if sig.str != "" {
buf := bytes.NewBuffer(body)
- dec = newDecoder(buf, order)
+ dec = newDecoder(buf, order, fds)
vs, err := dec.Decode(sig)
if err != nil {
return nil, err
@@ -207,12 +203,32 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
return
}
-// EncodeTo encodes and sends a message to the given writer. The byte order must
-// be either binary.LittleEndian or binary.BigEndian. If the message is not
-// valid or an error occurs when writing, an error is returned.
-func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
+// DecodeMessage tries to decode a single message in the D-Bus wire format
+// from the given reader. The byte order is figured out from the first byte.
+// The possibly returned error can be an error of the underlying reader, an
+// InvalidMessageError or a FormatError.
+func DecodeMessage(rd io.Reader) (msg *Message, err error) {
+ return DecodeMessageWithFDs(rd, make([]int, 0));
+}
+
+type nullwriter struct{}
+
+func (nullwriter) Write(p []byte) (cnt int, err error) {
+ return len(p), nil
+}
+
+func (msg *Message) CountFds() (int, error) {
+ if len(msg.Body) == 0 {
+ return 0, nil
+ }
+ enc := newEncoder(nullwriter{}, nativeEndian, make([]int, 0))
+ err := enc.Encode(msg.Body...)
+ return len(enc.fds), err
+}
+
+func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds []int, err error) {
if err := msg.IsValid(); err != nil {
- return err
+ return make([]int, 0), err
}
var vs [7]interface{}
switch order {
@@ -221,12 +237,16 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
case binary.BigEndian:
vs[0] = byte('B')
default:
- return errors.New("dbus: invalid byte order")
+ return make([]int, 0), errors.New("dbus: invalid byte order")
}
body := new(bytes.Buffer)
- enc := newEncoder(body, order)
+ fds = make([]int, 0)
+ enc := newEncoder(body, order, fds)
if len(msg.Body) != 0 {
- enc.Encode(msg.Body...)
+ err = enc.Encode(msg.Body...)
+ if err != nil {
+ return
+ }
}
vs[1] = msg.Type
vs[2] = msg.Flags
@@ -239,17 +259,28 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
}
vs[6] = headers
var buf bytes.Buffer
- enc = newEncoder(&buf, order)
- enc.Encode(vs[:]...)
+ enc = newEncoder(&buf, order, enc.fds)
+ err = enc.Encode(vs[:]...)
+ if err != nil {
+ return
+ }
enc.align(8)
body.WriteTo(&buf)
if buf.Len() > 1<<27 {
- return InvalidMessageError("message is too long")
+ return make([]int, 0), InvalidMessageError("message is too long")
}
if _, err := buf.WriteTo(out); err != nil {
- return err
+ return make([]int, 0), err
}
- return nil
+ return enc.fds, nil
+}
+
+// EncodeTo encodes and sends a message to the given writer. The byte order must
+// be either binary.LittleEndian or binary.BigEndian. If the message is not
+// valid or an error occurs when writing, an error is returned.
+func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error) {
+ _, err = msg.EncodeToWithFDs(out, order)
+ return err
}
// IsValid checks whether msg is a valid message and returns an
diff --git a/vendor/github.com/godbus/dbus/v5/sig.go b/vendor/github.com/godbus/dbus/v5/sig.go
index 2d326cebc..41a039812 100644
--- a/vendor/github.com/godbus/dbus/v5/sig.go
+++ b/vendor/github.com/godbus/dbus/v5/sig.go
@@ -34,7 +34,7 @@ type Signature struct {
func SignatureOf(vs ...interface{}) Signature {
var s string
for _, v := range vs {
- s += getSignature(reflect.TypeOf(v))
+ s += getSignature(reflect.TypeOf(v), &depthCounter{})
}
return Signature{s}
}
@@ -42,11 +42,19 @@ func SignatureOf(vs ...interface{}) Signature {
// SignatureOfType returns the signature of the given type. It panics if the
// type is not representable in D-Bus.
func SignatureOfType(t reflect.Type) Signature {
- return Signature{getSignature(t)}
+ return Signature{getSignature(t, &depthCounter{})}
}
// getSignature returns the signature of the given type and panics on unknown types.
-func getSignature(t reflect.Type) string {
+func getSignature(t reflect.Type, depth *depthCounter) (sig string) {
+ if !depth.Valid() {
+ panic("container nesting too deep")
+ }
+ defer func() {
+ if len(sig) > 255 {
+ panic("signature exceeds the length limitation")
+ }
+ }()
// handle simple types first
switch t.Kind() {
case reflect.Uint8:
@@ -74,7 +82,7 @@ func getSignature(t reflect.Type) string {
case reflect.Float64:
return "d"
case reflect.Ptr:
- return getSignature(t.Elem())
+ return getSignature(t.Elem(), depth)
case reflect.String:
if t == objectPathType {
return "o"
@@ -90,17 +98,20 @@ func getSignature(t reflect.Type) string {
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
- s += getSignature(t.Field(i).Type)
+ s += getSignature(t.Field(i).Type, depth.EnterStruct())
}
}
+ if len(s) == 0 {
+ panic("empty struct")
+ }
return "(" + s + ")"
case reflect.Array, reflect.Slice:
- return "a" + getSignature(t.Elem())
+ return "a" + getSignature(t.Elem(), depth.EnterArray())
case reflect.Map:
if !isKeyType(t.Key()) {
panic(InvalidTypeError{t})
}
- return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
+ return "a{" + getSignature(t.Key(), depth.EnterArray().EnterDictEntry()) + getSignature(t.Elem(), depth.EnterArray().EnterDictEntry()) + "}"
case reflect.Interface:
return "v"
}
@@ -118,7 +129,7 @@ func ParseSignature(s string) (sig Signature, err error) {
}
sig.str = s
for err == nil && len(s) != 0 {
- err, s = validSingle(s, 0)
+ err, s = validSingle(s, &depthCounter{})
}
if err != nil {
sig = Signature{""}
@@ -144,7 +155,7 @@ func (s Signature) Empty() bool {
// Single returns whether the signature represents a single, complete type.
func (s Signature) Single() bool {
- err, r := validSingle(s.str, 0)
+ err, r := validSingle(s.str, &depthCounter{})
return err != nil && r == ""
}
@@ -164,15 +175,38 @@ func (e SignatureError) Error() string {
return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
}
+type depthCounter struct {
+ arrayDepth, structDepth, dictEntryDepth int
+}
+
+func (cnt *depthCounter) Valid() bool {
+ return cnt.arrayDepth <= 32 && cnt.structDepth <= 32 && cnt.dictEntryDepth <= 32
+}
+
+func (cnt depthCounter) EnterArray() *depthCounter {
+ cnt.arrayDepth++
+ return &cnt
+}
+
+func (cnt depthCounter) EnterStruct() *depthCounter {
+ cnt.structDepth++
+ return &cnt
+}
+
+func (cnt depthCounter) EnterDictEntry() *depthCounter {
+ cnt.dictEntryDepth++
+ return &cnt
+}
+
// Try to read a single type from this string. If it was successful, err is nil
// and rem is the remaining unparsed part. Otherwise, err is a non-nil
// SignatureError and rem is "". depth is the current recursion depth which may
// not be greater than 64 and should be given as 0 on the first call.
-func validSingle(s string, depth int) (err error, rem string) {
+func validSingle(s string, depth *depthCounter) (err error, rem string) {
if s == "" {
return SignatureError{Sig: s, Reason: "empty signature"}, ""
}
- if depth > 64 {
+ if !depth.Valid() {
return SignatureError{Sig: s, Reason: "container nesting too deep"}, ""
}
switch s[0] {
@@ -187,10 +221,10 @@ func validSingle(s string, depth int) (err error, rem string) {
i++
rem = s[i+1:]
s = s[2:i]
- if err, _ = validSingle(s[:1], depth+1); err != nil {
+ if err, _ = validSingle(s[:1], depth.EnterArray().EnterDictEntry()); err != nil {
return err, ""
}
- err, nr := validSingle(s[1:], depth+1)
+ err, nr := validSingle(s[1:], depth.EnterArray().EnterDictEntry())
if err != nil {
return err, ""
}
@@ -199,7 +233,7 @@ func validSingle(s string, depth int) (err error, rem string) {
}
return nil, rem
}
- return validSingle(s[1:], depth+1)
+ return validSingle(s[1:], depth.EnterArray())
case '(':
i := findMatching(s, '(', ')')
if i == -1 {
@@ -208,7 +242,7 @@ func validSingle(s string, depth int) (err error, rem string) {
rem = s[i+1:]
s = s[1:i]
for err == nil && s != "" {
- err, s = validSingle(s, depth+1)
+ err, s = validSingle(s, depth.EnterStruct())
}
if err != nil {
rem = ""
@@ -236,7 +270,7 @@ func findMatching(s string, left, right rune) int {
// typeFor returns the type of the given signature. It ignores any left over
// characters and panics if s doesn't start with a valid type signature.
func typeFor(s string) (t reflect.Type) {
- err, _ := validSingle(s, 0)
+ err, _ := validSingle(s, &depthCounter{})
if err != nil {
panic(err)
}
diff --git a/vendor/github.com/godbus/dbus/v5/transport_generic.go b/vendor/github.com/godbus/dbus/v5/transport_generic.go
index 718a1ff02..a08e2813c 100644
--- a/vendor/github.com/godbus/dbus/v5/transport_generic.go
+++ b/vendor/github.com/godbus/dbus/v5/transport_generic.go
@@ -41,10 +41,12 @@ func (t genericTransport) ReadMessage() (*Message, error) {
}
func (t genericTransport) SendMessage(msg *Message) error {
- for _, v := range msg.Body {
- if _, ok := v.(UnixFD); ok {
- return errors.New("dbus: unix fd passing not enabled")
- }
+ fds, err := msg.CountFds()
+ if err != nil {
+ return err
+ }
+ if fds != 0 {
+ return errors.New("dbus: unix fd passing not enabled")
}
return msg.EncodeTo(t, nativeEndian)
}
diff --git a/vendor/github.com/godbus/dbus/v5/transport_unix.go b/vendor/github.com/godbus/dbus/v5/transport_unix.go
index c7cd02f97..2212e7fa7 100644
--- a/vendor/github.com/godbus/dbus/v5/transport_unix.go
+++ b/vendor/github.com/godbus/dbus/v5/transport_unix.go
@@ -113,7 +113,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil {
return nil, err
}
- dec := newDecoder(bytes.NewBuffer(headerdata), order)
+ dec := newDecoder(bytes.NewBuffer(headerdata), order, make([]int, 0))
dec.pos = 12
vs, err := dec.Decode(Signature{"a(yv)"})
if err != nil {
@@ -147,7 +147,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
if err != nil {
return nil, err
}
- msg, err := DecodeMessage(bytes.NewBuffer(all))
+ msg, err := DecodeMessageWithFDs(bytes.NewBuffer(all), fds)
if err != nil {
return nil, err
}
@@ -179,21 +179,21 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
}
func (t *unixTransport) SendMessage(msg *Message) error {
- fds := make([]int, 0)
- for i, v := range msg.Body {
- if fd, ok := v.(UnixFD); ok {
- msg.Body[i] = UnixFDIndex(len(fds))
- fds = append(fds, int(fd))
- }
+ fdcnt, err := msg.CountFds()
+ if err != nil {
+ return err
}
- if len(fds) != 0 {
+ if fdcnt != 0 {
if !t.hasUnixFDs {
return errors.New("dbus: unix fd passing not enabled")
}
- msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds)))
- oob := syscall.UnixRights(fds...)
+ msg.Headers[FieldUnixFDs] = MakeVariant(uint32(fdcnt))
buf := new(bytes.Buffer)
- msg.EncodeTo(buf, nativeEndian)
+ fds, err := msg.EncodeToWithFDs(buf, nativeEndian)
+ if err != nil {
+ return err
+ }
+ oob := syscall.UnixRights(fds...)
n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
if err != nil {
return err
diff --git a/vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go b/vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go
new file mode 100644
index 000000000..af7bafdf9
--- /dev/null
+++ b/vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go
@@ -0,0 +1,14 @@
+package dbus
+
+import "io"
+
+func (t *unixTransport) SendNullByte() error {
+ n, _, err := t.UnixConn.WriteMsgUnix([]byte{0}, nil, nil)
+ if err != nil {
+ return err
+ }
+ if n != 1 {
+ return io.ErrShortWrite
+ }
+ return nil
+}
diff --git a/vendor/github.com/moby/sys/mountinfo/BUILD.bazel b/vendor/github.com/moby/sys/mountinfo/BUILD.bazel
index 06844d1b8..3831f1777 100644
--- a/vendor/github.com/moby/sys/mountinfo/BUILD.bazel
+++ b/vendor/github.com/moby/sys/mountinfo/BUILD.bazel
@@ -21,9 +21,15 @@ go_library(
"@io_bazel_rules_go//go/platform:android": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
+ "@io_bazel_rules_go//go/platform:darwin": [
+ "//vendor/golang.org/x/sys/unix:go_default_library",
+ ],
"@io_bazel_rules_go//go/platform:freebsd": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
+ "@io_bazel_rules_go//go/platform:ios": [
+ "//vendor/golang.org/x/sys/unix:go_default_library",
+ ],
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
diff --git a/vendor/github.com/moby/sys/mountinfo/mounted_linux.go b/vendor/github.com/moby/sys/mountinfo/mounted_linux.go
index bc9f6b2ad..5c9e3e30e 100644
--- a/vendor/github.com/moby/sys/mountinfo/mounted_linux.go
+++ b/vendor/github.com/moby/sys/mountinfo/mounted_linux.go
@@ -16,9 +16,6 @@ func mountedByOpenat2(path string) (bool, error) {
Flags: unix.O_PATH | unix.O_CLOEXEC,
})
if err != nil {
- if err == unix.ENOENT { // not a mount
- return false, nil
- }
return false, &os.PathError{Op: "openat2", Path: dir, Err: err}
}
fd, err := unix.Openat2(dirfd, last, &unix.OpenHow{
@@ -26,20 +23,22 @@ func mountedByOpenat2(path string) (bool, error) {
Resolve: unix.RESOLVE_NO_XDEV,
})
_ = unix.Close(dirfd)
- switch err {
+ switch err { //nolint:errorlint // unix errors are bare
case nil: // definitely not a mount
_ = unix.Close(fd)
return false, nil
case unix.EXDEV: // definitely a mount
return true, nil
- case unix.ENOENT: // not a mount
- return false, nil
}
// not sure
return false, &os.PathError{Op: "openat2", Path: path, Err: err}
}
func mounted(path string) (bool, error) {
+ path, err := normalizePath(path)
+ if err != nil {
+ return false, err
+ }
// Try a fast path, using openat2() with RESOLVE_NO_XDEV.
mounted, err := mountedByOpenat2(path)
if err == nil {
diff --git a/vendor/github.com/moby/sys/mountinfo/mounted_unix.go b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go
index efb03978b..45ddad236 100644
--- a/vendor/github.com/moby/sys/mountinfo/mounted_unix.go
+++ b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go
@@ -1,9 +1,9 @@
-// +build linux freebsd,cgo openbsd,cgo
+//go:build linux || (freebsd && cgo) || (openbsd && cgo) || (darwin && cgo)
+// +build linux freebsd,cgo openbsd,cgo darwin,cgo
package mountinfo
import (
- "errors"
"fmt"
"os"
"path/filepath"
@@ -15,10 +15,6 @@ func mountedByStat(path string) (bool, error) {
var st unix.Stat_t
if err := unix.Lstat(path, &st); err != nil {
- if err == unix.ENOENT {
- // Treat ENOENT as "not mounted".
- return false, nil
- }
return false, &os.PathError{Op: "stat", Path: path, Err: err}
}
dev := st.Dev
@@ -49,14 +45,6 @@ func normalizePath(path string) (realPath string, err error) {
}
func mountedByMountinfo(path string) (bool, error) {
- path, err := normalizePath(path)
- if err != nil {
- if errors.Is(err, unix.ENOENT) {
- // treat ENOENT as "not mounted"
- return false, nil
- }
- return false, err
- }
entries, err := GetMounts(SingleEntryFilter(path))
if err != nil {
return false, err
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo.go b/vendor/github.com/moby/sys/mountinfo/mountinfo.go
index 403a89331..9867a66dd 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo.go
@@ -10,11 +10,12 @@ func GetMounts(f FilterFunc) ([]*Info, error) {
return parseMountTable(f)
}
-// Mounted determines if a specified path is a mount point.
+// Mounted determines if a specified path is a mount point. In case of any
+// error, false (and an error) is returned.
//
-// The argument must be an absolute path, with all symlinks resolved, and clean.
-// One way to ensure it is to process the path using filepath.Abs followed by
-// filepath.EvalSymlinks before calling this function.
+// The non-existent path returns an error. If a caller is not interested
+// in this particular error, it should handle it separately using e.g.
+// errors.Is(err, os.ErrNotExist).
func Mounted(path string) (bool, error) {
// root is always mounted
if path == string(os.PathSeparator) {
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go
index b1c12d02b..d5513a26d 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go
@@ -1,4 +1,5 @@
-// +build freebsd,cgo openbsd,cgo
+//go:build (freebsd && cgo) || (openbsd && cgo) || (darwin && cgo)
+// +build freebsd,cgo openbsd,cgo darwin,cgo
package mountinfo
@@ -21,7 +22,7 @@ func parseMountTable(filter FilterFunc) ([]*Info, error) {
count := int(C.getmntinfo(&rawEntries, C.MNT_WAIT))
if count == 0 {
- return nil, fmt.Errorf("Failed to call getmntinfo")
+ return nil, fmt.Errorf("failed to call getmntinfo")
}
var entries []C.struct_statfs
@@ -55,6 +56,10 @@ func parseMountTable(filter FilterFunc) ([]*Info, error) {
}
func mounted(path string) (bool, error) {
+ path, err := normalizePath(path)
+ if err != nil {
+ return false, err
+ }
// Fast path: compare st.st_dev fields.
// This should always work for FreeBSD and OpenBSD.
mounted, err := mountedByStat(path)
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go
index f09a70fa0..59332b07b 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go
@@ -52,7 +52,7 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
numFields := len(fields)
if numFields < 10 {
// should be at least 10 fields
- return nil, fmt.Errorf("Parsing '%s' failed: not enough fields (%d)", text, numFields)
+ return nil, fmt.Errorf("parsing '%s' failed: not enough fields (%d)", text, numFields)
}
// separator field
@@ -67,7 +67,7 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
for fields[sepIdx] != "-" {
sepIdx--
if sepIdx == 5 {
- return nil, fmt.Errorf("Parsing '%s' failed: missing - separator", text)
+ return nil, fmt.Errorf("parsing '%s' failed: missing - separator", text)
}
}
@@ -75,46 +75,39 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
p.Mountpoint, err = unescape(fields[4])
if err != nil {
- return nil, fmt.Errorf("Parsing '%s' failed: mount point: %w", fields[4], err)
+ return nil, fmt.Errorf("parsing '%s' failed: mount point: %w", fields[4], err)
}
p.FSType, err = unescape(fields[sepIdx+1])
if err != nil {
- return nil, fmt.Errorf("Parsing '%s' failed: fstype: %w", fields[sepIdx+1], err)
+ return nil, fmt.Errorf("parsing '%s' failed: fstype: %w", fields[sepIdx+1], err)
}
p.Source, err = unescape(fields[sepIdx+2])
if err != nil {
- return nil, fmt.Errorf("Parsing '%s' failed: source: %w", fields[sepIdx+2], err)
+ return nil, fmt.Errorf("parsing '%s' failed: source: %w", fields[sepIdx+2], err)
}
p.VFSOptions = fields[sepIdx+3]
// ignore any numbers parsing errors, as there should not be any
p.ID, _ = strconv.Atoi(fields[0])
p.Parent, _ = strconv.Atoi(fields[1])
- mm := strings.Split(fields[2], ":")
+ mm := strings.SplitN(fields[2], ":", 3)
if len(mm) != 2 {
- return nil, fmt.Errorf("Parsing '%s' failed: unexpected minor:major pair %s", text, mm)
+ return nil, fmt.Errorf("parsing '%s' failed: unexpected major:minor pair %s", text, mm)
}
p.Major, _ = strconv.Atoi(mm[0])
p.Minor, _ = strconv.Atoi(mm[1])
p.Root, err = unescape(fields[3])
if err != nil {
- return nil, fmt.Errorf("Parsing '%s' failed: root: %w", fields[3], err)
+ return nil, fmt.Errorf("parsing '%s' failed: root: %w", fields[3], err)
}
p.Options = fields[5]
// zero or more optional fields
- switch {
- case sepIdx == 6:
- // zero, do nothing
- case sepIdx == 7:
- p.Optional = fields[6]
- default:
- p.Optional = strings.Join(fields[6:sepIdx-1], " ")
- }
+ p.Optional = strings.Join(fields[6:sepIdx], " ")
- // Run the filter after parsing all of the fields.
+ // Run the filter after parsing all fields.
var skip, stop bool
if filter != nil {
skip, stop = filter(p)
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go
index d33ebca09..95769a76d 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go
@@ -1,4 +1,5 @@
-// +build !windows,!linux,!freebsd,!openbsd freebsd,!cgo openbsd,!cgo
+//go:build (!windows && !linux && !freebsd && !openbsd && !darwin) || (freebsd && !cgo) || (openbsd && !cgo) || (darwin && !cgo)
+// +build !windows,!linux,!freebsd,!openbsd,!darwin freebsd,!cgo openbsd,!cgo darwin,!cgo
package mountinfo
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/BUILD.bazel b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/BUILD.bazel
index 492ccf55c..6164811b8 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/BUILD.bazel
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/BUILD.bazel
@@ -4,8 +4,8 @@ go_library(
name = "go_default_library",
srcs = [
"cgroups.go",
- "cgroups_unsupported.go",
"file.go",
+ "getallpids.go",
"stats.go",
"utils.go",
"v1_utils.go",
@@ -16,18 +16,9 @@ go_library(
deps = [
"//vendor/github.com/cyphar/filepath-securejoin:go_default_library",
"//vendor/github.com/moby/sys/mountinfo:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
- ] + select({
- "@io_bazel_rules_go//go/platform:android": [
- "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
- ],
- "@io_bazel_rules_go//go/platform:linux": [
- "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
- ],
- "//conditions:default": [],
- }),
+ ],
)
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
index 68a346ca5..ba2b2266c 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
@@ -1,5 +1,3 @@
-// +build linux
-
package cgroups
import (
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go
deleted file mode 100644
index 278d507e2..000000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// +build !linux
-
-package cgroups
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices/BUILD.bazel b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices/BUILD.bazel
index c4f5c2c1a..5ec5ea5c5 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices/BUILD.bazel
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices/BUILD.bazel
@@ -6,15 +6,5 @@ go_library(
importmap = "kubevirt.io/kubevirt/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices",
importpath = "github.com/opencontainers/runc/libcontainer/cgroups/devices",
visibility = ["//visibility:public"],
- deps = select({
- "@io_bazel_rules_go//go/platform:android": [
- "//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
- ],
- "@io_bazel_rules_go//go/platform:linux": [
- "//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
- ],
- "//conditions:default": [],
- }),
+ deps = ["//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library"],
)
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices/devices_emulator.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices/devices_emulator.go
index c08477cbb..6c61ee4c0 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices/devices_emulator.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices/devices_emulator.go
@@ -1,5 +1,3 @@
-// +build linux
-
// SPDX-License-Identifier: Apache-2.0
/*
* Copyright (C) 2020 Aleksa Sarai <cyphar@cyphar.com>
@@ -22,14 +20,13 @@ package devices
import (
"bufio"
+ "fmt"
"io"
- "regexp"
"sort"
"strconv"
+ "strings"
"github.com/opencontainers/runc/libcontainer/devices"
-
- "github.com/pkg/errors"
)
// deviceMeta is a Rule without the Allow or Permissions fields, and no
@@ -79,19 +76,21 @@ func (e *Emulator) IsAllowAll() bool {
return e.IsBlacklist() && len(e.rules) == 0
}
-var devicesListRegexp = regexp.MustCompile(`^([abc])\s+(\d+|\*):(\d+|\*)\s+([rwm]+)$`)
-
func parseLine(line string) (*deviceRule, error) {
- matches := devicesListRegexp.FindStringSubmatch(line)
- if matches == nil {
- return nil, errors.Errorf("line doesn't match devices.list format")
+ // Input: node major:minor perms.
+ fields := strings.FieldsFunc(line, func(r rune) bool {
+ return r == ' ' || r == ':'
+ })
+ if len(fields) != 4 {
+ return nil, fmt.Errorf("malformed devices.list rule %s", line)
}
+
var (
rule deviceRule
- node = matches[1]
- major = matches[2]
- minor = matches[3]
- perms = matches[4]
+ node = fields[0]
+ major = fields[1]
+ minor = fields[2]
+ perms = fields[3]
)
// Parse the node type.
@@ -107,8 +106,7 @@ func parseLine(line string) (*deviceRule, error) {
case "c":
rule.meta.node = devices.CharDevice
default:
- // Should never happen!
- return nil, errors.Errorf("unknown device type %q", node)
+ return nil, fmt.Errorf("unknown device type %q", node)
}
// Parse the major number.
@@ -117,7 +115,7 @@ func parseLine(line string) (*deviceRule, error) {
} else {
val, err := strconv.ParseUint(major, 10, 32)
if err != nil {
- return nil, errors.Wrap(err, "parse major number")
+ return nil, fmt.Errorf("invalid major number: %w", err)
}
rule.meta.major = int64(val)
}
@@ -128,7 +126,7 @@ func parseLine(line string) (*deviceRule, error) {
} else {
val, err := strconv.ParseUint(minor, 10, 32)
if err != nil {
- return nil, errors.Wrap(err, "parse minor number")
+ return nil, fmt.Errorf("invalid minor number: %w", err)
}
rule.meta.minor = int64(val)
}
@@ -136,13 +134,12 @@ func parseLine(line string) (*deviceRule, error) {
// Parse the access permissions.
rule.perms = devices.Permissions(perms)
if !rule.perms.IsValid() || rule.perms.IsEmpty() {
- // Should never happen!
- return nil, errors.Errorf("parse access mode: contained unknown modes or is empty: %q", perms)
+ return nil, fmt.Errorf("parse access mode: contained unknown modes or is empty: %q", perms)
}
return &rule, nil
}
-func (e *Emulator) addRule(rule deviceRule) error {
+func (e *Emulator) addRule(rule deviceRule) error { //nolint:unparam
if e.rules == nil {
e.rules = make(map[deviceMeta]devices.Permissions)
}
@@ -180,7 +177,7 @@ func (e *Emulator) rmRule(rule deviceRule) error {
// Only give an error if the set of permissions overlap.
partialPerms := e.rules[partialMeta]
if !partialPerms.Intersection(rule.perms).IsEmpty() {
- return errors.Errorf("requested rule [%v %v] not supported by devices cgroupv1 (cannot punch hole in existing wildcard rule [%v %v])", rule.meta, rule.perms, partialMeta, partialPerms)
+ return fmt.Errorf("requested rule [%v %v] not supported by devices cgroupv1 (cannot punch hole in existing wildcard rule [%v %v])", rule.meta, rule.perms, partialMeta, partialPerms)
}
}
@@ -212,9 +209,9 @@ func (e *Emulator) allow(rule *deviceRule) error {
var err error
if e.defaultAllow {
- err = errors.Wrap(e.rmRule(*rule), "remove 'deny' exception")
+ err = wrapErr(e.rmRule(*rule), "unable to remove 'deny' exception")
} else {
- err = errors.Wrap(e.addRule(*rule), "add 'allow' exception")
+ err = wrapErr(e.addRule(*rule), "unable to add 'allow' exception")
}
return err
}
@@ -232,16 +229,16 @@ func (e *Emulator) deny(rule *deviceRule) error {
var err error
if e.defaultAllow {
- err = errors.Wrap(e.addRule(*rule), "add 'deny' exception")
+ err = wrapErr(e.addRule(*rule), "unable to add 'deny' exception")
} else {
- err = errors.Wrap(e.rmRule(*rule), "remove 'allow' exception")
+ err = wrapErr(e.rmRule(*rule), "unable to remove 'allow' exception")
}
return err
}
func (e *Emulator) Apply(rule devices.Rule) error {
if !rule.Type.CanCgroup() {
- return errors.Errorf("cannot add rule [%#v] with non-cgroup type %q", rule, rule.Type)
+ return fmt.Errorf("cannot add rule [%#v] with non-cgroup type %q", rule, rule.Type)
}
innerRule := &deviceRule{
@@ -283,17 +280,17 @@ func EmulatorFromList(list io.Reader) (*Emulator, error) {
line := s.Text()
deviceRule, err := parseLine(line)
if err != nil {
- return nil, errors.Wrapf(err, "parsing line %q", line)
+ return nil, fmt.Errorf("error parsing line %q: %w", line, err)
}
// "devices.list" is an allow list. Note that this means that in
// black-list mode, we have no idea what rules are in play. As a
// result, we need to be very careful in Transition().
if err := e.allow(deviceRule); err != nil {
- return nil, errors.Wrapf(err, "adding devices.list rule")
+ return nil, fmt.Errorf("error adding devices.list rule: %w", err)
}
}
if err := s.Err(); err != nil {
- return nil, errors.Wrap(err, "reading devices.list lines")
+ return nil, fmt.Errorf("error reading devices.list lines: %w", err)
}
return e, nil
}
@@ -305,7 +302,7 @@ func EmulatorFromList(list io.Reader) (*Emulator, error) {
// necessary.
//
// This function is the sole reason for all of Emulator -- to allow us
-// to figure out how to update a containers' cgroups without causing spurrious
+// to figure out how to update a containers' cgroups without causing spurious
// device errors (if possible).
func (source *Emulator) Transition(target *Emulator) ([]*devices.Rule, error) {
var transitionRules []*devices.Rule
@@ -380,3 +377,10 @@ func (e *Emulator) Rules() ([]*devices.Rule, error) {
defaultCgroup := &Emulator{defaultAllow: false}
return defaultCgroup.Transition(e)
}
+
+func wrapErr(err error, text string) error {
+ if err == nil {
+ return nil
+ }
+ return fmt.Errorf(text+": %w", err)
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/BUILD.bazel b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/BUILD.bazel
index 1136626f5..d667bebaf 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/BUILD.bazel
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/BUILD.bazel
@@ -11,7 +11,6 @@ go_library(
"//vendor/github.com/cilium/ebpf:go_default_library",
"//vendor/github.com/cilium/ebpf/asm:go_default_library",
"//vendor/github.com/cilium/ebpf/link:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
],
@@ -19,7 +18,6 @@ go_library(
"//vendor/github.com/cilium/ebpf:go_default_library",
"//vendor/github.com/cilium/ebpf/asm:go_default_library",
"//vendor/github.com/cilium/ebpf/link:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
],
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter/BUILD.bazel b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter/BUILD.bazel
index 5eabf95e0..9f9901a1a 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter/BUILD.bazel
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter/BUILD.bazel
@@ -10,7 +10,6 @@ go_library(
"//vendor/github.com/cilium/ebpf/asm:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
],
)
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go
index 96cbca391..4e69b35bc 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go
@@ -7,13 +7,14 @@
package devicefilter
import (
+ "errors"
+ "fmt"
"math"
"strconv"
"github.com/cilium/ebpf/asm"
devicesemulator "github.com/opencontainers/runc/libcontainer/cgroups/devices"
"github.com/opencontainers/runc/libcontainer/devices"
- "github.com/pkg/errors"
"golang.org/x/sys/unix"
)
@@ -51,21 +52,20 @@ func DeviceFilter(rules []*devices.Rule) (asm.Instructions, string, error) {
// only be one (at most) at the very start to instruct cgroupv1 to
// go into allow-list mode. However we do double-check this here.
if idx != 0 || rule.Allow != emu.IsBlacklist() {
- return nil, "", errors.Errorf("[internal error] emulated cgroupv2 devices ruleset had bad wildcard at idx %v (%s)", idx, rule.CgroupString())
+ return nil, "", fmt.Errorf("[internal error] emulated cgroupv2 devices ruleset had bad wildcard at idx %v (%s)", idx, rule.CgroupString())
}
continue
}
if rule.Allow == p.defaultAllow {
// There should be no rules which have an action equal to the
// default action, the emulator removes those.
- return nil, "", errors.Errorf("[internal error] emulated cgroupv2 devices ruleset had no-op rule at idx %v (%s)", idx, rule.CgroupString())
+ return nil, "", fmt.Errorf("[internal error] emulated cgroupv2 devices ruleset had no-op rule at idx %v (%s)", idx, rule.CgroupString())
}
if err := p.appendRule(rule); err != nil {
return nil, "", err
}
}
- insts, err := p.finalize()
- return insts, license, err
+ return p.finalize(), license, nil
}
type program struct {
@@ -118,13 +118,13 @@ func (p *program) appendRule(rule *devices.Rule) error {
bpfType = int32(unix.BPF_DEVCG_DEV_BLOCK)
default:
// We do not permit 'a', nor any other types we don't know about.
- return errors.Errorf("invalid type %q", string(rule.Type))
+ return fmt.Errorf("invalid type %q", string(rule.Type))
}
if rule.Major > math.MaxUint32 {
- return errors.Errorf("invalid major %d", rule.Major)
+ return fmt.Errorf("invalid major %d", rule.Major)
}
if rule.Minor > math.MaxUint32 {
- return errors.Errorf("invalid minor %d", rule.Major)
+ return fmt.Errorf("invalid minor %d", rule.Major)
}
hasMajor := rule.Major >= 0 // if not specified in OCI json, major is set to -1
hasMinor := rule.Minor >= 0
@@ -138,7 +138,7 @@ func (p *program) appendRule(rule *devices.Rule) error {
case 'm':
bpfAccess |= unix.BPF_DEVCG_ACC_MKNOD
default:
- return errors.Errorf("unknown device access %v", r)
+ return fmt.Errorf("unknown device access %v", r)
}
}
// If the access is rwm, skip the check.
@@ -180,7 +180,7 @@ func (p *program) appendRule(rule *devices.Rule) error {
return nil
}
-func (p *program) finalize() (asm.Instructions, error) {
+func (p *program) finalize() asm.Instructions {
var v int32
if p.defaultAllow {
v = 1
@@ -192,7 +192,7 @@ func (p *program) finalize() (asm.Instructions, error) {
asm.Return(),
)
p.blockID = -1
- return p.insts, nil
+ return p.insts
}
func acceptBlock(accept bool) asm.Instructions {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf_linux.go
index 6c8de80dd..104c74a89 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf_linux.go
@@ -1,6 +1,7 @@
package ebpf
import (
+ "errors"
"fmt"
"os"
"runtime"
@@ -10,7 +11,6 @@ import (
"github.com/cilium/ebpf"
"github.com/cilium/ebpf/asm"
"github.com/cilium/ebpf/link"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@@ -134,7 +134,7 @@ func haveBpfProgReplace() bool {
// not supported
return
}
- // attach_flags test succeded.
+ // attach_flags test succeeded.
if !errors.Is(err, unix.EBADF) {
logrus.Debugf("checking for BPF_F_REPLACE: got unexpected (not EBADF or EINVAL) error: %v", err)
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
index 5f6ab9fd6..0cdaf7478 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
@@ -2,20 +2,27 @@ package cgroups
import (
"bytes"
+ "errors"
+ "fmt"
"os"
+ "path"
+ "strconv"
"strings"
"sync"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
// OpenFile opens a cgroup file in a given dir with given flags.
-// It is supposed to be used for cgroup files only.
+// It is supposed to be used for cgroup files only, and returns
+// an error if the file is not a cgroup file.
+//
+// Arguments dir and file are joined together to form an absolute path
+// to a file being opened.
func OpenFile(dir, file string, flags int) (*os.File, error) {
if dir == "" {
- return nil, errors.Errorf("no directory specified for %s", file)
+ return nil, fmt.Errorf("no directory specified for %s", file)
}
return openFile(dir, file, flags)
}
@@ -43,7 +50,8 @@ func WriteFile(dir, file, data string) error {
}
defer fd.Close()
if err := retryingWriteFile(fd, data); err != nil {
- return errors.Wrapf(err, "failed to write %q", data)
+ // Having data in the error message helps in debugging.
+ return fmt.Errorf("failed to write %q: %w", data, err)
}
return nil
}
@@ -81,7 +89,7 @@ func prepareOpenat2() error {
})
if err != nil {
prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
- if err != unix.ENOSYS {
+ if err != unix.ENOSYS { //nolint:errorlint // unix errors are bare
logrus.Warnf("falling back to securejoin: %s", prepErr)
} else {
logrus.Debug("openat2 not available, falling back to securejoin")
@@ -107,8 +115,6 @@ func prepareOpenat2() error {
return prepErr
}
-// OpenFile opens a cgroup file in a given dir with given flags.
-// It is supposed to be used for cgroup files only.
func openFile(dir, file string, flags int) (*os.File, error) {
mode := os.FileMode(0)
if TestMode && flags&os.O_WRONLY != 0 {
@@ -116,34 +122,52 @@ func openFile(dir, file string, flags int) (*os.File, error) {
flags |= os.O_TRUNC | os.O_CREATE
mode = 0o600
}
+ path := path.Join(dir, file)
if prepareOpenat2() != nil {
- return openFallback(dir, file, flags, mode)
+ return openFallback(path, flags, mode)
}
- reldir := strings.TrimPrefix(dir, cgroupfsPrefix)
- if len(reldir) == len(dir) { // non-standard path, old system?
- return openFallback(dir, file, flags, mode)
+ relPath := strings.TrimPrefix(path, cgroupfsPrefix)
+ if len(relPath) == len(path) { // non-standard path, old system?
+ return openFallback(path, flags, mode)
}
- relname := reldir + "/" + file
- fd, err := unix.Openat2(cgroupFd, relname,
+ fd, err := unix.Openat2(cgroupFd, relPath,
&unix.OpenHow{
Resolve: resolveFlags,
Flags: uint64(flags) | unix.O_CLOEXEC,
Mode: uint64(mode),
})
if err != nil {
- return nil, &os.PathError{Op: "openat2", Path: dir + "/" + file, Err: err}
+ err = &os.PathError{Op: "openat2", Path: path, Err: err}
+ // Check if cgroupFd is still opened to cgroupfsDir
+ // (happens when this package is incorrectly used
+ // across the chroot/pivot_root/mntns boundary, or
+ // when /sys/fs/cgroup is remounted).
+ //
+ // TODO: if such usage will ever be common, amend this
+ // to reopen cgroupFd and retry openat2.
+ fdStr := strconv.Itoa(cgroupFd)
+ fdDest, _ := os.Readlink("/proc/self/fd/" + fdStr)
+ if fdDest != cgroupfsDir {
+ // Wrap the error so it is clear that cgroupFd
+ // is opened to an unexpected/wrong directory.
+ err = fmt.Errorf("cgroupFd %s unexpectedly opened to %s != %s: %w",
+ fdStr, fdDest, cgroupfsDir, err)
+ }
+ return nil, err
}
- return os.NewFile(uintptr(fd), cgroupfsPrefix+relname), nil
+ return os.NewFile(uintptr(fd), path), nil
}
var errNotCgroupfs = errors.New("not a cgroup file")
-// openFallback is used when openat2(2) is not available. It checks the opened
+// Can be changed by unit tests.
+var openFallback = openAndCheck
+
+// openAndCheck is used when openat2(2) is not available. It checks the opened
// file is on cgroupfs, returning an error otherwise.
-func openFallback(dir, file string, flags int, mode os.FileMode) (*os.File, error) {
- path := dir + "/" + file
+func openAndCheck(path string, flags int, mode os.FileMode) (*os.File, error) {
fd, err := os.OpenFile(path, flags, mode)
if err != nil {
return nil, err
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD.bazel b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD.bazel
index 6ada94d56..12508e89f 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD.bazel
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD.bazel
@@ -8,6 +8,7 @@ go_library(
"cpuacct.go",
"cpuset.go",
"devices.go",
+ "error.go",
"freezer.go",
"fs.go",
"hugetlb.go",
@@ -15,38 +16,23 @@ go_library(
"name.go",
"net_cls.go",
"net_prio.go",
+ "paths.go",
"perf_event.go",
"pids.go",
- "unsupported.go",
+ "rdma.go",
],
importmap = "kubevirt.io/kubevirt/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs",
importpath = "github.com/opencontainers/runc/libcontainer/cgroups/fs",
visibility = ["//visibility:public"],
- deps = select({
- "@io_bazel_rules_go//go/platform:android": [
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/utils:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
- "//vendor/github.com/sirupsen/logrus:go_default_library",
- "//vendor/golang.org/x/sys/unix:go_default_library",
- ],
- "@io_bazel_rules_go//go/platform:linux": [
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/utils:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
- "//vendor/github.com/sirupsen/logrus:go_default_library",
- "//vendor/golang.org/x/sys/unix:go_default_library",
- ],
- "//conditions:default": [],
- }),
+ deps = [
+ "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/devices:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/utils:go_default_library",
+ "//vendor/github.com/sirupsen/logrus:go_default_library",
+ "//vendor/golang.org/x/sys/unix:go_default_library",
+ ],
)
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go
index 88012a2f5..c81b6562a 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go
@@ -1,10 +1,7 @@
-// +build linux
-
package fs
import (
"bufio"
- "fmt"
"os"
"path/filepath"
"strconv"
@@ -23,8 +20,8 @@ func (s *BlkioGroup) Name() string {
return "blkio"
}
-func (s *BlkioGroup) Apply(path string, d *cgroupData) error {
- return join(path, d.pid)
+func (s *BlkioGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func (s *BlkioGroup) Set(path string, r *configs.Resources) error {
@@ -131,19 +128,19 @@ func getBlkioStat(dir, file string) ([]cgroups.BlkioStatEntry, error) {
// skip total line
continue
} else {
- return nil, fmt.Errorf("Invalid line found while parsing %s/%s: %s", dir, file, sc.Text())
+ return nil, malformedLine(dir, file, sc.Text())
}
}
v, err := strconv.ParseUint(fields[0], 10, 64)
if err != nil {
- return nil, err
+ return nil, &parseError{Path: dir, File: file, Err: err}
}
major := v
v, err = strconv.ParseUint(fields[1], 10, 64)
if err != nil {
- return nil, err
+ return nil, &parseError{Path: dir, File: file, Err: err}
}
minor := v
@@ -155,10 +152,13 @@ func getBlkioStat(dir, file string) ([]cgroups.BlkioStatEntry, error) {
}
v, err = strconv.ParseUint(fields[valueField], 10, 64)
if err != nil {
- return nil, err
+ return nil, &parseError{Path: dir, File: file, Err: err}
}
blkioStats = append(blkioStats, cgroups.BlkioStatEntry{Major: major, Minor: minor, Op: op, Value: v})
}
+ if err := sc.Err(); err != nil {
+ return nil, &parseError{Path: dir, File: file, Err: err}
+ }
return blkioStats, nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go
index 7ca8b8a8d..6c79f899b 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs
import (
@@ -21,24 +19,19 @@ func (s *CpuGroup) Name() string {
return "cpu"
}
-func (s *CpuGroup) Apply(path string, d *cgroupData) error {
- // This might happen if we have no cpu cgroup mounted.
- // Just do nothing and don't fail.
- if path == "" {
- return nil
- }
+func (s *CpuGroup) Apply(path string, r *configs.Resources, pid int) error {
if err := os.MkdirAll(path, 0o755); err != nil {
return err
}
// We should set the real-Time group scheduling settings before moving
// in the process because if the process is already in SCHED_RR mode
// and no RT bandwidth is set, adding it will fail.
- if err := s.SetRtSched(path, d.config.Resources); err != nil {
+ if err := s.SetRtSched(path, r); err != nil {
return err
}
- // Since we are not using join(), we need to place the pid
- // into the procs file unlike other subsystems.
- return cgroups.WriteCgroupProc(path, d.pid)
+ // Since we are not using apply(), we need to place the pid
+ // into the procs file.
+ return cgroups.WriteCgroupProc(path, pid)
}
func (s *CpuGroup) SetRtSched(path string, r *configs.Resources) error {
@@ -105,7 +98,8 @@ func (s *CpuGroup) Set(path string, r *configs.Resources) error {
}
func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error {
- f, err := cgroups.OpenFile(path, "cpu.stat", os.O_RDONLY)
+ const file = "cpu.stat"
+ f, err := cgroups.OpenFile(path, file, os.O_RDONLY)
if err != nil {
if os.IsNotExist(err) {
return nil
@@ -118,7 +112,7 @@ func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error {
for sc.Scan() {
t, v, err := fscommon.ParseKeyValue(sc.Text())
if err != nil {
- return err
+ return &parseError{Path: path, File: file, Err: err}
}
switch t {
case "nr_periods":
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go
index 4fbf07849..d3bd7e111 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go
@@ -1,12 +1,8 @@
-// +build linux
-
package fs
import (
"bufio"
- "fmt"
"os"
- "path/filepath"
"strconv"
"strings"
@@ -38,8 +34,8 @@ func (s *CpuacctGroup) Name() string {
return "cpuacct"
}
-func (s *CpuacctGroup) Apply(path string, d *cgroupData) error {
- return join(path, d.pid)
+func (s *CpuacctGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func (s *CpuacctGroup) Set(_ string, _ *configs.Resources) error {
@@ -85,45 +81,43 @@ func getCpuUsageBreakdown(path string) (uint64, uint64, error) {
const (
userField = "user"
systemField = "system"
+ file = cgroupCpuacctStat
)
// Expected format:
// user <usage in ticks>
// system <usage in ticks>
- data, err := cgroups.ReadFile(path, cgroupCpuacctStat)
+ data, err := cgroups.ReadFile(path, file)
if err != nil {
return 0, 0, err
}
+ // TODO: use strings.SplitN instead.
fields := strings.Fields(data)
- if len(fields) < 4 {
- return 0, 0, fmt.Errorf("failure - %s is expected to have at least 4 fields", filepath.Join(path, cgroupCpuacctStat))
- }
- if fields[0] != userField {
- return 0, 0, fmt.Errorf("unexpected field %q in %q, expected %q", fields[0], cgroupCpuacctStat, userField)
- }
- if fields[2] != systemField {
- return 0, 0, fmt.Errorf("unexpected field %q in %q, expected %q", fields[2], cgroupCpuacctStat, systemField)
+ if len(fields) < 4 || fields[0] != userField || fields[2] != systemField {
+ return 0, 0, malformedLine(path, file, data)
}
if userModeUsage, err = strconv.ParseUint(fields[1], 10, 64); err != nil {
- return 0, 0, err
+ return 0, 0, &parseError{Path: path, File: file, Err: err}
}
if kernelModeUsage, err = strconv.ParseUint(fields[3], 10, 64); err != nil {
- return 0, 0, err
+ return 0, 0, &parseError{Path: path, File: file, Err: err}
}
return (userModeUsage * nanosecondsInSecond) / clockTicks, (kernelModeUsage * nanosecondsInSecond) / clockTicks, nil
}
func getPercpuUsage(path string) ([]uint64, error) {
+ const file = "cpuacct.usage_percpu"
percpuUsage := []uint64{}
- data, err := cgroups.ReadFile(path, "cpuacct.usage_percpu")
+ data, err := cgroups.ReadFile(path, file)
if err != nil {
return percpuUsage, err
}
+ // TODO: use strings.SplitN instead.
for _, value := range strings.Fields(data) {
value, err := strconv.ParseUint(value, 10, 64)
if err != nil {
- return percpuUsage, fmt.Errorf("Unable to convert param value to uint64: %s", err)
+ return percpuUsage, &parseError{Path: path, File: file, Err: err}
}
percpuUsage = append(percpuUsage, value)
}
@@ -133,16 +127,17 @@ func getPercpuUsage(path string) ([]uint64, error) {
func getPercpuUsageInModes(path string) ([]uint64, []uint64, error) {
usageKernelMode := []uint64{}
usageUserMode := []uint64{}
+ const file = cgroupCpuacctUsageAll
- file, err := cgroups.OpenFile(path, cgroupCpuacctUsageAll, os.O_RDONLY)
+ fd, err := cgroups.OpenFile(path, file, os.O_RDONLY)
if os.IsNotExist(err) {
return usageKernelMode, usageUserMode, nil
} else if err != nil {
return nil, nil, err
}
- defer file.Close()
+ defer fd.Close()
- scanner := bufio.NewScanner(file)
+ scanner := bufio.NewScanner(fd)
scanner.Scan() // skipping header line
for scanner.Scan() {
@@ -153,19 +148,18 @@ func getPercpuUsageInModes(path string) ([]uint64, []uint64, error) {
usageInKernelMode, err := strconv.ParseUint(lineFields[kernelModeColumn], 10, 64)
if err != nil {
- return nil, nil, fmt.Errorf("Unable to convert CPU usage in kernel mode to uint64: %s", err)
+ return nil, nil, &parseError{Path: path, File: file, Err: err}
}
usageKernelMode = append(usageKernelMode, usageInKernelMode)
usageInUserMode, err := strconv.ParseUint(lineFields[userModeColumn], 10, 64)
if err != nil {
- return nil, nil, fmt.Errorf("Unable to convert CPU usage in user mode to uint64: %s", err)
+ return nil, nil, &parseError{Path: path, File: file, Err: err}
}
usageUserMode = append(usageUserMode, usageInUserMode)
}
-
if err := scanner.Err(); err != nil {
- return nil, nil, fmt.Errorf("Problem in reading %s line by line, %s", cgroupCpuacctUsageAll, err)
+ return nil, nil, &parseError{Path: path, File: file, Err: err}
}
return usageKernelMode, usageUserMode, nil
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go
index 58a0f0406..550baa427 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go
@@ -1,19 +1,17 @@
-// +build linux
-
package fs
import (
- "fmt"
+ "errors"
"os"
"path/filepath"
"strconv"
"strings"
+ "golang.org/x/sys/unix"
+
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
"github.com/opencontainers/runc/libcontainer/configs"
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
type CpusetGroup struct{}
@@ -22,8 +20,8 @@ func (s *CpusetGroup) Name() string {
return "cpuset"
}
-func (s *CpusetGroup) Apply(path string, d *cgroupData) error {
- return s.ApplyDir(path, d.config.Resources, d.pid)
+func (s *CpusetGroup) Apply(path string, r *configs.Resources, pid int) error {
+ return s.ApplyDir(path, r, pid)
}
func (s *CpusetGroup) Set(path string, r *configs.Resources) error {
@@ -40,32 +38,32 @@ func (s *CpusetGroup) Set(path string, r *configs.Resources) error {
return nil
}
-func getCpusetStat(path string, filename string) ([]uint16, error) {
+func getCpusetStat(path string, file string) ([]uint16, error) {
var extracted []uint16
- fileContent, err := fscommon.GetCgroupParamString(path, filename)
+ fileContent, err := fscommon.GetCgroupParamString(path, file)
if err != nil {
return extracted, err
}
if len(fileContent) == 0 {
- return extracted, fmt.Errorf("%s found to be empty", filepath.Join(path, filename))
+ return extracted, &parseError{Path: path, File: file, Err: errors.New("empty file")}
}
for _, s := range strings.Split(fileContent, ",") {
- splitted := strings.SplitN(s, "-", 3)
- switch len(splitted) {
+ sp := strings.SplitN(s, "-", 3)
+ switch len(sp) {
case 3:
- return extracted, fmt.Errorf("invalid values in %s", filepath.Join(path, filename))
+ return extracted, &parseError{Path: path, File: file, Err: errors.New("extra dash")}
case 2:
- min, err := strconv.ParseUint(splitted[0], 10, 16)
+ min, err := strconv.ParseUint(sp[0], 10, 16)
if err != nil {
- return extracted, err
+ return extracted, &parseError{Path: path, File: file, Err: err}
}
- max, err := strconv.ParseUint(splitted[1], 10, 16)
+ max, err := strconv.ParseUint(sp[1], 10, 16)
if err != nil {
- return extracted, err
+ return extracted, &parseError{Path: path, File: file, Err: err}
}
if min > max {
- return extracted, fmt.Errorf("invalid values in %s", filepath.Join(path, filename))
+ return extracted, &parseError{Path: path, File: file, Err: errors.New("invalid values, min > max")}
}
for i := min; i <= max; i++ {
extracted = append(extracted, uint16(i))
@@ -73,7 +71,7 @@ func getCpusetStat(path string, filename string) ([]uint16, error) {
case 1:
value, err := strconv.ParseUint(s, 10, 16)
if err != nil {
- return extracted, err
+ return extracted, &parseError{Path: path, File: file, Err: err}
}
extracted = append(extracted, uint16(value))
}
@@ -168,9 +166,8 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error
if err := s.ensureCpusAndMems(dir, r); err != nil {
return err
}
-
- // because we are not using d.join we need to place the pid into the procs file
- // unlike the other subsystems
+ // Since we are not using apply(), we need to place the pid
+ // into the procs file.
return cgroups.WriteCgroupProc(dir, pid)
}
@@ -198,7 +195,7 @@ func cpusetEnsureParent(current string) error {
}
// Treat non-existing directory as cgroupfs as it will be created,
// and the root cpuset directory obviously exists.
- if err != nil && err != unix.ENOENT {
+ if err != nil && err != unix.ENOENT { //nolint:errorlint // unix errors are bare
return &os.PathError{Op: "statfs", Path: parent, Err: err}
}
@@ -224,12 +221,12 @@ func cpusetCopyIfNeeded(current, parent string) error {
}
if isEmptyCpuset(currentCpus) {
- if err := cgroups.WriteFile(current, "cpuset.cpus", string(parentCpus)); err != nil {
+ if err := cgroups.WriteFile(current, "cpuset.cpus", parentCpus); err != nil {
return err
}
}
if isEmptyCpuset(currentMems) {
- if err := cgroups.WriteFile(current, "cpuset.mems", string(parentMems)); err != nil {
+ if err := cgroups.WriteFile(current, "cpuset.mems", parentMems); err != nil {
return err
}
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go
index dcf69ce13..4527a70eb 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs
import (
@@ -15,15 +13,15 @@ import (
)
type DevicesGroup struct {
- testingSkipFinalCheck bool
+ TestingSkipFinalCheck bool
}
func (s *DevicesGroup) Name() string {
return "devices"
}
-func (s *DevicesGroup) Apply(path string, d *cgroupData) error {
- if d.config.SkipDevices {
+func (s *DevicesGroup) Apply(path string, r *configs.Resources, pid int) error {
+ if r.SkipDevices {
return nil
}
if path == "" {
@@ -31,7 +29,8 @@ func (s *DevicesGroup) Apply(path string, d *cgroupData) error {
// is a hard requirement for container's security.
return errSubsystemDoesNotExist
}
- return join(path, d.pid)
+
+ return apply(path, pid)
}
func loadEmulator(path string) (*cgroupdevices.Emulator, error) {
@@ -91,7 +90,7 @@ func (s *DevicesGroup) Set(path string, r *configs.Resources) error {
//
// This safety-check is skipped for the unit tests because we cannot
// currently mock devices.list correctly.
- if !s.testingSkipFinalCheck {
+ if !s.TestingSkipFinalCheck {
currentAfter, err := loadEmulator(path)
if err != nil {
return err
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/error.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/error.go
new file mode 100644
index 000000000..f2ab6f130
--- /dev/null
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/error.go
@@ -0,0 +1,15 @@
+package fs
+
+import (
+ "fmt"
+
+ "github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
+)
+
+type parseError = fscommon.ParseError
+
+// malformedLine is used by all cgroupfs file parsers that expect a line
+// in a particular format but get some garbage instead.
+func malformedLine(path, file, line string) error {
+ return &parseError{Path: path, File: file, Err: fmt.Errorf("malformed line: %s", line)}
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go
index 4baa2798a..987f1bf5e 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs
import (
@@ -21,8 +19,8 @@ func (s *FreezerGroup) Name() string {
return "freezer"
}
-func (s *FreezerGroup) Apply(path string, d *cgroupData) error {
- return join(path, d.pid)
+func (s *FreezerGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go
index 777b94f03..fb4fcc7f7 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go
@@ -1,165 +1,86 @@
-// +build linux
-
package fs
import (
+ "errors"
"fmt"
"os"
- "path/filepath"
"sync"
+ "golang.org/x/sys/unix"
+
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
"github.com/opencontainers/runc/libcontainer/configs"
- libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
-var (
- subsystems = []subsystem{
- &CpusetGroup{},
- &DevicesGroup{},
- &MemoryGroup{},
- &CpuGroup{},
- &CpuacctGroup{},
- &PidsGroup{},
- &BlkioGroup{},
- &HugetlbGroup{},
- &NetClsGroup{},
- &NetPrioGroup{},
- &PerfEventGroup{},
- &FreezerGroup{},
- &NameGroup{GroupName: "name=systemd", Join: true},
- }
- HugePageSizes, _ = cgroups.GetHugePageSize()
-)
+var subsystems = []subsystem{
+ &CpusetGroup{},
+ &DevicesGroup{},
+ &MemoryGroup{},
+ &CpuGroup{},
+ &CpuacctGroup{},
+ &PidsGroup{},
+ &BlkioGroup{},
+ &HugetlbGroup{},
+ &NetClsGroup{},
+ &NetPrioGroup{},
+ &PerfEventGroup{},
+ &FreezerGroup{},
+ &RdmaGroup{},
+ &NameGroup{GroupName: "name=systemd", Join: true},
+}
var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist")
+func init() {
+ // If using cgroups-hybrid mode then add a "" controller indicating
+ // it should join the cgroups v2.
+ if cgroups.IsCgroup2HybridMode() {
+ subsystems = append(subsystems, &NameGroup{GroupName: "", Join: true})
+ }
+}
+
type subsystem interface {
// Name returns the name of the subsystem.
Name() string
- // Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
+ // GetStats fills in the stats for the subsystem.
GetStats(path string, stats *cgroups.Stats) error
- // Creates and joins the cgroup represented by 'cgroupData'.
- Apply(path string, c *cgroupData) error
+ // Apply creates and joins a cgroup, adding pid into it. Some
+ // subsystems use resources to pre-configure the cgroup parents
+ // before creating or joining it.
+ Apply(path string, r *configs.Resources, pid int) error
// Set sets the cgroup resources.
Set(path string, r *configs.Resources) error
}
type manager struct {
- mu sync.Mutex
- cgroups *configs.Cgroup
- rootless bool // ignore permission-related errors
- paths map[string]string
-}
-
-func NewManager(cg *configs.Cgroup, paths map[string]string, rootless bool) cgroups.Manager {
- return &manager{
- cgroups: cg,
- paths: paths,
- rootless: rootless,
- }
-}
-
-// The absolute path to the root of the cgroup hierarchies.
-var (
- cgroupRootLock sync.Mutex
- cgroupRoot string
-)
-
-const defaultCgroupRoot = "/sys/fs/cgroup"
-
-func tryDefaultCgroupRoot() string {
- var st, pst unix.Stat_t
-
- // (1) it should be a directory...
- err := unix.Lstat(defaultCgroupRoot, &st)
- if err != nil || st.Mode&unix.S_IFDIR == 0 {
- return ""
- }
-
- // (2) ... and a mount point ...
- err = unix.Lstat(filepath.Dir(defaultCgroupRoot), &pst)
- if err != nil {
- return ""
- }
-
- if st.Dev == pst.Dev {
- // parent dir has the same dev -- not a mount point
- return ""
- }
-
- // (3) ... of 'tmpfs' fs type.
- var fst unix.Statfs_t
- err = unix.Statfs(defaultCgroupRoot, &fst)
- if err != nil || fst.Type != unix.TMPFS_MAGIC {
- return ""
- }
-
- // (4) it should have at least 1 entry ...
- dir, err := os.Open(defaultCgroupRoot)
- if err != nil {
- return ""
- }
- names, err := dir.Readdirnames(1)
- if err != nil {
- return ""
- }
- if len(names) < 1 {
- return ""
- }
- // ... which is a cgroup mount point.
- err = unix.Statfs(filepath.Join(defaultCgroupRoot, names[0]), &fst)
- if err != nil || fst.Type != unix.CGROUP_SUPER_MAGIC {
- return ""
- }
-
- return defaultCgroupRoot
+ mu sync.Mutex
+ cgroups *configs.Cgroup
+ paths map[string]string
}
-// Gets the cgroupRoot.
-func getCgroupRoot() (string, error) {
- cgroupRootLock.Lock()
- defer cgroupRootLock.Unlock()
-
- if cgroupRoot != "" {
- return cgroupRoot, nil
- }
-
- // fast path
- cgroupRoot = tryDefaultCgroupRoot()
- if cgroupRoot != "" {
- return cgroupRoot, nil
+func NewManager(cg *configs.Cgroup, paths map[string]string) (cgroups.Manager, error) {
+ // Some v1 controllers (cpu, cpuset, and devices) expect
+ // cgroups.Resources to not be nil in Apply.
+ if cg.Resources == nil {
+ return nil, errors.New("cgroup v1 manager needs configs.Resources to be set during manager creation")
}
-
- // slow path: parse mountinfo
- mi, err := cgroups.GetCgroupMounts(false)
- if err != nil {
- return "", err
- }
- if len(mi) < 1 {
- return "", errors.New("no cgroup mount found in mountinfo")
+ if cg.Resources.Unified != nil {
+ return nil, cgroups.ErrV1NoUnified
}
- // Get the first cgroup mount (e.g. "/sys/fs/cgroup/memory"),
- // use its parent directory.
- root := filepath.Dir(mi[0].Mountpoint)
-
- if _, err := os.Stat(root); err != nil {
- return "", err
+ if paths == nil {
+ var err error
+ paths, err = initPaths(cg)
+ if err != nil {
+ return nil, err
+ }
}
- cgroupRoot = root
- return cgroupRoot, nil
-}
-
-type cgroupData struct {
- root string
- innerPath string
- config *configs.Cgroup
- pid int
+ return &manager{
+ cgroups: cg,
+ paths: paths,
+ }, nil
}
// isIgnorableError returns whether err is a permission error (in the loose
@@ -171,8 +92,6 @@ func isIgnorableError(rootless bool, err error) bool {
if !rootless {
return false
}
- // TODO: rm errors.Cause once we switch to %w everywhere
- err = errors.Cause(err)
// Is it an ordinary EPERM?
if errors.Is(err, os.ErrPermission) {
return true
@@ -186,56 +105,30 @@ func isIgnorableError(rootless bool, err error) bool {
}
func (m *manager) Apply(pid int) (err error) {
- if m.cgroups == nil {
- return nil
- }
m.mu.Lock()
defer m.mu.Unlock()
c := m.cgroups
- if c.Resources.Unified != nil {
- return cgroups.ErrV1NoUnified
- }
-
- m.paths = make(map[string]string)
- if c.Paths != nil {
- cgMap, err := cgroups.ParseCgroupFile("/proc/self/cgroup")
- if err != nil {
- return err
- }
- for name, path := range c.Paths {
- // XXX(kolyshkin@): why this check is needed?
- if _, ok := cgMap[name]; ok {
- m.paths[name] = path
- }
- }
- return cgroups.EnterPid(m.paths, pid)
- }
-
- d, err := getCgroupData(m.cgroups, pid)
- if err != nil {
- return err
- }
for _, sys := range subsystems {
- p, err := d.path(sys.Name())
- if err != nil {
- // The non-presence of the devices subsystem is
- // considered fatal for security reasons.
- if cgroups.IsNotFound(err) && (c.SkipDevices || sys.Name() != "devices") {
- continue
- }
- return err
+ name := sys.Name()
+ p, ok := m.paths[name]
+ if !ok {
+ continue
}
- m.paths[sys.Name()] = p
- if err := sys.Apply(p, d); err != nil {
+ if err := sys.Apply(p, c.Resources, pid); err != nil {
// In the case of rootless (including euid=0 in userns), where an
// explicit cgroup path hasn't been set, we don't bail on error in
- // case of permission problems. Cases where limits have been set
- // (and we couldn't create our own cgroup) are handled by Set.
- if isIgnorableError(m.rootless, err) && m.cgroups.Path == "" {
- delete(m.paths, sys.Name())
+ // case of permission problems here, but do delete the path from
+ // the m.paths map, since it is either non-existent and could not
+ // be created, or the pid could not be added to it.
+ //
+ // Cases where limits for the subsystem have been set are handled
+ // later by Set, which fails with a friendly error (see
+ // if path == "" in Set).
+ if isIgnorableError(c.Rootless, err) && c.Path == "" {
+ delete(m.paths, name)
continue
}
return err
@@ -246,9 +139,6 @@ func (m *manager) Apply(pid int) (err error) {
}
func (m *manager) Destroy() error {
- if m.cgroups == nil || m.cgroups.Paths != nil {
- return nil
- }
m.mu.Lock()
defer m.mu.Unlock()
return cgroups.RemovePaths(m.paths)
@@ -281,11 +171,6 @@ func (m *manager) Set(r *configs.Resources) error {
return nil
}
- // If Paths are set, then we are just joining cgroups paths
- // and there is no need to set any values.
- if m.cgroups != nil && m.cgroups.Paths != nil {
- return nil
- }
if r.Unified != nil {
return cgroups.ErrV1NoUnified
}
@@ -295,10 +180,11 @@ func (m *manager) Set(r *configs.Resources) error {
for _, sys := range subsystems {
path := m.paths[sys.Name()]
if err := sys.Set(path, r); err != nil {
- if m.rootless && sys.Name() == "devices" {
+ // When rootless is true, errors from the device subsystem
+ // are ignored, as it is really not expected to work.
+ if m.cgroups.Rootless && sys.Name() == "devices" {
continue
}
- // When m.rootless is true, errors from the device subsystem are ignored because it is really not expected to work.
// However, errors from other subsystems are not ignored.
// see @test "runc create (rootless + limits + no cgrouppath + no permission) fails with informative error"
if path == "" {
@@ -317,7 +203,7 @@ func (m *manager) Set(r *configs.Resources) error {
// provided
func (m *manager) Freeze(state configs.FreezerState) error {
path := m.Path("freezer")
- if m.cgroups == nil || path == "" {
+ if path == "" {
return errors.New("cannot toggle freezer: cgroups not configured for container")
}
@@ -339,68 +225,6 @@ func (m *manager) GetAllPids() ([]int, error) {
return cgroups.GetAllPids(m.Path("devices"))
}
-func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {
- root, err := getCgroupRoot()
- if err != nil {
- return nil, err
- }
-
- if (c.Name != "" || c.Parent != "") && c.Path != "" {
- return nil, errors.New("cgroup: either Path or Name and Parent should be used")
- }
-
- // XXX: Do not remove this code. Path safety is important! -- cyphar
- cgPath := libcontainerUtils.CleanPath(c.Path)
- cgParent := libcontainerUtils.CleanPath(c.Parent)
- cgName := libcontainerUtils.CleanPath(c.Name)
-
- innerPath := cgPath
- if innerPath == "" {
- innerPath = filepath.Join(cgParent, cgName)
- }
-
- return &cgroupData{
- root: root,
- innerPath: innerPath,
- config: c,
- pid: pid,
- }, nil
-}
-
-func (raw *cgroupData) path(subsystem string) (string, error) {
- // If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
- if filepath.IsAbs(raw.innerPath) {
- mnt, err := cgroups.FindCgroupMountpoint(raw.root, subsystem)
- // If we didn't mount the subsystem, there is no point we make the path.
- if err != nil {
- return "", err
- }
-
- // Sometimes subsystems can be mounted together as 'cpu,cpuacct'.
- return filepath.Join(raw.root, filepath.Base(mnt), raw.innerPath), nil
- }
-
- // Use GetOwnCgroupPath instead of GetInitCgroupPath, because the creating
- // process could in container and shared pid namespace with host, and
- // /proc/1/cgroup could point to whole other world of cgroups.
- parentPath, err := cgroups.GetOwnCgroupPath(subsystem)
- if err != nil {
- return "", err
- }
-
- return filepath.Join(parentPath, raw.innerPath), nil
-}
-
-func join(path string, pid int) error {
- if path == "" {
- return nil
- }
- if err := os.MkdirAll(path, 0o755); err != nil {
- return err
- }
- return cgroups.WriteCgroupProc(path, pid)
-}
-
func (m *manager) GetPaths() map[string]string {
m.mu.Lock()
defer m.mu.Unlock()
@@ -432,7 +256,7 @@ func OOMKillCount(path string) (uint64, error) {
func (m *manager) OOMKillCount() (uint64, error) {
c, err := OOMKillCount(m.Path("memory"))
// Ignore ENOENT when rootless as it couldn't create cgroup.
- if err != nil && m.rootless && os.IsNotExist(err) {
+ if err != nil && m.cgroups.Rootless && os.IsNotExist(err) {
err = nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go
index 3cafc5399..8ddd6fdd8 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go
@@ -1,9 +1,6 @@
-// +build linux
-
package fs
import (
- "fmt"
"strconv"
"github.com/opencontainers/runc/libcontainer/cgroups"
@@ -17,8 +14,8 @@ func (s *HugetlbGroup) Name() string {
return "hugetlb"
}
-func (s *HugetlbGroup) Apply(path string, d *cgroupData) error {
- return join(path, d.pid)
+func (s *HugetlbGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func (s *HugetlbGroup) Set(path string, r *configs.Resources) error {
@@ -32,29 +29,29 @@ func (s *HugetlbGroup) Set(path string, r *configs.Resources) error {
}
func (s *HugetlbGroup) GetStats(path string, stats *cgroups.Stats) error {
- hugetlbStats := cgroups.HugetlbStats{}
if !cgroups.PathExists(path) {
return nil
}
- for _, pageSize := range HugePageSizes {
+ hugetlbStats := cgroups.HugetlbStats{}
+ for _, pageSize := range cgroups.HugePageSizes() {
usage := "hugetlb." + pageSize + ".usage_in_bytes"
value, err := fscommon.GetCgroupParamUint(path, usage)
if err != nil {
- return fmt.Errorf("failed to parse %s - %v", usage, err)
+ return err
}
hugetlbStats.Usage = value
maxUsage := "hugetlb." + pageSize + ".max_usage_in_bytes"
value, err = fscommon.GetCgroupParamUint(path, maxUsage)
if err != nil {
- return fmt.Errorf("failed to parse %s - %v", maxUsage, err)
+ return err
}
hugetlbStats.MaxUsage = value
failcnt := "hugetlb." + pageSize + ".failcnt"
value, err = fscommon.GetCgroupParamUint(path, failcnt)
if err != nil {
- return fmt.Errorf("failed to parse %s - %v", failcnt, err)
+ return err
}
hugetlbStats.Failcnt = value
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go
index 33946726f..b7c75f941 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go
@@ -1,9 +1,8 @@
-// +build linux
-
package fs
import (
"bufio"
+ "errors"
"fmt"
"math"
"os"
@@ -11,11 +10,11 @@ import (
"strconv"
"strings"
+ "golang.org/x/sys/unix"
+
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
"github.com/opencontainers/runc/libcontainer/configs"
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
const (
@@ -31,8 +30,8 @@ func (s *MemoryGroup) Name() string {
return "memory"
}
-func (s *MemoryGroup) Apply(path string, d *cgroupData) (err error) {
- return join(path, d.pid)
+func (s *MemoryGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func setMemory(path string, val int64) error {
@@ -56,7 +55,7 @@ func setMemory(path string, val int64) error {
return err
}
- return errors.Errorf("unable to set memory limit to %d (current usage: %d, peak usage: %d)", val, usage, max)
+ return fmt.Errorf("unable to set memory limit to %d (current usage: %d, peak usage: %d)", val, usage, max)
}
func setSwap(path string, val int64) error {
@@ -134,15 +133,15 @@ func (s *MemoryGroup) Set(path string, r *configs.Resources) error {
return err
}
} else {
- return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", *r.MemorySwappiness)
+ return fmt.Errorf("invalid memory swappiness value: %d (valid range is 0-100)", *r.MemorySwappiness)
}
return nil
}
func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
- // Set stats from memory.stat.
- statsFile, err := cgroups.OpenFile(path, "memory.stat", os.O_RDONLY)
+ const file = "memory.stat"
+ statsFile, err := cgroups.OpenFile(path, file, os.O_RDONLY)
if err != nil {
if os.IsNotExist(err) {
return nil
@@ -155,7 +154,7 @@ func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
for sc.Scan() {
t, v, err := fscommon.ParseKeyValue(sc.Text())
if err != nil {
- return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err)
+ return &parseError{Path: path, File: file, Err: err}
}
stats.MemoryStats.Stats[t] = v
}
@@ -220,42 +219,42 @@ func getMemoryData(path, name string) (cgroups.MemoryData, error) {
// are optional in the kernel.
return cgroups.MemoryData{}, nil
}
- return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", usage, err)
+ return cgroups.MemoryData{}, err
}
memoryData.Usage = value
value, err = fscommon.GetCgroupParamUint(path, maxUsage)
if err != nil {
- return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", maxUsage, err)
+ return cgroups.MemoryData{}, err
}
memoryData.MaxUsage = value
value, err = fscommon.GetCgroupParamUint(path, failcnt)
if err != nil {
- return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", failcnt, err)
+ return cgroups.MemoryData{}, err
}
memoryData.Failcnt = value
value, err = fscommon.GetCgroupParamUint(path, limit)
if err != nil {
- return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", limit, err)
+ return cgroups.MemoryData{}, err
}
memoryData.Limit = value
return memoryData, nil
}
-func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) {
+func getPageUsageByNUMA(path string) (cgroups.PageUsageByNUMA, error) {
const (
maxColumns = math.MaxUint8 + 1
- filename = "memory.numa_stat"
+ file = "memory.numa_stat"
)
stats := cgroups.PageUsageByNUMA{}
- file, err := cgroups.OpenFile(cgroupPath, filename, os.O_RDONLY)
+ fd, err := cgroups.OpenFile(path, file, os.O_RDONLY)
if os.IsNotExist(err) {
return stats, nil
} else if err != nil {
return stats, err
}
- defer file.Close()
+ defer fd.Close()
// File format is documented in linux/Documentation/cgroup-v1/memory.txt
// and it looks like this:
@@ -266,7 +265,7 @@ func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) {
// unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
// hierarchical_<counter>=<counter pages> N0=<node 0 pages> N1=<node 1 pages> ...
- scanner := bufio.NewScanner(file)
+ scanner := bufio.NewScanner(fd)
for scanner.Scan() {
var field *cgroups.PageStats
@@ -284,8 +283,7 @@ func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) {
} else {
// The first column was already validated,
// so be strict to the rest.
- return stats, fmt.Errorf("malformed line %q in %s",
- line, filename)
+ return stats, malformedLine(path, file, line)
}
}
key, val := byNode[0], byNode[1]
@@ -296,24 +294,23 @@ func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) {
}
field.Total, err = strconv.ParseUint(val, 0, 64)
if err != nil {
- return stats, err
+ return stats, &parseError{Path: path, File: file, Err: err}
}
field.Nodes = map[uint8]uint64{}
} else { // Subsequent columns: key is N<id>, val is usage.
if len(key) < 2 || key[0] != 'N' {
// This is definitely an error.
- return stats, fmt.Errorf("malformed line %q in %s",
- line, filename)
+ return stats, malformedLine(path, file, line)
}
n, err := strconv.ParseUint(key[1:], 10, 8)
if err != nil {
- return cgroups.PageUsageByNUMA{}, err
+ return stats, &parseError{Path: path, File: file, Err: err}
}
usage, err := strconv.ParseUint(val, 10, 64)
if err != nil {
- return cgroups.PageUsageByNUMA{}, err
+ return stats, &parseError{Path: path, File: file, Err: err}
}
field.Nodes[uint8(n)] = usage
@@ -321,9 +318,8 @@ func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) {
}
}
- err = scanner.Err()
- if err != nil {
- return cgroups.PageUsageByNUMA{}, err
+ if err := scanner.Err(); err != nil {
+ return cgroups.PageUsageByNUMA{}, &parseError{Path: path, File: file, Err: err}
}
return stats, nil
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go
index 94a94b5e8..b8d5d849c 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs
import (
@@ -16,10 +14,10 @@ func (s *NameGroup) Name() string {
return s.GroupName
}
-func (s *NameGroup) Apply(path string, d *cgroupData) error {
+func (s *NameGroup) Apply(path string, _ *configs.Resources, pid int) error {
if s.Join {
- // ignore errors if the named cgroup does not exist
- _ = join(path, d.pid)
+ // Ignore errors if the named cgroup does not exist.
+ _ = apply(path, pid)
}
return nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go
index f2617aa44..abfd09ce8 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs
import (
@@ -15,8 +13,8 @@ func (s *NetClsGroup) Name() string {
return "net_cls"
}
-func (s *NetClsGroup) Apply(path string, d *cgroupData) error {
- return join(path, d.pid)
+func (s *NetClsGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func (s *NetClsGroup) Set(path string, r *configs.Resources) error {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go
index d0ac5e66b..da74d3779 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs
import (
@@ -13,8 +11,8 @@ func (s *NetPrioGroup) Name() string {
return "net_prio"
}
-func (s *NetPrioGroup) Apply(path string, d *cgroupData) error {
- return join(path, d.pid)
+func (s *NetPrioGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func (s *NetPrioGroup) Set(path string, r *configs.Resources) error {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/paths.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/paths.go
new file mode 100644
index 000000000..1092331b2
--- /dev/null
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/paths.go
@@ -0,0 +1,186 @@
+package fs
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+ "sync"
+
+ "golang.org/x/sys/unix"
+
+ "github.com/opencontainers/runc/libcontainer/cgroups"
+ "github.com/opencontainers/runc/libcontainer/configs"
+ "github.com/opencontainers/runc/libcontainer/utils"
+)
+
+// The absolute path to the root of the cgroup hierarchies.
+var (
+ cgroupRootLock sync.Mutex
+ cgroupRoot string
+)
+
+const defaultCgroupRoot = "/sys/fs/cgroup"
+
+func initPaths(cg *configs.Cgroup) (map[string]string, error) {
+ root, err := rootPath()
+ if err != nil {
+ return nil, err
+ }
+
+ inner, err := innerPath(cg)
+ if err != nil {
+ return nil, err
+ }
+
+ paths := make(map[string]string)
+ for _, sys := range subsystems {
+ name := sys.Name()
+ path, err := subsysPath(root, inner, name)
+ if err != nil {
+ // The non-presence of the devices subsystem
+ // is considered fatal for security reasons.
+ if cgroups.IsNotFound(err) && (cg.SkipDevices || name != "devices") {
+ continue
+ }
+
+ return nil, err
+ }
+ paths[name] = path
+ }
+
+ return paths, nil
+}
+
+func tryDefaultCgroupRoot() string {
+ var st, pst unix.Stat_t
+
+ // (1) it should be a directory...
+ err := unix.Lstat(defaultCgroupRoot, &st)
+ if err != nil || st.Mode&unix.S_IFDIR == 0 {
+ return ""
+ }
+
+ // (2) ... and a mount point ...
+ err = unix.Lstat(filepath.Dir(defaultCgroupRoot), &pst)
+ if err != nil {
+ return ""
+ }
+
+ if st.Dev == pst.Dev {
+ // parent dir has the same dev -- not a mount point
+ return ""
+ }
+
+ // (3) ... of 'tmpfs' fs type.
+ var fst unix.Statfs_t
+ err = unix.Statfs(defaultCgroupRoot, &fst)
+ if err != nil || fst.Type != unix.TMPFS_MAGIC {
+ return ""
+ }
+
+ // (4) it should have at least 1 entry ...
+ dir, err := os.Open(defaultCgroupRoot)
+ if err != nil {
+ return ""
+ }
+ names, err := dir.Readdirnames(1)
+ if err != nil {
+ return ""
+ }
+ if len(names) < 1 {
+ return ""
+ }
+ // ... which is a cgroup mount point.
+ err = unix.Statfs(filepath.Join(defaultCgroupRoot, names[0]), &fst)
+ if err != nil || fst.Type != unix.CGROUP_SUPER_MAGIC {
+ return ""
+ }
+
+ return defaultCgroupRoot
+}
+
+// rootPath finds and returns path to the root of the cgroup hierarchies.
+func rootPath() (string, error) {
+ cgroupRootLock.Lock()
+ defer cgroupRootLock.Unlock()
+
+ if cgroupRoot != "" {
+ return cgroupRoot, nil
+ }
+
+ // fast path
+ cgroupRoot = tryDefaultCgroupRoot()
+ if cgroupRoot != "" {
+ return cgroupRoot, nil
+ }
+
+ // slow path: parse mountinfo
+ mi, err := cgroups.GetCgroupMounts(false)
+ if err != nil {
+ return "", err
+ }
+ if len(mi) < 1 {
+ return "", errors.New("no cgroup mount found in mountinfo")
+ }
+
+ // Get the first cgroup mount (e.g. "/sys/fs/cgroup/memory"),
+ // use its parent directory.
+ root := filepath.Dir(mi[0].Mountpoint)
+
+ if _, err := os.Stat(root); err != nil {
+ return "", err
+ }
+
+ cgroupRoot = root
+ return cgroupRoot, nil
+}
+
+func innerPath(c *configs.Cgroup) (string, error) {
+ if (c.Name != "" || c.Parent != "") && c.Path != "" {
+ return "", errors.New("cgroup: either Path or Name and Parent should be used")
+ }
+
+ // XXX: Do not remove CleanPath. Path safety is important! -- cyphar
+ innerPath := utils.CleanPath(c.Path)
+ if innerPath == "" {
+ cgParent := utils.CleanPath(c.Parent)
+ cgName := utils.CleanPath(c.Name)
+ innerPath = filepath.Join(cgParent, cgName)
+ }
+
+ return innerPath, nil
+}
+
+func subsysPath(root, inner, subsystem string) (string, error) {
+ // If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
+ if filepath.IsAbs(inner) {
+ mnt, err := cgroups.FindCgroupMountpoint(root, subsystem)
+ // If we didn't mount the subsystem, there is no point we make the path.
+ if err != nil {
+ return "", err
+ }
+
+ // Sometimes subsystems can be mounted together as 'cpu,cpuacct'.
+ return filepath.Join(root, filepath.Base(mnt), inner), nil
+ }
+
+ // Use GetOwnCgroupPath instead of GetInitCgroupPath, because the creating
+ // process could in container and shared pid namespace with host, and
+ // /proc/1/cgroup could point to whole other world of cgroups.
+ parentPath, err := cgroups.GetOwnCgroupPath(subsystem)
+ if err != nil {
+ return "", err
+ }
+
+ return filepath.Join(parentPath, inner), nil
+}
+
+func apply(path string, pid int) error {
+ if path == "" {
+ return nil
+ }
+ if err := os.MkdirAll(path, 0o755); err != nil {
+ return err
+ }
+ return cgroups.WriteCgroupProc(path, pid)
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go
index 1a306fbe3..b86955c8f 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs
import (
@@ -13,8 +11,8 @@ func (s *PerfEventGroup) Name() string {
return "perf_event"
}
-func (s *PerfEventGroup) Apply(path string, d *cgroupData) error {
- return join(path, d.pid)
+func (s *PerfEventGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func (s *PerfEventGroup) Set(_ string, _ *configs.Resources) error {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids.go
index 1b08433c4..1f13532a5 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids.go
@@ -1,10 +1,7 @@
-// +build linux
-
package fs
import (
- "fmt"
- "path/filepath"
+ "math"
"strconv"
"github.com/opencontainers/runc/libcontainer/cgroups"
@@ -18,8 +15,8 @@ func (s *PidsGroup) Name() string {
return "pids"
}
-func (s *PidsGroup) Apply(path string, d *cgroupData) error {
- return join(path, d.pid)
+func (s *PidsGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
}
func (s *PidsGroup) Set(path string, r *configs.Resources) error {
@@ -45,21 +42,18 @@ func (s *PidsGroup) GetStats(path string, stats *cgroups.Stats) error {
}
current, err := fscommon.GetCgroupParamUint(path, "pids.current")
if err != nil {
- return fmt.Errorf("failed to parse pids.current - %s", err)
+ return err
}
- maxString, err := fscommon.GetCgroupParamString(path, "pids.max")
+ max, err := fscommon.GetCgroupParamUint(path, "pids.max")
if err != nil {
- return fmt.Errorf("failed to parse pids.max - %s", err)
+ return err
}
-
- // Default if pids.max == "max" is 0 -- which represents "no limit".
- var max uint64
- if maxString != "max" {
- max, err = fscommon.ParseUint(maxString, 10, 64)
- if err != nil {
- return fmt.Errorf("failed to parse pids.max - unable to parse %q as a uint from Cgroup file %q", maxString, filepath.Join(path, "pids.max"))
- }
+ // If no limit is set, read from pids.max returns "max", which is
+ // converted to MaxUint64 by GetCgroupParamUint. Historically, we
+ // represent "no limit" for pids as 0, thus this conversion.
+ if max == math.MaxUint64 {
+ max = 0
}
stats.PidsStats.Current = current
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/rdma.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/rdma.go
new file mode 100644
index 000000000..5bbe0f35f
--- /dev/null
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/rdma.go
@@ -0,0 +1,25 @@
+package fs
+
+import (
+ "github.com/opencontainers/runc/libcontainer/cgroups"
+ "github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
+ "github.com/opencontainers/runc/libcontainer/configs"
+)
+
+type RdmaGroup struct{}
+
+func (s *RdmaGroup) Name() string {
+ return "rdma"
+}
+
+func (s *RdmaGroup) Apply(path string, _ *configs.Resources, pid int) error {
+ return apply(path, pid)
+}
+
+func (s *RdmaGroup) Set(path string, r *configs.Resources) error {
+ return fscommon.RdmaSet(path, r)
+}
+
+func (s *RdmaGroup) GetStats(path string, stats *cgroups.Stats) error {
+ return fscommon.RdmaGetStats(path, stats)
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/unsupported.go
deleted file mode 100644
index 3ef9e0315..000000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/unsupported.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// +build !linux
-
-package fs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/BUILD.bazel b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/BUILD.bazel
index 8034a53d0..f800d9340 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/BUILD.bazel
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/BUILD.bazel
@@ -20,28 +20,14 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/utils:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
- ] + select({
- "@io_bazel_rules_go//go/platform:android": [
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
- "//vendor/github.com/sirupsen/logrus:go_default_library",
- "//vendor/golang.org/x/sys/unix:go_default_library",
- ],
- "@io_bazel_rules_go//go/platform:linux": [
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
- "//vendor/github.com/opencontainers/runc/libcontainer/userns:go_default_library",
- "//vendor/github.com/sirupsen/logrus:go_default_library",
- "//vendor/golang.org/x/sys/unix:go_default_library",
- ],
- "//conditions:default": [],
- }),
+ "//vendor/github.com/sirupsen/logrus:go_default_library",
+ "//vendor/golang.org/x/sys/unix:go_default_library",
+ ],
)
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpu.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpu.go
index 25c47c961..bbbae4d58 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpu.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpu.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs2
import (
@@ -49,7 +47,8 @@ func setCpu(dirPath string, r *configs.Resources) error {
}
func statCpu(dirPath string, stats *cgroups.Stats) error {
- f, err := cgroups.OpenFile(dirPath, "cpu.stat", os.O_RDONLY)
+ const file = "cpu.stat"
+ f, err := cgroups.OpenFile(dirPath, file, os.O_RDONLY)
if err != nil {
return err
}
@@ -59,7 +58,7 @@ func statCpu(dirPath string, stats *cgroups.Stats) error {
for sc.Scan() {
t, v, err := fscommon.ParseKeyValue(sc.Text())
if err != nil {
- return err
+ return &parseError{Path: dirPath, File: file, Err: err}
}
switch t {
case "usage_usec":
@@ -81,5 +80,8 @@ func statCpu(dirPath string, stats *cgroups.Stats) error {
stats.CpuStats.ThrottlingData.ThrottledTime = v * 1000
}
}
+ if err := sc.Err(); err != nil {
+ return &parseError{Path: dirPath, File: file, Err: err}
+ }
return nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpuset.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpuset.go
index da29d7f2b..16c45bad8 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpuset.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpuset.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs2
import (
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/defaultpath.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/defaultpath.go
index ba81ce0b4..9c949c91f 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/defaultpath.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/defaultpath.go
@@ -18,41 +18,37 @@ package fs2
import (
"bufio"
+ "errors"
+ "fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/opencontainers/runc/libcontainer/configs"
- libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
- "github.com/pkg/errors"
+ "github.com/opencontainers/runc/libcontainer/utils"
)
const UnifiedMountpoint = "/sys/fs/cgroup"
func defaultDirPath(c *configs.Cgroup) (string, error) {
if (c.Name != "" || c.Parent != "") && c.Path != "" {
- return "", errors.Errorf("cgroup: either Path or Name and Parent should be used, got %+v", c)
+ return "", fmt.Errorf("cgroup: either Path or Name and Parent should be used, got %+v", c)
}
- if len(c.Paths) != 0 {
- // never set by specconv
- return "", errors.Errorf("cgroup: Paths is unsupported, use Path, got %+v", c)
- }
-
- // XXX: Do not remove this code. Path safety is important! -- cyphar
- cgPath := libcontainerUtils.CleanPath(c.Path)
- cgParent := libcontainerUtils.CleanPath(c.Parent)
- cgName := libcontainerUtils.CleanPath(c.Name)
- return _defaultDirPath(UnifiedMountpoint, cgPath, cgParent, cgName)
+ return _defaultDirPath(UnifiedMountpoint, c.Path, c.Parent, c.Name)
}
func _defaultDirPath(root, cgPath, cgParent, cgName string) (string, error) {
if (cgName != "" || cgParent != "") && cgPath != "" {
return "", errors.New("cgroup: either Path or Name and Parent should be used")
}
- innerPath := cgPath
+
+ // XXX: Do not remove CleanPath. Path safety is important! -- cyphar
+ innerPath := utils.CleanPath(cgPath)
if innerPath == "" {
+ cgParent := utils.CleanPath(cgParent)
+ cgName := utils.CleanPath(cgName)
innerPath = filepath.Join(cgParent, cgName)
}
if filepath.IsAbs(innerPath) {
@@ -89,7 +85,7 @@ func parseCgroupFromReader(r io.Reader) (string, error) {
parts = strings.SplitN(text, ":", 3)
)
if len(parts) < 3 {
- return "", errors.Errorf("invalid cgroup entry: %q", text)
+ return "", fmt.Errorf("invalid cgroup entry: %q", text)
}
// text is like "0::/user.slice/user-1001.slice/session-1.scope"
if parts[0] == "0" && parts[1] == "" {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go
index 7c501cad8..0d2345607 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go
@@ -1,16 +1,15 @@
-// +build linux
-
package fs2
import (
+ "fmt"
+
+ "golang.org/x/sys/unix"
+
"github.com/opencontainers/runc/libcontainer/cgroups/ebpf"
"github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/devices"
"github.com/opencontainers/runc/libcontainer/userns"
-
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
func isRWM(perms devices.Permissions) bool {
@@ -64,7 +63,7 @@ func setDevices(dirPath string, r *configs.Resources) error {
}
dirFD, err := unix.Open(dirPath, unix.O_DIRECTORY|unix.O_RDONLY, 0o600)
if err != nil {
- return errors.Errorf("cannot get dir FD for %s", dirPath)
+ return fmt.Errorf("cannot get dir FD for %s", dirPath)
}
defer unix.Close(dirFD)
if _, err := ebpf.LoadAttachCgroupDeviceFilter(insts, license, dirFD); err != nil {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/freezer.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/freezer.go
index e901f7a07..8917a6411 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/freezer.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/freezer.go
@@ -1,19 +1,17 @@
-// +build linux
-
package fs2
import (
"bufio"
- stdErrors "errors"
+ "errors"
"fmt"
"os"
"strings"
"time"
+ "golang.org/x/sys/unix"
+
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
func setFreezer(dirPath string, state configs.FreezerState) error {
@@ -26,7 +24,7 @@ func setFreezer(dirPath string, state configs.FreezerState) error {
case configs.Thawed:
stateStr = "0"
default:
- return errors.Errorf("invalid freezer state %q requested", state)
+ return fmt.Errorf("invalid freezer state %q requested", state)
}
fd, err := cgroups.OpenFile(dirPath, "cgroup.freeze", unix.O_RDWR)
@@ -37,7 +35,7 @@ func setFreezer(dirPath string, state configs.FreezerState) error {
if state != configs.Frozen {
return nil
}
- return errors.Wrap(err, "freezer not supported")
+ return fmt.Errorf("freezer not supported: %w", err)
}
defer fd.Close()
@@ -48,7 +46,7 @@ func setFreezer(dirPath string, state configs.FreezerState) error {
if actualState, err := readFreezer(dirPath, fd); err != nil {
return err
} else if actualState != state {
- return errors.Errorf(`expected "cgroup.freeze" to be in state %q but was in %q`, state, actualState)
+ return fmt.Errorf(`expected "cgroup.freeze" to be in state %q but was in %q`, state, actualState)
}
return nil
}
@@ -58,7 +56,7 @@ func getFreezer(dirPath string) (configs.FreezerState, error) {
if err != nil {
// If the kernel is too old, then we just treat the freezer as being in
// an "undefined" state.
- if os.IsNotExist(err) || stdErrors.Is(err, unix.ENODEV) {
+ if os.IsNotExist(err) || errors.Is(err, unix.ENODEV) {
err = nil
}
return configs.Undefined, err
@@ -82,7 +80,7 @@ func readFreezer(dirPath string, fd *os.File) (configs.FreezerState, error) {
case "1\n":
return waitFrozen(dirPath)
default:
- return configs.Undefined, errors.Errorf(`unknown "cgroup.freeze" state: %q`, state)
+ return configs.Undefined, fmt.Errorf(`unknown "cgroup.freeze" state: %q`, state)
}
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/fs2.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/fs2.go
index afba0ab1c..492778e31 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/fs2.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/fs2.go
@@ -1,8 +1,7 @@
-// +build linux
-
package fs2
import (
+ "errors"
"fmt"
"os"
"strings"
@@ -10,9 +9,10 @@ import (
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
"github.com/opencontainers/runc/libcontainer/configs"
- "github.com/pkg/errors"
)
+type parseError = fscommon.ParseError
+
type manager struct {
config *configs.Cgroup
// dirPath is like "/sys/fs/cgroup/user.slice/user-1001.slice/session-1.scope"
@@ -20,16 +20,12 @@ type manager struct {
// controllers is content of "cgroup.controllers" file.
// excludes pseudo-controllers ("devices" and "freezer").
controllers map[string]struct{}
- rootless bool
}
// NewManager creates a manager for cgroup v2 unified hierarchy.
// dirPath is like "/sys/fs/cgroup/user.slice/user-1001.slice/session-1.scope".
// If dirPath is empty, it is automatically set using config.
-func NewManager(config *configs.Cgroup, dirPath string, rootless bool) (cgroups.Manager, error) {
- if config == nil {
- config = &configs.Cgroup{}
- }
+func NewManager(config *configs.Cgroup, dirPath string) (cgroups.Manager, error) {
if dirPath == "" {
var err error
dirPath, err = defaultDirPath(config)
@@ -39,9 +35,8 @@ func NewManager(config *configs.Cgroup, dirPath string, rootless bool) (cgroups.
}
m := &manager{
- config: config,
- dirPath: dirPath,
- rootless: rootless,
+ config: config,
+ dirPath: dirPath,
}
return m, nil
}
@@ -53,7 +48,7 @@ func (m *manager) getControllers() error {
data, err := cgroups.ReadFile(m.dirPath, "cgroup.controllers")
if err != nil {
- if m.rootless && m.config.Path == "" {
+ if m.config.Rootless && m.config.Path == "" {
return nil
}
return err
@@ -73,12 +68,12 @@ func (m *manager) Apply(pid int) error {
// - "runc create (no limits + no cgrouppath + no permission) succeeds"
// - "runc create (rootless + no limits + cgrouppath + no permission) fails with permission error"
// - "runc create (rootless + limits + no cgrouppath + no permission) fails with informative error"
- if m.rootless {
+ if m.config.Rootless {
if m.config.Path == "" {
if blNeed, nErr := needAnyControllers(m.config.Resources); nErr == nil && !blNeed {
return nil
}
- return errors.Wrap(err, "rootless needs no limits + no cgrouppath when no permission is granted for cgroups")
+ return fmt.Errorf("rootless needs no limits + no cgrouppath when no permission is granted for cgroups: %w", err)
}
}
return err
@@ -123,13 +118,20 @@ func (m *manager) GetStats() (*cgroups.Stats, error) {
if err := statHugeTlb(m.dirPath, st); err != nil && !os.IsNotExist(err) {
errs = append(errs, err)
}
- if len(errs) > 0 && !m.rootless {
- return st, errors.Errorf("error while statting cgroup v2: %+v", errs)
+ // rdma (since kernel 4.11)
+ if err := fscommon.RdmaGetStats(m.dirPath, st); err != nil && !os.IsNotExist(err) {
+ errs = append(errs, err)
+ }
+ if len(errs) > 0 && !m.config.Rootless {
+ return st, fmt.Errorf("error while statting cgroup v2: %+v", errs)
}
return st, nil
}
func (m *manager) Freeze(state configs.FreezerState) error {
+ if m.config.Resources == nil {
+ return errors.New("cannot toggle freezer: cgroups not configured for container")
+ }
if err := setFreezer(m.dirPath, state); err != nil {
return err
}
@@ -146,6 +148,9 @@ func (m *manager) Path(_ string) string {
}
func (m *manager) Set(r *configs.Resources) error {
+ if r == nil {
+ return nil
+ }
if err := m.getControllers(); err != nil {
return err
}
@@ -167,10 +172,10 @@ func (m *manager) Set(r *configs.Resources) error {
}
// devices (since kernel 4.15, pseudo-controller)
//
- // When m.rootless is true, errors from the device subsystem are ignored because it is really not expected to work.
+ // When rootless is true, errors from the device subsystem are ignored because it is really not expected to work.
// However, errors from other subsystems are not ignored.
// see @test "runc create (rootless + limits + no cgrouppath + no permission) fails with informative error"
- if err := setDevices(m.dirPath, r); err != nil && !m.rootless {
+ if err := setDevices(m.dirPath, r); err != nil && !m.config.Rootless {
return err
}
// cpuset (since kernel 5.0)
@@ -181,6 +186,10 @@ func (m *manager) Set(r *configs.Resources) error {
if err := setHugeTlb(m.dirPath, r); err != nil {
return err
}
+ // rdma (since kernel 4.11)
+ if err := fscommon.RdmaSet(m.dirPath, r); err != nil {
+ return err
+ }
// freezer (since kernel 5.2, pseudo-controller)
if err := setFreezer(m.dirPath, r.Freezer); err != nil {
return err
@@ -198,9 +207,8 @@ func (m *manager) setUnified(res map[string]string) error {
return fmt.Errorf("unified resource %q must be a file name (no slashes)", k)
}
if err := cgroups.WriteFile(m.dirPath, k, v); err != nil {
- errC := errors.Cause(err)
// Check for both EPERM and ENOENT since O_CREAT is used by WriteFile.
- if errors.Is(errC, os.ErrPermission) || errors.Is(errC, os.ErrNotExist) {
+ if errors.Is(err, os.ErrPermission) || errors.Is(err, os.ErrNotExist) {
// Check if a controller is available,
// to give more specific error if not.
sk := strings.SplitN(k, ".", 2)
@@ -212,7 +220,7 @@ func (m *manager) setUnified(res map[string]string) error {
return fmt.Errorf("unified resource %q can't be set: controller %q not available", k, c)
}
}
- return errors.Wrapf(err, "can't set unified resource %q", k)
+ return fmt.Errorf("unable to set unified resource %q: %w", k, err)
}
}
@@ -243,7 +251,7 @@ func OOMKillCount(path string) (uint64, error) {
func (m *manager) OOMKillCount() (uint64, error) {
c, err := OOMKillCount(m.dirPath)
- if err != nil && m.rootless && os.IsNotExist(err) {
+ if err != nil && m.config.Rootless && os.IsNotExist(err) {
err = nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/hugetlb.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/hugetlb.go
index 96390a224..c92a7e64a 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/hugetlb.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/hugetlb.go
@@ -1,12 +1,8 @@
-// +build linux
-
package fs2
import (
"strconv"
- "github.com/pkg/errors"
-
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
"github.com/opencontainers/runc/libcontainer/configs"
@@ -30,10 +26,8 @@ func setHugeTlb(dirPath string, r *configs.Resources) error {
}
func statHugeTlb(dirPath string, stats *cgroups.Stats) error {
- hugePageSizes, _ := cgroups.GetHugePageSize()
hugetlbStats := cgroups.HugetlbStats{}
-
- for _, pagesize := range hugePageSizes {
+ for _, pagesize := range cgroups.HugePageSizes() {
value, err := fscommon.GetCgroupParamUint(dirPath, "hugetlb."+pagesize+".current")
if err != nil {
return err
@@ -43,7 +37,7 @@ func statHugeTlb(dirPath string, stats *cgroups.Stats) error {
fileName := "hugetlb." + pagesize + ".events"
value, err = fscommon.GetValueByKey(dirPath, fileName, "max")
if err != nil {
- return errors.Wrap(err, "failed to read stats")
+ return err
}
hugetlbStats.Failcnt = value
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/io.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/io.go
index fd3f0993e..b2ff7d340 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/io.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/io.go
@@ -1,5 +1,3 @@
-// +build linux
-
package fs2
import (
@@ -117,13 +115,14 @@ func readCgroup2MapFile(dirPath string, name string) (map[string][]string, error
ret[parts[0]] = parts[1:]
}
if err := scanner.Err(); err != nil {
- return nil, err
+ return nil, &parseError{Path: dirPath, File: name, Err: err}
}
return ret, nil
}
func statIo(dirPath string, stats *cgroups.Stats) error {
- values, err := readCgroup2MapFile(dirPath, "io.stat")
+ const file = "io.stat"
+ values, err := readCgroup2MapFile(dirPath, file)
if err != nil {
return err
}
@@ -136,11 +135,11 @@ func statIo(dirPath string, stats *cgroups.Stats) error {
}
major, err := strconv.ParseUint(d[0], 10, 64)
if err != nil {
- return err
+ return &parseError{Path: dirPath, File: file, Err: err}
}
minor, err := strconv.ParseUint(d[1], 10, 64)
if err != nil {
- return err
+ return &parseError{Path: dirPath, File: file, Err: err}
}
for _, item := range v {
@@ -177,7 +176,7 @@ func statIo(dirPath string, stats *cgroups.Stats) error {
value, err := strconv.ParseUint(d[1], 10, 64)
if err != nil {
- return err
+ return &parseError{Path: dirPath, File: file, Err: err}
}
entry := cgroups.BlkioStatEntry{
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/memory.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/memory.go
index 53e8f1e93..adbc4b230 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/memory.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/memory.go
@@ -1,19 +1,18 @@
-// +build linux
-
package fs2
import (
"bufio"
+ "errors"
"math"
"os"
"strconv"
"strings"
+ "golang.org/x/sys/unix"
+
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
"github.com/opencontainers/runc/libcontainer/configs"
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
// numToStr converts an int64 value to a string for writing to a
@@ -75,8 +74,8 @@ func setMemory(dirPath string, r *configs.Resources) error {
}
func statMemory(dirPath string, stats *cgroups.Stats) error {
- // Set stats from memory.stat.
- statsFile, err := cgroups.OpenFile(dirPath, "memory.stat", os.O_RDONLY)
+ const file = "memory.stat"
+ statsFile, err := cgroups.OpenFile(dirPath, file, os.O_RDONLY)
if err != nil {
return err
}
@@ -86,10 +85,13 @@ func statMemory(dirPath string, stats *cgroups.Stats) error {
for sc.Scan() {
t, v, err := fscommon.ParseKeyValue(sc.Text())
if err != nil {
- return errors.Wrapf(err, "failed to parse memory.stat (%q)", sc.Text())
+ return &parseError{Path: dirPath, File: file, Err: err}
}
stats.MemoryStats.Stats[t] = v
}
+ if err := sc.Err(); err != nil {
+ return &parseError{Path: dirPath, File: file, Err: err}
+ }
stats.MemoryStats.Cache = stats.MemoryStats.Stats["file"]
// Unlike cgroup v1 which has memory.use_hierarchy binary knob,
// cgroup v2 is always hierarchical.
@@ -139,13 +141,13 @@ func getMemoryDataV2(path, name string) (cgroups.MemoryData, error) {
// swapaccount=0 kernel boot parameter is given.
return cgroups.MemoryData{}, nil
}
- return cgroups.MemoryData{}, errors.Wrapf(err, "failed to parse %s", usage)
+ return cgroups.MemoryData{}, err
}
memoryData.Usage = value
value, err = fscommon.GetCgroupParamUint(path, limit)
if err != nil {
- return cgroups.MemoryData{}, errors.Wrapf(err, "failed to parse %s", limit)
+ return cgroups.MemoryData{}, err
}
memoryData.Limit = value
@@ -153,7 +155,8 @@ func getMemoryDataV2(path, name string) (cgroups.MemoryData, error) {
}
func statsFromMeminfo(stats *cgroups.Stats) error {
- f, err := os.Open("/proc/meminfo")
+ const file = "/proc/meminfo"
+ f, err := os.Open(file)
if err != nil {
return err
}
@@ -190,7 +193,7 @@ func statsFromMeminfo(stats *cgroups.Stats) error {
vStr := strings.TrimSpace(strings.TrimSuffix(parts[1], " kB"))
*p, err = strconv.ParseUint(vStr, 10, 64)
if err != nil {
- return errors.Wrap(err, "parsing /proc/meminfo "+k)
+ return &parseError{File: file, Err: errors.New("bad value for " + k)}
}
found++
@@ -199,8 +202,8 @@ func statsFromMeminfo(stats *cgroups.Stats) error {
break
}
}
- if sc.Err() != nil {
- return sc.Err()
+ if err := sc.Err(); err != nil {
+ return &parseError{Path: "", File: file, Err: err}
}
stats.MemoryStats.SwapUsage.Usage = (swap_total - swap_free) * 1024
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/pids.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/pids.go
index e2050002d..c8c4a3658 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/pids.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/pids.go
@@ -1,17 +1,16 @@
-// +build linux
-
package fs2
import (
+ "errors"
+ "math"
"os"
- "path/filepath"
"strings"
+ "golang.org/x/sys/unix"
+
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
"github.com/opencontainers/runc/libcontainer/configs"
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
func isPidsSet(r *configs.Resources) bool {
@@ -53,22 +52,18 @@ func statPids(dirPath string, stats *cgroups.Stats) error {
if os.IsNotExist(err) {
return statPidsFromCgroupProcs(dirPath, stats)
}
- return errors.Wrap(err, "failed to parse pids.current")
+ return err
}
- maxString, err := fscommon.GetCgroupParamString(dirPath, "pids.max")
+ max, err := fscommon.GetCgroupParamUint(dirPath, "pids.max")
if err != nil {
- return errors.Wrap(err, "failed to parse pids.max")
+ return err
}
-
- // Default if pids.max == "max" is 0 -- which represents "no limit".
- var max uint64
- if maxString != "max" {
- max, err = fscommon.ParseUint(maxString, 10, 64)
- if err != nil {
- return errors.Wrapf(err, "failed to parse pids.max - unable to parse %q as a uint from Cgroup file %q",
- maxString, filepath.Join(dirPath, "pids.max"))
- }
+ // If no limit is set, read from pids.max returns "max", which is
+ // converted to MaxUint64 by GetCgroupParamUint. Historically, we
+ // represent "no limit" for pids as 0, thus this conversion.
+ if max == math.MaxUint64 {
+ max = 0
}
stats.PidsStats.Current = current
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/BUILD.bazel b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/BUILD.bazel
index 185eda6db..d3c587757 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/BUILD.bazel
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/BUILD.bazel
@@ -2,17 +2,16 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
- srcs = ["utils.go"],
+ srcs = [
+ "rdma.go",
+ "utils.go",
+ ],
importmap = "kubevirt.io/kubevirt/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon",
importpath = "github.com/opencontainers/runc/libcontainer/cgroups/fscommon",
visibility = ["//visibility:public"],
- deps = select({
- "@io_bazel_rules_go//go/platform:android": [
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
- ],
- "@io_bazel_rules_go//go/platform:linux": [
- "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
- ],
- "//conditions:default": [],
- }),
+ deps = [
+ "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
+ "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
+ "//vendor/golang.org/x/sys/unix:go_default_library",
+ ],
)
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/rdma.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/rdma.go
new file mode 100644
index 000000000..d463d15ee
--- /dev/null
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/rdma.go
@@ -0,0 +1,121 @@
+package fscommon
+
+import (
+ "bufio"
+ "errors"
+ "math"
+ "os"
+ "strconv"
+ "strings"
+
+ "github.com/opencontainers/runc/libcontainer/cgroups"
+ "github.com/opencontainers/runc/libcontainer/configs"
+ "golang.org/x/sys/unix"
+)
+
+// parseRdmaKV parses raw string to RdmaEntry.
+func parseRdmaKV(raw string, entry *cgroups.RdmaEntry) error {
+ var value uint32
+
+ parts := strings.SplitN(raw, "=", 3)
+
+ if len(parts) != 2 {
+ return errors.New("Unable to parse RDMA entry")
+ }
+
+ k, v := parts[0], parts[1]
+
+ if v == "max" {
+ value = math.MaxUint32
+ } else {
+ val64, err := strconv.ParseUint(v, 10, 32)
+ if err != nil {
+ return err
+ }
+ value = uint32(val64)
+ }
+ if k == "hca_handle" {
+ entry.HcaHandles = value
+ } else if k == "hca_object" {
+ entry.HcaObjects = value
+ }
+
+ return nil
+}
+
+// readRdmaEntries reads and converts array of rawstrings to RdmaEntries from file.
+// example entry: mlx4_0 hca_handle=2 hca_object=2000
+func readRdmaEntries(dir, file string) ([]cgroups.RdmaEntry, error) {
+ rdmaEntries := make([]cgroups.RdmaEntry, 0)
+ fd, err := cgroups.OpenFile(dir, file, unix.O_RDONLY)
+ if err != nil {
+ return nil, err
+ }
+ defer fd.Close() //nolint:errorlint
+ scanner := bufio.NewScanner(fd)
+ for scanner.Scan() {
+ parts := strings.SplitN(scanner.Text(), " ", 4)
+ if len(parts) == 3 {
+ entry := new(cgroups.RdmaEntry)
+ entry.Device = parts[0]
+ err = parseRdmaKV(parts[1], entry)
+ if err != nil {
+ continue
+ }
+ err = parseRdmaKV(parts[2], entry)
+ if err != nil {
+ continue
+ }
+
+ rdmaEntries = append(rdmaEntries, *entry)
+ }
+ }
+ return rdmaEntries, scanner.Err()
+}
+
+// RdmaGetStats returns rdma stats such as totalLimit and current entries.
+func RdmaGetStats(path string, stats *cgroups.Stats) error {
+ currentEntries, err := readRdmaEntries(path, "rdma.current")
+ if err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ err = nil
+ }
+ return err
+ }
+ maxEntries, err := readRdmaEntries(path, "rdma.max")
+ if err != nil {
+ return err
+ }
+ // If device got removed between reading two files, ignore returning stats.
+ if len(currentEntries) != len(maxEntries) {
+ return nil
+ }
+
+ stats.RdmaStats = cgroups.RdmaStats{
+ RdmaLimit: maxEntries,
+ RdmaCurrent: currentEntries,
+ }
+
+ return nil
+}
+
+func createCmdString(device string, limits configs.LinuxRdma) string {
+ cmdString := device
+ if limits.HcaHandles != nil {
+ cmdString += " hca_handle=" + strconv.FormatUint(uint64(*limits.HcaHandles), 10)
+ }
+ if limits.HcaObjects != nil {
+ cmdString += " hca_object=" + strconv.FormatUint(uint64(*limits.HcaObjects), 10)
+ }
+ return cmdString
+}
+
+// RdmaSet sets RDMA resources.
+func RdmaSet(path string, r *configs.Resources) error {
+ for device, limits := range r.Rdma {
+ if err := cgroups.WriteFile(path, "rdma.max", createCmdString(device, limits)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go
index e31146ae9..f4a51c9e5 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go
@@ -1,11 +1,10 @@
-// +build linux
-
package fscommon
import (
"errors"
"fmt"
"math"
+ "path"
"strconv"
"strings"
@@ -13,8 +12,6 @@ import (
)
var (
- ErrNotValidFormat = errors.New("line is not a valid key value format")
-
// Deprecated: use cgroups.OpenFile instead.
OpenFile = cgroups.OpenFile
// Deprecated: use cgroups.ReadFile instead.
@@ -23,6 +20,19 @@ var (
WriteFile = cgroups.WriteFile
)
+// ParseError records a parse error details, including the file path.
+type ParseError struct {
+ Path string
+ File string
+ Err error
+}
+
+func (e *ParseError) Error() string {
+ return "unable to parse " + path.Join(e.Path, e.File) + ": " + e.Err.Error()
+}
+
+func (e *ParseError) Unwrap() error { return e.Err }
+
// ParseUint converts a string to an uint64 integer.
// Negative values are returned at zero as, due to kernel bugs,
// some of the memory cgroup stats can be negative.
@@ -34,7 +44,7 @@ func ParseUint(s string, base, bitSize int) (uint64, error) {
// 2. Handle negative values lesser than MinInt64
if intErr == nil && intValue < 0 {
return 0, nil
- } else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 {
+ } else if errors.Is(intErr, strconv.ErrRange) && intValue < 0 {
return 0, nil
}
@@ -56,7 +66,7 @@ func ParseKeyValue(t string) (string, uint64, error) {
value, err := ParseUint(parts[1], 10, 64)
if err != nil {
- return "", 0, fmt.Errorf("unable to convert to uint64: %v", err)
+ return "", 0, err
}
return parts[0], value, nil
@@ -71,11 +81,15 @@ func GetValueByKey(path, file, key string) (uint64, error) {
return 0, err
}
- lines := strings.Split(string(content), "\n")
+ lines := strings.Split(content, "\n")
for _, line := range lines {
arr := strings.Split(line, " ")
if len(arr) == 2 && arr[0] == key {
- return ParseUint(arr[1], 10, 64)
+ val, err := ParseUint(arr[1], 10, 64)
+ if err != nil {
+ err = &ParseError{Path: path, File: file, Err: err}
+ }
+ return val, err
}
}
@@ -96,7 +110,7 @@ func GetCgroupParamUint(path, file string) (uint64, error) {
res, err := ParseUint(contents, 10, 64)
if err != nil {
- return res, fmt.Errorf("unable to parse file %q", path+"/"+file)
+ return res, &ParseError{Path: path, File: file, Err: err}
}
return res, nil
}
@@ -115,7 +129,7 @@ func GetCgroupParamInt(path, file string) (int64, error) {
res, err := strconv.ParseInt(contents, 10, 64)
if err != nil {
- return res, fmt.Errorf("unable to parse %q as a int from Cgroup file %q", contents, path+"/"+file)
+ return res, &ParseError{Path: path, File: file, Err: err}
}
return res, nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go
new file mode 100644
index 000000000..1355a5101
--- /dev/null
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go
@@ -0,0 +1,27 @@
+package cgroups
+
+import (
+ "io/fs"
+ "path/filepath"
+)
+
+// GetAllPids returns all pids from the cgroup identified by path, and all its
+// sub-cgroups.
+func GetAllPids(path string) ([]int, error) {
+ var pids []int
+ err := filepath.WalkDir(path, func(p string, d fs.DirEntry, iErr error) error {
+ if iErr != nil {
+ return iErr
+ }
+ if !d.IsDir() {
+ return nil
+ }
+ cPids, err := readProcsFile(p)
+ if err != nil {
+ return err
+ }
+ pids = append(pids, cPids...)
+ return nil
+ })
+ return pids, err
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
index e7f9c4626..40a81dd5a 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
@@ -1,5 +1,3 @@
-// +build linux
-
package cgroups
type ThrottlingData struct {
@@ -126,7 +124,7 @@ type BlkioStatEntry struct {
}
type BlkioStats struct {
- // number of bytes tranferred to and from the block device
+ // number of bytes transferred to and from the block device
IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
@@ -146,6 +144,17 @@ type HugetlbStats struct {
Failcnt uint64 `json:"failcnt"`
}
+type RdmaEntry struct {
+ Device string `json:"device,omitempty"`
+ HcaHandles uint32 `json:"hca_handles,omitempty"`
+ HcaObjects uint32 `json:"hca_objects,omitempty"`
+}
+
+type RdmaStats struct {
+ RdmaLimit []RdmaEntry `json:"rdma_limit,omitempty"`
+ RdmaCurrent []RdmaEntry `json:"rdma_current,omitempty"`
+}
+
type Stats struct {
CpuStats CpuStats `json:"cpu_stats,omitempty"`
CPUSetStats CPUSetStats `json:"cpuset_stats,omitempty"`
@@ -154,6 +163,7 @@ type Stats struct {
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
// the map is in the format "size of hugepage: stats of the hugepage"
HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitempty"`
+ RdmaStats RdmaStats `json:"rdma_stats,omitempty"`
}
func NewStats() *Stats {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
index 92606525b..b32af4ee5 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
@@ -1,5 +1,3 @@
-// +build linux
-
package cgroups
import (
@@ -7,7 +5,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -23,11 +20,14 @@ import (
const (
CgroupProcesses = "cgroup.procs"
unifiedMountpoint = "/sys/fs/cgroup"
+ hybridMountpoint = "/sys/fs/cgroup/unified"
)
var (
isUnifiedOnce sync.Once
isUnified bool
+ isHybridOnce sync.Once
+ isHybrid bool
)
// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
@@ -49,6 +49,24 @@ func IsCgroup2UnifiedMode() bool {
return isUnified
}
+// IsCgroup2HybridMode returns whether we are running in cgroup v2 hybrid mode.
+func IsCgroup2HybridMode() bool {
+ isHybridOnce.Do(func() {
+ var st unix.Statfs_t
+ err := unix.Statfs(hybridMountpoint, &st)
+ if err != nil {
+ isHybrid = false
+ if !os.IsNotExist(err) {
+ // Report unexpected errors.
+ logrus.WithError(err).Debugf("statfs(%q) failed", hybridMountpoint)
+ }
+ return
+ }
+ isHybrid = st.Type == unix.CGROUP2_SUPER_MAGIC
+ })
+ return isHybrid
+}
+
type Mount struct {
Mountpoint string
Root string
@@ -118,8 +136,8 @@ func GetAllSubsystems() ([]string, error) {
return subsystems, nil
}
-func readProcsFile(file string) ([]int, error) {
- f, err := os.Open(file)
+func readProcsFile(dir string) ([]int, error) {
+ f, err := OpenFile(dir, CgroupProcesses, os.O_RDONLY)
if err != nil {
return nil, err
}
@@ -210,7 +228,7 @@ func EnterPid(cgroupPaths map[string]string, pid int) error {
func rmdir(path string) error {
err := unix.Rmdir(path)
- if err == nil || err == unix.ENOENT {
+ if err == nil || err == unix.ENOENT { //nolint:errorlint // unix errors are bare
return nil
}
return &os.PathError{Op: "rmdir", Path: path, Err: err}
@@ -224,7 +242,7 @@ func RemovePath(path string) error {
return nil
}
- infos, err := ioutil.ReadDir(path)
+ infos, err := os.ReadDir(path)
if err != nil {
if os.IsNotExist(err) {
err = nil
@@ -284,40 +302,61 @@ func RemovePaths(paths map[string]string) (err error) {
return fmt.Errorf("Failed to remove paths: %v", paths)
}
-func GetHugePageSize() ([]string, error) {
- dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
- if err != nil {
- return nil, err
- }
- files, err := dir.Readdirnames(0)
- dir.Close()
- if err != nil {
- return nil, err
- }
+var (
+ hugePageSizes []string
+ initHPSOnce sync.Once
+)
+
+func HugePageSizes() []string {
+ initHPSOnce.Do(func() {
+ dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
+ if err != nil {
+ return
+ }
+ files, err := dir.Readdirnames(0)
+ dir.Close()
+ if err != nil {
+ return
+ }
+
+ hugePageSizes, err = getHugePageSizeFromFilenames(files)
+ if err != nil {
+ logrus.Warn("HugePageSizes: ", err)
+ }
+ })
- return getHugePageSizeFromFilenames(files)
+ return hugePageSizes
}
func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
pageSizes := make([]string, 0, len(fileNames))
+ var warn error
for _, file := range fileNames {
// example: hugepages-1048576kB
val := strings.TrimPrefix(file, "hugepages-")
if len(val) == len(file) {
- // unexpected file name: no prefix found
+ // Unexpected file name: no prefix found, ignore it.
continue
}
- // The suffix is always "kB" (as of Linux 5.9)
+ // The suffix is always "kB" (as of Linux 5.13). If we find
+ // something else, produce an error but keep going.
eLen := len(val) - 2
val = strings.TrimSuffix(val, "kB")
if len(val) != eLen {
- logrus.Warnf("GetHugePageSize: %s: invalid filename suffix (expected \"kB\")", file)
+ // Highly unlikely.
+ if warn == nil {
+ warn = errors.New(file + `: invalid suffix (expected "kB")`)
+ }
continue
}
size, err := strconv.Atoi(val)
if err != nil {
- return nil, err
+ // Highly unlikely.
+ if warn == nil {
+ warn = fmt.Errorf("%s: %w", file, err)
+ }
+ continue
}
// Model after https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/hugetlb_cgroup.c?id=eff48ddeab782e35e58ccc8853f7386bbae9dec4#n574
// but in our case the size is in KB already.
@@ -331,34 +370,12 @@ func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
pageSizes = append(pageSizes, val)
}
- return pageSizes, nil
+ return pageSizes, warn
}
// GetPids returns all pids, that were added to cgroup at path.
func GetPids(dir string) ([]int, error) {
- return readProcsFile(filepath.Join(dir, CgroupProcesses))
-}
-
-// GetAllPids returns all pids, that were added to cgroup at path and to all its
-// subcgroups.
-func GetAllPids(path string) ([]int, error) {
- var pids []int
- // collect pids from all sub-cgroups
- err := filepath.Walk(path, func(p string, info os.FileInfo, iErr error) error {
- if iErr != nil {
- return iErr
- }
- if info.IsDir() || info.Name() != CgroupProcesses {
- return nil
- }
- cPids, err := readProcsFile(p)
- if err != nil {
- return err
- }
- pids = append(pids, cPids...)
- return nil
- })
- return pids, err
+ return readProcsFile(dir)
}
// WriteCgroupProc writes the specified pid into the cgroup's cgroup.procs file
@@ -376,7 +393,7 @@ func WriteCgroupProc(dir string, pid int) error {
file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY)
if err != nil {
- return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
+ return fmt.Errorf("failed to write %v: %w", pid, err)
}
defer file.Close()
@@ -393,7 +410,7 @@ func WriteCgroupProc(dir string, pid int) error {
continue
}
- return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
+ return fmt.Errorf("failed to write %v: %w", pid, err)
}
return err
}
@@ -446,5 +463,5 @@ func ConvertBlkIOToIOWeightValue(blkIoWeight uint16) uint64 {
if blkIoWeight == 0 {
return 0
}
- return uint64(1 + (uint64(blkIoWeight)-10)*9999/990)
+ return 1 + (uint64(blkIoWeight)-10)*9999/990
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
index 95ec9dff0..47c75f22b 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
@@ -46,11 +46,8 @@ func NewNotFoundError(sub string) error {
}
func IsNotFound(err error) bool {
- if err == nil {
- return false
- }
- _, ok := err.(*NotFoundError)
- return ok
+ var nfErr *NotFoundError
+ return errors.As(err, &nfErr)
}
func tryDefaultPath(cgroupPath, subsystem string) string {
@@ -116,6 +113,11 @@ func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
return "", errUnified
}
+ // If subsystem is empty, we look for the cgroupv2 hybrid path.
+ if len(subsystem) == 0 {
+ return hybridMountpoint, nil
+ }
+
// Avoid parsing mountinfo by trying the default path first, if possible.
if path := tryDefaultPath(cgroupPath, subsystem); path != "" {
return path, nil
@@ -154,7 +156,7 @@ func findCgroupMountpointAndRootFromMI(mounts []*mountinfo.Info, cgroupPath, sub
func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
if len(m.Subsystems) == 0 {
- return "", fmt.Errorf("no subsystem for mount")
+ return "", errors.New("no subsystem for mount")
}
return getControllerPath(m.Subsystems[0], cgroups)
@@ -226,6 +228,11 @@ func GetOwnCgroupPath(subsystem string) (string, error) {
return "", err
}
+ // If subsystem is empty, we look for the cgroupv2 hybrid path.
+ if len(subsystem) == 0 {
+ return hybridMountpoint, nil
+ }
+
return getCgroupPathHelper(subsystem, cgroup)
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/BUILD.bazel b/vendor/github.com/opencontainers/runc/libcontainer/configs/BUILD.bazel
index acccbbee9..f945c9a20 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/BUILD.bazel
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/BUILD.bazel
@@ -18,6 +18,7 @@ go_library(
"namespaces_syscall_unsupported.go",
"namespaces_unsupported.go",
"network.go",
+ "rdma.go",
],
importmap = "kubevirt.io/kubevirt/vendor/github.com/opencontainers/runc/libcontainer/configs",
importpath = "github.com/opencontainers/runc/libcontainer/configs",
@@ -25,16 +26,14 @@ go_library(
deps = [
"//vendor/github.com/opencontainers/runc/libcontainer/devices:go_default_library",
"//vendor/github.com/opencontainers/runtime-spec/specs-go:go_default_library",
- "//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
+ "//vendor/golang.org/x/sys/unix:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:android": [
"//vendor/github.com/coreos/go-systemd/v22/dbus:go_default_library",
- "//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/coreos/go-systemd/v22/dbus:go_default_library",
- "//vendor/golang.org/x/sys/unix:go_default_library",
],
"//conditions:default": [],
}),
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
index 5ea9d940c..2d4a89871 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
@@ -28,17 +28,26 @@ type Cgroup struct {
// ScopePrefix describes prefix for the scope name
ScopePrefix string `json:"scope_prefix"`
- // Paths represent the absolute cgroups paths to join.
- // This takes precedence over Path.
- Paths map[string]string
-
// Resources contains various cgroups settings to apply
*Resources
+ // Systemd tells if systemd should be used to manage cgroups.
+ Systemd bool
+
// SystemdProps are any additional properties for systemd,
// derived from org.systemd.property.xxx annotations.
// Ignored unless systemd is used for managing cgroups.
SystemdProps []systemdDbus.Property `json:"-"`
+
+ // Rootless tells if rootless cgroups should be used.
+ Rootless bool
+
+ // The host UID that should own the cgroup, or nil to accept
+ // the default ownership. This should only be set when the
+ // cgroupfs is to be mounted read/write.
+ // Not all cgroup manager implementations support changing
+ // the ownership.
+ OwnerUID *int `json:"owner_uid,omitempty"`
}
type Resources struct {
@@ -117,6 +126,9 @@ type Resources struct {
// Set class identifier for container's network packets
NetClsClassid uint32 `json:"net_cls_classid_u"`
+ // Rdma resource restriction configuration
+ Rdma map[string]LinuxRdma `json:"rdma"`
+
// Used on cgroups v2:
// CpuWeight sets a proportional bandwidth limit.
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
index 2a519f582..7e383020f 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
index 4281593f0..c1b4a0041 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
@@ -7,10 +7,10 @@ import (
"os/exec"
"time"
+ "github.com/sirupsen/logrus"
+
"github.com/opencontainers/runc/libcontainer/devices"
"github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
type Rlimit struct {
@@ -31,10 +31,12 @@ type IDMap struct {
// for syscalls. Additional architectures can be added by specifying them in
// Architectures.
type Seccomp struct {
- DefaultAction Action `json:"default_action"`
- Architectures []string `json:"architectures"`
- Syscalls []*Syscall `json:"syscalls"`
- DefaultErrnoRet *uint `json:"default_errno_ret"`
+ DefaultAction Action `json:"default_action"`
+ Architectures []string `json:"architectures"`
+ Syscalls []*Syscall `json:"syscalls"`
+ DefaultErrnoRet *uint `json:"default_errno_ret"`
+ ListenerPath string `json:"listener_path,omitempty"`
+ ListenerMetadata string `json:"listener_metadata,omitempty"`
}
// Action is taken upon rule match in Seccomp
@@ -47,6 +49,9 @@ const (
Allow
Trace
Log
+ Notify
+ KillThread
+ KillProcess
)
// Operator is a comparison operator to be used when matching syscall arguments in Seccomp
@@ -246,6 +251,19 @@ const (
Poststop HookName = "poststop"
)
+// KnownHookNames returns the known hook names.
+// Used by `runc features`.
+func KnownHookNames() []string {
+ return []string{
+ string(Prestart), // deprecated
+ string(CreateRuntime),
+ string(CreateContainer),
+ string(StartContainer),
+ string(Poststart),
+ string(Poststop),
+ }
+}
+
type Capabilities struct {
// Bounding is the set of capabilities checked by the kernel.
Bounding []string
@@ -262,7 +280,7 @@ type Capabilities struct {
func (hooks HookList) RunHooks(state *specs.State) error {
for i, h := range hooks {
if err := h.Run(state); err != nil {
- return errors.Wrapf(err, "Running hook #%d:", i)
+ return fmt.Errorf("error running hook #%d: %w", i, err)
}
}
@@ -375,7 +393,7 @@ func (c Command) Run(s *specs.State) error {
go func() {
err := cmd.Wait()
if err != nil {
- err = fmt.Errorf("error running hook: %v, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
+ err = fmt.Errorf("error running hook: %w, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
}
errC <- err
}()
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
index 07da10804..8c02848b7 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
@@ -1,17 +1,24 @@
package configs
-import "fmt"
+import "errors"
+
+var (
+ errNoUIDMap = errors.New("User namespaces enabled, but no uid mappings found.")
+ errNoUserMap = errors.New("User namespaces enabled, but no user mapping found.")
+ errNoGIDMap = errors.New("User namespaces enabled, but no gid mappings found.")
+ errNoGroupMap = errors.New("User namespaces enabled, but no group mapping found.")
+)
// HostUID gets the translated uid for the process on host which could be
// different when user namespaces are enabled.
func (c Config) HostUID(containerId int) (int, error) {
if c.Namespaces.Contains(NEWUSER) {
if c.UidMappings == nil {
- return -1, fmt.Errorf("User namespaces enabled, but no uid mappings found.")
+ return -1, errNoUIDMap
}
id, found := c.hostIDFromMapping(containerId, c.UidMappings)
if !found {
- return -1, fmt.Errorf("User namespaces enabled, but no user mapping found.")
+ return -1, errNoUserMap
}
return id, nil
}
@@ -30,11 +37,11 @@ func (c Config) HostRootUID() (int, error) {
func (c Config) HostGID(containerId int) (int, error) {
if c.Namespaces.Contains(NEWUSER) {
if c.GidMappings == nil {
- return -1, fmt.Errorf("User namespaces enabled, but no gid mappings found.")
+ return -1, errNoGIDMap
}
id, found := c.hostIDFromMapping(containerId, c.GidMappings)
if !found {
- return -1, fmt.Errorf("User namespaces enabled, but no group mapping found.")
+ return -1, errNoGroupMap
}
return id, nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
index 93bf41c8d..bce829e29 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
@@ -1,3 +1,4 @@
+//go:build gofuzz
// +build gofuzz
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
index 57e9f037d..f8d951ab8 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
@@ -1,6 +1,9 @@
package configs
type IntelRdt struct {
+ // The identity for RDT Class of Service
+ ClosID string `json:"closID,omitempty"`
+
// The schema for L3 cache id and capacity bitmask (CBM)
// Format: "L3:<cache_id0>=<cbm0>;<cache_id1>=<cbm1>;..."
L3CacheSchema string `json:"l3_cache_schema,omitempty"`
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
index a75ff10ec..784c61820 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
@@ -1,5 +1,7 @@
package configs
+import "golang.org/x/sys/unix"
+
const (
// EXT_COPYUP is a directive to copy up the contents of a directory when
// a tmpfs is mounted over it.
@@ -28,6 +30,9 @@ type Mount struct {
// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
Relabel string `json:"relabel"`
+ // RecAttr represents mount properties to be applied recursively (AT_RECURSIVE), see mount_setattr(2).
+ RecAttr *unix.MountAttr `json:"rec_attr"`
+
// Extensions are additional flags that are specific to runc.
Extensions int `json:"extensions"`
@@ -37,3 +42,7 @@ type Mount struct {
// Optional Command to be run after Source is mounted.
PostmountCmds []Command `json:"postmount_cmds"`
}
+
+func (m *Mount) IsBind() bool {
+ return m.Flags&unix.MS_BIND != 0
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
index 2dc7adfc9..0516dba8d 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
index 5d9a5c81f..fbb0d4907 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux && !windows
// +build !linux,!windows
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
index cc76e2f58..946db30a5 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go
new file mode 100644
index 000000000..c69f2c802
--- /dev/null
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go
@@ -0,0 +1,9 @@
+package configs
+
+// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11)
+type LinuxRdma struct {
+ // Maximum number of HCA handles that can be opened. Default is "no limit".
+ HcaHandles *uint32 `json:"hca_handles,omitempty"`
+ // Maximum number of HCA objects that can be created. Default is "no limit".
+ HcaObjects *uint32 `json:"hca_objects,omitempty"`
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
index 6d5b3d09d..7d8e9fc31 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
@@ -1,10 +1,10 @@
+//go:build !windows
// +build !windows
package devices
import (
"errors"
- "io/ioutil"
"os"
"path/filepath"
@@ -16,8 +16,8 @@ var ErrNotADevice = errors.New("not a device node")
// Testing dependencies
var (
- unixLstat = unix.Lstat
- ioutilReadDir = ioutil.ReadDir
+ unixLstat = unix.Lstat
+ osReadDir = os.ReadDir
)
func mkDev(d *Rule) (uint64, error) {
@@ -40,7 +40,7 @@ func DeviceFromPath(path, permissions string) (*Device, error) {
var (
devType Type
mode = stat.Mode
- devNumber = uint64(stat.Rdev)
+ devNumber = uint64(stat.Rdev) //nolint:unconvert // Rdev is uint32 on e.g. MIPS.
major = unix.Major(devNumber)
minor = unix.Minor(devNumber)
)
@@ -76,7 +76,7 @@ func HostDevices() ([]*Device, error) {
// GetDevices recursively traverses a directory specified by path
// and returns all devices found there.
func GetDevices(path string) ([]*Device, error) {
- files, err := ioutilReadDir(path)
+ files, err := osReadDir(path)
if err != nil {
return nil, err
}
@@ -103,7 +103,7 @@ func GetDevices(path string) ([]*Device, error) {
}
device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
if err != nil {
- if err == ErrNotADevice {
+ if errors.Is(err, ErrNotADevice) {
continue
}
if os.IsNotExist(err) {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
index 967717a1b..f95c1409f 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
@@ -1,3 +1,4 @@
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package user
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
index cc7a106be..2473c5ead 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
@@ -120,7 +120,7 @@ func ParsePasswdFileFilter(path string, filter func(User) bool) ([]User, error)
func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
if r == nil {
- return nil, fmt.Errorf("nil source for passwd-formatted data")
+ return nil, errors.New("nil source for passwd-formatted data")
}
var (
@@ -178,7 +178,7 @@ func ParseGroupFileFilter(path string, filter func(Group) bool) ([]Group, error)
func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
if r == nil {
- return nil, fmt.Errorf("nil source for group-formatted data")
+ return nil, errors.New("nil source for group-formatted data")
}
rd := bufio.NewReader(r)
out := []Group{}
@@ -339,7 +339,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
if userArg == "" {
userArg = strconv.Itoa(user.Uid)
}
- return nil, fmt.Errorf("unable to find user %s: %v", userArg, err)
+ return nil, fmt.Errorf("unable to find user %s: %w", userArg, err)
}
var matchedUserName string
@@ -355,7 +355,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
if uidErr != nil {
// Not numeric.
- return nil, fmt.Errorf("unable to find user %s: %v", userArg, ErrNoPasswdEntries)
+ return nil, fmt.Errorf("unable to find user %s: %w", userArg, ErrNoPasswdEntries)
}
user.Uid = uidArg
@@ -390,7 +390,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
return g.Name == groupArg
})
if err != nil && group != nil {
- return nil, fmt.Errorf("unable to find groups for spec %v: %v", matchedUserName, err)
+ return nil, fmt.Errorf("unable to find groups for spec %v: %w", matchedUserName, err)
}
// Only start modifying user.Gid if it is in explicit form.
@@ -404,7 +404,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
if gidErr != nil {
// Not numeric.
- return nil, fmt.Errorf("unable to find group %s: %v", groupArg, ErrNoGroupEntries)
+ return nil, fmt.Errorf("unable to find group %s: %w", groupArg, ErrNoGroupEntries)
}
user.Gid = gidArg
@@ -445,7 +445,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
return false
})
if err != nil {
- return nil, fmt.Errorf("Unable to find additional groups %v: %v", additionalGroups, err)
+ return nil, fmt.Errorf("Unable to find additional groups %v: %w", additionalGroups, err)
}
}
@@ -468,7 +468,8 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
if !found {
gid, err := strconv.ParseInt(ag, 10, 64)
if err != nil {
- return nil, fmt.Errorf("Unable to find group %s", ag)
+ // Not a numeric ID either.
+ return nil, fmt.Errorf("Unable to find group %s: %w", ag, ErrNoGroupEntries)
}
// Ensure gid is inside gid range.
if gid < minID || gid > maxID {
@@ -521,7 +522,7 @@ func ParseSubIDFileFilter(path string, filter func(SubID) bool) ([]SubID, error)
func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
if r == nil {
- return nil, fmt.Errorf("nil source for subid-formatted data")
+ return nil, errors.New("nil source for subid-formatted data")
}
var (
@@ -574,7 +575,7 @@ func ParseIDMapFileFilter(path string, filter func(IDMap) bool) ([]IDMap, error)
func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
if r == nil {
- return nil, fmt.Errorf("nil source for idmap-formatted data")
+ return nil, errors.New("nil source for idmap-formatted data")
}
var (
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
index 8c9bb5df3..e018eae61 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
@@ -1,3 +1,4 @@
+//go:build gofuzz
// +build gofuzz
package user
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go b/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
index 529f8eaea..1e00ab8b5 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
@@ -1,3 +1,4 @@
+//go:build gofuzz
// +build gofuzz
package userns
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
index f45bb0c31..f35c13a10 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package userns
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
index c8a9364d5..7ef9da21f 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
@@ -1,5 +1,3 @@
-// +build linux
-
package utils
/*
@@ -88,6 +86,11 @@ func SendFd(socket *os.File, name string, fd uintptr) error {
if len(name) >= MaxNameLen {
return fmt.Errorf("sendfd: filename too long: %s", name)
}
- oob := unix.UnixRights(int(fd))
- return unix.Sendmsg(int(socket.Fd()), []byte(name), oob, nil, 0)
+ return SendFds(socket, []byte(name), int(fd))
+}
+
+// SendFds sends a list of files descriptor and msg over the given AF_UNIX socket.
+func SendFds(socket *os.File, msg []byte, fds ...int) error {
+ oob := unix.UnixRights(fds...)
+ return unix.Sendmsg(int(socket.Fd()), msg, oob, nil, 0)
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
index cd78f23e1..6b9fc3435 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
@@ -11,7 +11,7 @@ import (
"strings"
"unsafe"
- "github.com/cyphar/filepath-securejoin"
+ securejoin "github.com/cyphar/filepath-securejoin"
"golang.org/x/sys/unix"
)
@@ -33,16 +33,6 @@ func init() {
}
}
-// ResolveRootfs ensures that the current working directory is
-// not a symlink and returns the absolute path to the rootfs
-func ResolveRootfs(uncleanRootfs string) (string, error) {
- rootfs, err := filepath.Abs(uncleanRootfs)
- if err != nil {
- return "", err
- }
- return filepath.EvalSymlinks(rootfs)
-}
-
// ExitStatus returns the correct exit status for a process based on if it
// was signaled or exited cleanly
func ExitStatus(status unix.WaitStatus) int {
@@ -120,7 +110,7 @@ func WithProcfd(root, unsafePath string, fn func(procfd string) error) error {
unsafePath = stripRoot(root, unsafePath)
path, err := securejoin.SecureJoin(root, unsafePath)
if err != nil {
- return fmt.Errorf("resolving path inside rootfs failed: %v", err)
+ return fmt.Errorf("resolving path inside rootfs failed: %w", err)
}
// Open the target path.
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
index 1576f2d4a..220d0b439 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
@@ -1,3 +1,4 @@
+//go:build !windows
// +build !windows
package utils
@@ -14,7 +15,7 @@ import (
func EnsureProcHandle(fh *os.File) error {
var buf unix.Statfs_t
if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil {
- return fmt.Errorf("ensure %s is on procfs: %v", fh.Name(), err)
+ return fmt.Errorf("ensure %s is on procfs: %w", fh.Name(), err)
}
if buf.Type != unix.PROC_SUPER_MAGIC {
return fmt.Errorf("%s is not on procfs", fh.Name())
@@ -52,7 +53,7 @@ func CloseExecFrom(minFd int) error {
// Intentionally ignore errors from unix.CloseOnExec -- the cases where
// this might fail are basically file descriptors that have already
// been closed (including and especially the one that was created when
- // ioutil.ReadDir did the "opendir" syscall).
+ // os.ReadDir did the "opendir" syscall).
unix.CloseOnExec(fd)
}
return nil
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 16daeeaa3..49dc79d62 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -44,8 +44,8 @@ github.com/c9s/goprocinfo/linux
# github.com/cespare/xxhash/v2 v2.1.1
## explicit; go 1.11
github.com/cespare/xxhash/v2
-# github.com/cilium/ebpf v0.6.2
-## explicit; go 1.15
+# github.com/cilium/ebpf v0.7.0
+## explicit; go 1.16
github.com/cilium/ebpf
github.com/cilium/ebpf/asm
github.com/cilium/ebpf/internal
@@ -68,8 +68,8 @@ github.com/coreos/go-systemd/v22/dbus
## explicit; go 1.13
github.com/coreos/prometheus-operator/pkg/apis/monitoring
github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1
-# github.com/cyphar/filepath-securejoin v0.2.2
-## explicit
+# github.com/cyphar/filepath-securejoin v0.2.3
+## explicit; go 1.13
github.com/cyphar/filepath-securejoin
# github.com/davecgh/go-spew v1.1.1
## explicit
@@ -147,7 +147,7 @@ github.com/go-stack/stack
# github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
## explicit; go 1.13
github.com/go-task/slim-sprig
-# github.com/godbus/dbus/v5 v5.0.4
+# github.com/godbus/dbus/v5 v5.0.6
## explicit; go 1.12
github.com/godbus/dbus/v5
# github.com/gogo/protobuf v1.3.2
@@ -270,8 +270,8 @@ github.com/mitchellh/mapstructure
## explicit; go 1.13
github.com/moby/spdystream
github.com/moby/spdystream/spdy
-# github.com/moby/sys/mountinfo v0.4.1
-## explicit; go 1.14
+# github.com/moby/sys/mountinfo v0.5.0
+## explicit; go 1.16
github.com/moby/sys/mountinfo
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
## explicit
@@ -317,8 +317,8 @@ github.com/onsi/gomega/matchers/support/goraph/edge
github.com/onsi/gomega/matchers/support/goraph/node
github.com/onsi/gomega/matchers/support/goraph/util
github.com/onsi/gomega/types
-# github.com/opencontainers/runc v1.0.3
-## explicit; go 1.13
+# github.com/opencontainers/runc v1.1.2
+## explicit; go 1.16
github.com/opencontainers/runc/libcontainer/cgroups
github.com/opencontainers/runc/libcontainer/cgroups/devices
github.com/opencontainers/runc/libcontainer/cgroups/ebpf
@@ -334,7 +334,7 @@ github.com/opencontainers/runc/libcontainer/utils
# github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
## explicit
github.com/opencontainers/runtime-spec/specs-go
-# github.com/opencontainers/selinux v1.8.2 => github.com/opencontainers/selinux v1.6.0
+# github.com/opencontainers/selinux v1.10.0 => github.com/opencontainers/selinux v1.6.0
## explicit; go 1.13
github.com/opencontainers/selinux/go-selinux
github.com/opencontainers/selinux/pkg/pwalk
--
2.37.1