From 981b7fc2f3596e0125973f2df6a0989b1ed78d7c Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 16 Jul 2021 12:35:27 -0700 Subject: [PATCH 1/2] vendor: bump runc to 1.0.1 The commands used were (roughly): hack/pin-dependency.sh github.com/opencontainers/runc v1.0.1 hack/lint-dependencies.sh # Follow its recommendations. hack/pin-dependency.sh github.com/cilium/ebpf v0.6.2 hack/pin-dependency.sh github.com/opencontainers/selinux v1.8.2 hack/pin-dependency.sh github.com/sirupsen/logrus v1.8.1 # Recheck. hack/lint-dependencies.sh GO111MODULE=on go mod edit -dropreplace github.com/willf/bitset hack/update-vendor.sh # Recheck. hack/lint-dependencies.sh hack/update-internal-modules.sh # Recheck. hack/lint-dependencies.sh Signed-off-by: Kir Kolyshkin --- .../{willf => bits-and-blooms}/bitset/LICENSE | 4 +- go.mod | 14 +- go.sum | 20 +- .../src/k8s.io/apiextensions-apiserver/go.sum | 3 +- staging/src/k8s.io/apiserver/go.mod | 1 + staging/src/k8s.io/apiserver/go.sum | 3 +- staging/src/k8s.io/cloud-provider/go.sum | 3 +- staging/src/k8s.io/controller-manager/go.sum | 3 +- staging/src/k8s.io/kube-aggregator/go.sum | 3 +- .../src/k8s.io/kube-controller-manager/go.sum | 1 + .../src/k8s.io/legacy-cloud-providers/go.sum | 1 + .../src/k8s.io/pod-security-admission/go.sum | 3 +- staging/src/k8s.io/sample-apiserver/go.sum | 3 +- .../bitset/.gitignore | 0 .../bitset/.travis.yml | 0 .../{willf => bits-and-blooms}/bitset/LICENSE | 0 .../bitset/README.md | 11 +- .../bitset/azure-pipelines.yml | 0 .../bitset/bitset.go | 23 +- .../github.com/bits-and-blooms/bitset/go.mod | 3 + .../{willf => bits-and-blooms}/bitset/go.sum | 0 .../bitset/popcnt.go | 0 .../bitset/popcnt_19.go | 0 .../bitset/popcnt_amd64.go | 0 .../bitset/popcnt_amd64.s | 0 .../bitset/popcnt_generic.go | 0 .../bitset/trailing_zeros_18.go | 0 .../bitset/trailing_zeros_19.go | 0 vendor/github.com/cilium/ebpf/CONTRIBUTING.md | 21 +- vendor/github.com/cilium/ebpf/Makefile | 7 +- vendor/github.com/cilium/ebpf/asm/func.go | 52 ++ .../github.com/cilium/ebpf/asm/func_string.go | 56 +- .../github.com/cilium/ebpf/asm/instruction.go | 32 +- .../github.com/cilium/ebpf/asm/load_store.go | 2 +- vendor/github.com/cilium/ebpf/asm/opcode.go | 4 +- vendor/github.com/cilium/ebpf/collection.go | 59 +- vendor/github.com/cilium/ebpf/elf_reader.go | 50 +- .../cilium/ebpf/internal/btf/btf.go | 32 +- .../cilium/ebpf/internal/btf/btf_types.go | 27 +- .../ebpf/internal/btf/btf_types_string.go | 44 + .../cilium/ebpf/internal/btf/core.go | 763 +++++++++++++++--- .../cilium/ebpf/internal/btf/ext_info.go | 46 +- .../cilium/ebpf/internal/btf/types.go | 62 +- vendor/github.com/cilium/ebpf/internal/elf.go | 16 + .../github.com/cilium/ebpf/internal/endian.go | 5 + .../github.com/cilium/ebpf/internal/errors.go | 4 + vendor/github.com/cilium/ebpf/internal/ptr.go | 4 - .../cilium/ebpf/internal/syscall.go | 67 +- .../cilium/ebpf/internal/unix/types_linux.go | 3 + .../cilium/ebpf/internal/unix/types_other.go | 3 + vendor/github.com/cilium/ebpf/link/iter.go | 43 +- vendor/github.com/cilium/ebpf/link/kprobe.go | 288 +++++-- .../github.com/cilium/ebpf/link/perf_event.go | 78 +- .../github.com/cilium/ebpf/link/platform.go | 25 + vendor/github.com/cilium/ebpf/link/program.go | 4 +- .../github.com/cilium/ebpf/link/syscalls.go | 17 + .../github.com/cilium/ebpf/link/tracepoint.go | 4 +- vendor/github.com/cilium/ebpf/link/uprobe.go | 237 ++++++ vendor/github.com/cilium/ebpf/linker.go | 11 +- vendor/github.com/cilium/ebpf/map.go | 86 +- vendor/github.com/cilium/ebpf/prog.go | 151 ++-- vendor/github.com/cilium/ebpf/run-tests.sh | 125 +-- vendor/github.com/cilium/ebpf/syscalls.go | 181 ++--- vendor/github.com/cilium/ebpf/types.go | 4 + vendor/github.com/cilium/ebpf/types_string.go | 8 +- .../runc/libcontainer/apparmor/apparmor.go | 16 + .../libcontainer/apparmor/apparmor_linux.go | 11 +- .../apparmor/apparmor_unsupported.go | 10 +- .../cgroups/devices/devices_emulator.go | 13 +- .../cgroups/ebpf/devicefilter/devicefilter.go | 119 +-- .../runc/libcontainer/cgroups/ebpf/ebpf.go | 57 -- .../libcontainer/cgroups/ebpf/ebpf_linux.go | 253 ++++++ .../cgroups/{fscommon/open.go => file.go} | 60 +- .../runc/libcontainer/cgroups/fs/blkio.go | 59 +- .../runc/libcontainer/cgroups/fs/cpu.go | 17 +- .../runc/libcontainer/cgroups/fs/cpuacct.go | 11 +- .../runc/libcontainer/cgroups/fs/cpuset.go | 19 +- .../runc/libcontainer/cgroups/fs/devices.go | 5 +- .../runc/libcontainer/cgroups/fs/freezer.go | 36 +- .../runc/libcontainer/cgroups/fs/fs.go | 8 +- .../runc/libcontainer/cgroups/fs/hugetlb.go | 5 +- .../runc/libcontainer/cgroups/fs/memory.go | 26 +- .../runc/libcontainer/cgroups/fs/net_cls.go | 6 +- .../runc/libcontainer/cgroups/fs/net_prio.go | 6 +- .../libcontainer/cgroups/fs/perf_event.go | 3 +- .../runc/libcontainer/cgroups/fs/pids.go | 5 +- .../runc/libcontainer/cgroups/fs2/cpu.go | 7 +- .../runc/libcontainer/cgroups/fs2/cpuset.go | 6 +- .../runc/libcontainer/cgroups/fs2/create.go | 14 +- .../libcontainer/cgroups/fs2/defaultpath.go | 4 +- .../runc/libcontainer/cgroups/fs2/devices.go | 16 +- .../runc/libcontainer/cgroups/fs2/freezer.go | 101 ++- .../runc/libcontainer/cgroups/fs2/fs2.go | 8 +- .../runc/libcontainer/cgroups/fs2/hugetlb.go | 2 +- .../runc/libcontainer/cgroups/fs2/io.go | 98 ++- .../runc/libcontainer/cgroups/fs2/memory.go | 8 +- .../runc/libcontainer/cgroups/fs2/pids.go | 6 +- .../libcontainer/cgroups/fscommon/fscommon.go | 51 -- .../libcontainer/cgroups/fscommon/utils.go | 15 +- .../libcontainer/cgroups/systemd/common.go | 59 +- .../libcontainer/cgroups/systemd/cpuset.go | 6 +- .../runc/libcontainer/cgroups/systemd/dbus.go | 6 +- .../runc/libcontainer/cgroups/systemd/v1.go | 131 ++- .../runc/libcontainer/cgroups/systemd/v2.go | 32 +- .../runc/libcontainer/cgroups/utils.go | 6 +- .../runc/libcontainer/configs/cgroup_linux.go | 10 +- .../configs/cgroup_unsupported.go | 4 +- .../runc/libcontainer/configs/config.go | 10 +- .../runc/libcontainer/configs/devices.go | 17 - .../runc/libcontainer/configs/mount.go | 2 +- .../configs/namespaces_unsupported.go | 3 +- .../runc/libcontainer/configs/network.go | 13 +- .../configs/validate/validator.go | 17 +- .../runc/libcontainer/console_linux.go | 2 +- .../runc/libcontainer/container_linux.go | 33 +- .../runc/libcontainer/criu_opts_linux.go | 1 + .../runc/libcontainer/devices/device_unix.go | 11 +- .../runc/libcontainer/factory_linux.go | 8 +- .../runc/libcontainer/init_linux.go | 14 +- .../runc/libcontainer/intelrdt/cmt.go | 4 +- .../runc/libcontainer/intelrdt/mbm.go | 6 +- .../runc/libcontainer/intelrdt/monitoring.go | 4 +- .../runc/libcontainer/keys/keyctl.go | 10 +- .../runc/libcontainer/logs/logs.go | 2 +- .../runc/libcontainer/network_linux.go | 3 +- .../runc/libcontainer/notify_linux.go | 2 +- .../runc/libcontainer/process_linux.go | 30 +- .../runc/libcontainer/restored_process.go | 4 +- .../runc/libcontainer/rootfs_linux.go | 47 +- .../seccomp/patchbpf/enosys_linux.go | 33 +- .../runc/libcontainer/setns_init_linux.go | 4 +- .../runc/libcontainer/stacktrace/capture.go | 4 +- .../runc/libcontainer/standard_init_linux.go | 10 +- .../runc/libcontainer/state_linux.go | 2 +- .../runc/libcontainer/system/linux.go | 11 +- .../runc/libcontainer/system/proc.go | 2 +- .../libcontainer/system/userns_deprecated.go | 5 - .../runc/libcontainer/user/user.go | 116 ++- .../opencontainers/selinux/go-selinux/doc.go | 4 - .../selinux/go-selinux/label/label_linux.go | 5 +- .../selinux/go-selinux/selinux.go | 10 +- .../selinux/go-selinux/selinux_linux.go | 13 +- .../selinux/go-selinux/selinux_stub.go | 2 + vendor/github.com/sirupsen/logrus/.travis.yml | 14 +- .../github.com/sirupsen/logrus/CHANGELOG.md | 36 + vendor/github.com/sirupsen/logrus/README.md | 2 +- vendor/github.com/sirupsen/logrus/entry.go | 73 +- vendor/github.com/sirupsen/logrus/go.sum | 2 - .../sirupsen/logrus/json_formatter.go | 5 +- vendor/github.com/sirupsen/logrus/logger.go | 2 +- .../sirupsen/logrus/terminal_check_unix.go | 2 +- .../sirupsen/logrus/text_formatter.go | 7 +- vendor/github.com/willf/bitset/go.mod | 3 - vendor/modules.txt | 22 +- 154 files changed, 3328 insertions(+), 1359 deletions(-) rename LICENSES/vendor/github.com/{willf => bits-and-blooms}/bitset/LICENSE (91%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/.gitignore (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/.travis.yml (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/LICENSE (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/README.md (84%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/azure-pipelines.yml (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/bitset.go (97%) create mode 100644 vendor/github.com/bits-and-blooms/bitset/go.mod rename vendor/github.com/{willf => bits-and-blooms}/bitset/go.sum (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/popcnt.go (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/popcnt_19.go (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/popcnt_amd64.go (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/popcnt_amd64.s (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/popcnt_generic.go (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/trailing_zeros_18.go (100%) rename vendor/github.com/{willf => bits-and-blooms}/bitset/trailing_zeros_19.go (100%) create mode 100644 vendor/github.com/cilium/ebpf/internal/btf/btf_types_string.go create mode 100644 vendor/github.com/cilium/ebpf/link/platform.go create mode 100644 vendor/github.com/cilium/ebpf/link/uprobe.go create mode 100644 vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go delete mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf.go create mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf_linux.go rename vendor/github.com/opencontainers/runc/libcontainer/cgroups/{fscommon/open.go => file.go} (71%) delete mode 100644 vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/fscommon.go delete mode 100644 vendor/github.com/opencontainers/runc/libcontainer/configs/devices.go delete mode 100644 vendor/github.com/opencontainers/runc/libcontainer/system/userns_deprecated.go delete mode 100644 vendor/github.com/willf/bitset/go.mod diff --git a/LICENSES/vendor/github.com/willf/bitset/LICENSE b/LICENSES/vendor/github.com/bits-and-blooms/bitset/LICENSE similarity index 91% rename from LICENSES/vendor/github.com/willf/bitset/LICENSE rename to LICENSES/vendor/github.com/bits-and-blooms/bitset/LICENSE index cb0e0a2d5703..987cea60a4c6 100644 --- a/LICENSES/vendor/github.com/willf/bitset/LICENSE +++ b/LICENSES/vendor/github.com/bits-and-blooms/bitset/LICENSE @@ -1,4 +1,4 @@ -= vendor/github.com/willf/bitset licensed under: = += vendor/github.com/bits-and-blooms/bitset licensed under: = Copyright (c) 2014 Will Fitzgerald. All rights reserved. @@ -28,4 +28,4 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -= vendor/github.com/willf/bitset/LICENSE 0d2b5d66dabaff0df8e1ffe191a21bd1 += vendor/github.com/bits-and-blooms/bitset/LICENSE 0d2b5d66dabaff0df8e1ffe191a21bd1 diff --git a/go.mod b/go.mod index 61ec527819c9..db90595b14cc 100644 --- a/go.mod +++ b/go.mod @@ -66,8 +66,8 @@ require ( github.com/onsi/ginkgo v1.14.0 github.com/onsi/gomega v1.10.1 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/runc v1.0.0-rc95 - github.com/opencontainers/selinux v1.8.0 + github.com/opencontainers/runc v1.0.1 + github.com/opencontainers/selinux v1.8.2 github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.11.0 @@ -181,6 +181,7 @@ replace ( github.com/benbjohnson/clock => github.com/benbjohnson/clock v1.0.3 github.com/beorn7/perks => github.com/beorn7/perks v1.0.1 github.com/bgentry/speakeasy => github.com/bgentry/speakeasy v0.1.0 + github.com/bits-and-blooms/bitset => github.com/bits-and-blooms/bitset v1.2.0 github.com/bketelsen/crypt => github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c github.com/blang/semver => github.com/blang/semver v3.5.1+incompatible github.com/boltdb/bolt => github.com/boltdb/bolt v1.3.1 @@ -192,7 +193,7 @@ replace ( github.com/chzyer/logex => github.com/chzyer/logex v1.1.10 github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/chzyer/test => github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 - github.com/cilium/ebpf => github.com/cilium/ebpf v0.5.0 + github.com/cilium/ebpf => github.com/cilium/ebpf v0.6.2 github.com/clusterhq/flocker-go => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 github.com/cncf/udpa/go => github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 github.com/cockroachdb/datadriven => github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 @@ -368,9 +369,9 @@ replace ( github.com/onsi/gomega => github.com/onsi/gomega v1.10.1 github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.1 - github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc95 + github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.1 github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 - github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.8.0 + github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.8.2 github.com/opentracing/opentracing-go => github.com/opentracing/opentracing-go v1.1.0 github.com/pascaldekloe/goe => github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c github.com/pelletier/go-toml => github.com/pelletier/go-toml v1.2.0 @@ -396,7 +397,7 @@ replace ( github.com/seccomp/libseccomp-golang => github.com/seccomp/libseccomp-golang v0.9.1 github.com/sergi/go-diff => github.com/sergi/go-diff v1.1.0 github.com/shurcooL/sanitized_anchor_name => github.com/shurcooL/sanitized_anchor_name v1.0.0 - github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.7.0 + github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.8.1 github.com/smartystreets/assertions => github.com/smartystreets/assertions v1.1.0 github.com/smartystreets/goconvey => github.com/smartystreets/goconvey v1.6.4 github.com/soheilhy/cmux => github.com/soheilhy/cmux v0.1.5 @@ -418,7 +419,6 @@ replace ( github.com/vishvananda/netlink => github.com/vishvananda/netlink v1.1.0 github.com/vishvananda/netns => github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae github.com/vmware/govmomi => github.com/vmware/govmomi v0.20.3 - github.com/willf/bitset => github.com/willf/bitset v1.1.11 github.com/xiang90/probing => github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 github.com/xlab/treeprint => github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca github.com/yuin/goldmark => github.com/yuin/goldmark v1.3.5 diff --git a/go.sum b/go.sum index 75c168161fab..6e4d3152c309 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiU github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -84,8 +86,8 @@ github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d8 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= -github.com/cilium/ebpf v0.5.0 h1:E1KshmrMEtkMP2UjlWzfmUV1owWY+BnbL5FxxuatnrU= -github.com/cilium/ebpf v0.5.0/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/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 h1:eIHD9GNM3Hp7kcRW5mvcz7WTR3ETeoYYKwpgA04kaXE= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -371,12 +373,12 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.0.0-rc95 h1:RMuWVfY3E1ILlVsC3RhIq38n4sJtlOFwU9gfFZSqrd0= -github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= +github.com/opencontainers/runc v1.0.1 h1:G18PGckGdAm3yVQRWDVQ1rLSLntiniKJ0cNRT2Tm5gs= +github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.8.0 h1:+77ba4ar4jsCbL1GLbFL8fFM57w6suPfSS9PDLDY7KM= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -418,8 +420,8 @@ 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= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= @@ -454,8 +456,6 @@ github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3C github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmware/govmomi v0.20.3 h1:gpw/0Ku+6RgF3jsi7fnCLmlcikBHfKBCUcu1qgc16OU= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= diff --git a/staging/src/k8s.io/apiextensions-apiserver/go.sum b/staging/src/k8s.io/apiextensions-apiserver/go.sum index ac515006d5d6..4e7435bf857e 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/go.sum +++ b/staging/src/k8s.io/apiextensions-apiserver/go.sum @@ -382,8 +382,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/staging/src/k8s.io/apiserver/go.mod b/staging/src/k8s.io/apiserver/go.mod index 797442c7c95a..d4e58068b14f 100644 --- a/staging/src/k8s.io/apiserver/go.mod +++ b/staging/src/k8s.io/apiserver/go.mod @@ -22,6 +22,7 @@ require ( github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 go.etcd.io/etcd/api/v3 v3.5.0 diff --git a/staging/src/k8s.io/apiserver/go.sum b/staging/src/k8s.io/apiserver/go.sum index f8ac1364726d..9ec78c5c07bf 100644 --- a/staging/src/k8s.io/apiserver/go.sum +++ b/staging/src/k8s.io/apiserver/go.sum @@ -376,8 +376,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/staging/src/k8s.io/cloud-provider/go.sum b/staging/src/k8s.io/cloud-provider/go.sum index 0c49d35f3443..218948a0bc7c 100644 --- a/staging/src/k8s.io/cloud-provider/go.sum +++ b/staging/src/k8s.io/cloud-provider/go.sum @@ -372,8 +372,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/staging/src/k8s.io/controller-manager/go.sum b/staging/src/k8s.io/controller-manager/go.sum index fb877b9a59c5..0a8eedfdf01f 100644 --- a/staging/src/k8s.io/controller-manager/go.sum +++ b/staging/src/k8s.io/controller-manager/go.sum @@ -480,8 +480,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/staging/src/k8s.io/kube-aggregator/go.sum b/staging/src/k8s.io/kube-aggregator/go.sum index d593b65858c4..b38e307e5d20 100644 --- a/staging/src/k8s.io/kube-aggregator/go.sum +++ b/staging/src/k8s.io/kube-aggregator/go.sum @@ -373,8 +373,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/staging/src/k8s.io/kube-controller-manager/go.sum b/staging/src/k8s.io/kube-controller-manager/go.sum index 17f7606d813c..d308f64ffda4 100644 --- a/staging/src/k8s.io/kube-controller-manager/go.sum +++ b/staging/src/k8s.io/kube-controller-manager/go.sum @@ -324,6 +324,7 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/staging/src/k8s.io/legacy-cloud-providers/go.sum b/staging/src/k8s.io/legacy-cloud-providers/go.sum index a4c7ce22d185..d74d52be5d1e 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/go.sum +++ b/staging/src/k8s.io/legacy-cloud-providers/go.sum @@ -380,6 +380,7 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/staging/src/k8s.io/pod-security-admission/go.sum b/staging/src/k8s.io/pod-security-admission/go.sum index 782e4dd8b0dc..4107b91f8952 100644 --- a/staging/src/k8s.io/pod-security-admission/go.sum +++ b/staging/src/k8s.io/pod-security-admission/go.sum @@ -369,8 +369,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/staging/src/k8s.io/sample-apiserver/go.sum b/staging/src/k8s.io/sample-apiserver/go.sum index 56408a03cd06..233f6998543f 100644 --- a/staging/src/k8s.io/sample-apiserver/go.sum +++ b/staging/src/k8s.io/sample-apiserver/go.sum @@ -370,8 +370,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/vendor/github.com/willf/bitset/.gitignore b/vendor/github.com/bits-and-blooms/bitset/.gitignore similarity index 100% rename from vendor/github.com/willf/bitset/.gitignore rename to vendor/github.com/bits-and-blooms/bitset/.gitignore diff --git a/vendor/github.com/willf/bitset/.travis.yml b/vendor/github.com/bits-and-blooms/bitset/.travis.yml similarity index 100% rename from vendor/github.com/willf/bitset/.travis.yml rename to vendor/github.com/bits-and-blooms/bitset/.travis.yml diff --git a/vendor/github.com/willf/bitset/LICENSE b/vendor/github.com/bits-and-blooms/bitset/LICENSE similarity index 100% rename from vendor/github.com/willf/bitset/LICENSE rename to vendor/github.com/bits-and-blooms/bitset/LICENSE diff --git a/vendor/github.com/willf/bitset/README.md b/vendor/github.com/bits-and-blooms/bitset/README.md similarity index 84% rename from vendor/github.com/willf/bitset/README.md rename to vendor/github.com/bits-and-blooms/bitset/README.md index 50338e71dfdb..97e83071e41a 100644 --- a/vendor/github.com/willf/bitset/README.md +++ b/vendor/github.com/bits-and-blooms/bitset/README.md @@ -2,10 +2,9 @@ *Go language library to map between non-negative integers and boolean values* -[![Test](https://github.com/willf/bitset/workflows/Test/badge.svg)](https://github.com/willf/bitset/actions?query=workflow%3ATest) -[![Master Coverage Status](https://coveralls.io/repos/willf/bitset/badge.svg?branch=master&service=github)](https://coveralls.io/github/willf/bitset?branch=master) +[![Test](https://github.com/bits-and-blooms/bitset/workflows/Test/badge.svg)](https://github.com/willf/bitset/actions?query=workflow%3ATest) [![Go Report Card](https://goreportcard.com/badge/github.com/willf/bitset)](https://goreportcard.com/report/github.com/willf/bitset) -[![PkgGoDev](https://pkg.go.dev/badge/github.com/willf/bitset?tab=doc)](https://pkg.go.dev/github.com/willf/bitset?tab=doc) +[![PkgGoDev](https://pkg.go.dev/badge/github.com/bits-and-blooms/bitset?tab=doc)](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc) ## Description @@ -30,7 +29,7 @@ import ( "fmt" "math/rand" - "github.com/willf/bitset" + "github.com/bits-and-blooms/bitset" ) func main() { @@ -63,7 +62,7 @@ func main() { As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets. -Package documentation is at: https://pkg.go.dev/github.com/willf/bitset?tab=doc +Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc ## Memory Usage @@ -78,7 +77,7 @@ It is possible that a later version will match the `math/bits` return signature ## Installation ```bash -go get github.com/willf/bitset +go get github.com/bits-and-blooms/bitset ``` ## Contributing diff --git a/vendor/github.com/willf/bitset/azure-pipelines.yml b/vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml similarity index 100% rename from vendor/github.com/willf/bitset/azure-pipelines.yml rename to vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml diff --git a/vendor/github.com/willf/bitset/bitset.go b/vendor/github.com/bits-and-blooms/bitset/bitset.go similarity index 97% rename from vendor/github.com/willf/bitset/bitset.go rename to vendor/github.com/bits-and-blooms/bitset/bitset.go index 21e889da2e06..d688806a54b8 100644 --- a/vendor/github.com/willf/bitset/bitset.go +++ b/vendor/github.com/bits-and-blooms/bitset/bitset.go @@ -209,6 +209,27 @@ func (b *BitSet) Flip(i uint) *BitSet { return b } +// FlipRange bit in [start, end). +// If end>= Cap(), this function will panic. +// Warning: using a very large value for 'end' +// may lead to a memory shortage and a panic: the caller is responsible +// for providing sensible parameters in line with their memory capacity. +func (b *BitSet) FlipRange(start, end uint) *BitSet { + if start >= end { + return b + } + + b.extendSetMaybe(end - 1) + var startWord uint = start >> log2WordSize + var endWord uint = end >> log2WordSize + b.set[startWord] ^= ^(^uint64(0) << (start & (wordSize - 1))) + for i := startWord; i < endWord; i++ { + b.set[i] = ^b.set[i] + } + b.set[endWord] ^= ^uint64(0) >> (-end & (wordSize - 1)) + return b +} + // Shrink shrinks BitSet so that the provided value is the last possible // set value. It clears all bits > the provided index and reduces the size // and length of the set. @@ -519,7 +540,7 @@ func (b *BitSet) Copy(c *BitSet) (count uint) { } // Count (number of set bits). -// Also known as "popcount" or "popularity count". +// Also known as "popcount" or "population count". func (b *BitSet) Count() uint { if b != nil && b.set != nil { return uint(popcntSlice(b.set)) diff --git a/vendor/github.com/bits-and-blooms/bitset/go.mod b/vendor/github.com/bits-and-blooms/bitset/go.mod new file mode 100644 index 000000000000..c43e4522b7f9 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/go.mod @@ -0,0 +1,3 @@ +module github.com/bits-and-blooms/bitset + +go 1.14 diff --git a/vendor/github.com/willf/bitset/go.sum b/vendor/github.com/bits-and-blooms/bitset/go.sum similarity index 100% rename from vendor/github.com/willf/bitset/go.sum rename to vendor/github.com/bits-and-blooms/bitset/go.sum diff --git a/vendor/github.com/willf/bitset/popcnt.go b/vendor/github.com/bits-and-blooms/bitset/popcnt.go similarity index 100% rename from vendor/github.com/willf/bitset/popcnt.go rename to vendor/github.com/bits-and-blooms/bitset/popcnt.go diff --git a/vendor/github.com/willf/bitset/popcnt_19.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_19.go similarity index 100% rename from vendor/github.com/willf/bitset/popcnt_19.go rename to vendor/github.com/bits-and-blooms/bitset/popcnt_19.go diff --git a/vendor/github.com/willf/bitset/popcnt_amd64.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go similarity index 100% rename from vendor/github.com/willf/bitset/popcnt_amd64.go rename to vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go diff --git a/vendor/github.com/willf/bitset/popcnt_amd64.s b/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s similarity index 100% rename from vendor/github.com/willf/bitset/popcnt_amd64.s rename to vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s diff --git a/vendor/github.com/willf/bitset/popcnt_generic.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go similarity index 100% rename from vendor/github.com/willf/bitset/popcnt_generic.go rename to vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go diff --git a/vendor/github.com/willf/bitset/trailing_zeros_18.go b/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go similarity index 100% rename from vendor/github.com/willf/bitset/trailing_zeros_18.go rename to vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go diff --git a/vendor/github.com/willf/bitset/trailing_zeros_19.go b/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go similarity index 100% rename from vendor/github.com/willf/bitset/trailing_zeros_19.go rename to vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go diff --git a/vendor/github.com/cilium/ebpf/CONTRIBUTING.md b/vendor/github.com/cilium/ebpf/CONTRIBUTING.md index 97c794f3a9b3..72ceb4378297 100644 --- a/vendor/github.com/cilium/ebpf/CONTRIBUTING.md +++ b/vendor/github.com/cilium/ebpf/CONTRIBUTING.md @@ -18,6 +18,23 @@ reason about the proposed changes. ## Running the tests Many of the tests require privileges to set resource limits and load eBPF code. -The easiest way to obtain these is to run the tests with `sudo`: +The easiest way to obtain these is to run the tests with `sudo`. + +To test the current package with your local kernel you can simply run: +``` +go test -exec sudo ./... +``` + +To test the current package with a different kernel version you can use the [run-tests.sh](run-tests.sh) script. +It requires [virtme](https://github.com/amluto/virtme) and qemu to be installed. + +Examples: + +```bash +# 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 +``` - sudo go test ./... \ No newline at end of file diff --git a/vendor/github.com/cilium/ebpf/Makefile b/vendor/github.com/cilium/ebpf/Makefile index 5d4195833cab..5dd342c5b287 100644 --- a/vendor/github.com/cilium/ebpf/Makefile +++ b/vendor/github.com/cilium/ebpf/Makefile @@ -1,7 +1,7 @@ # The development version of clang is distributed as the 'clang' binary, # while stable/released versions have a version number attached. # Pin the default clang to a stable version. -CLANG ?= clang-11 +CLANG ?= clang-12 CFLAGS := -target bpf -O2 -g -Wall -Werror $(CFLAGS) # Obtain an absolute path to the directory of the Makefile. @@ -17,7 +17,7 @@ VERSION := $(shell cat ${REPODIR}/testdata/docker/VERSION) TARGETS := \ testdata/loader-clang-7 \ testdata/loader-clang-9 \ - testdata/loader-clang-11 \ + testdata/loader-$(CLANG) \ testdata/invalid_map \ testdata/raw_tracepoint \ testdata/invalid_map_static \ @@ -33,6 +33,7 @@ TARGETS := \ docker-all: docker run --rm --user "${UIDGID}" \ -v "${REPODIR}":/ebpf -w /ebpf --env MAKEFLAGS \ + --env CFLAGS="-fdebug-prefix-map=/ebpf=." \ "${IMAGE}:${VERSION}" \ make all @@ -47,6 +48,8 @@ clean: -$(RM) internal/btf/testdata/*.elf all: $(addsuffix -el.elf,$(TARGETS)) $(addsuffix -eb.elf,$(TARGETS)) + ln -srf testdata/loader-$(CLANG)-el.elf testdata/loader-el.elf + ln -srf testdata/loader-$(CLANG)-eb.elf testdata/loader-eb.elf testdata/loader-%-el.elf: testdata/loader.c $* $(CFLAGS) -mlittle-endian -c $< -o $@ diff --git a/vendor/github.com/cilium/ebpf/asm/func.go b/vendor/github.com/cilium/ebpf/asm/func.go index 1d77745450b4..aee2c7ac8106 100644 --- a/vendor/github.com/cilium/ebpf/asm/func.go +++ b/vendor/github.com/cilium/ebpf/asm/func.go @@ -132,6 +132,58 @@ const ( FnSkStorageDelete FnSendSignal FnTcpGenSyncookie + FnSkbOutput + FnProbeReadUser + FnProbeReadKernel + FnProbeReadUserStr + FnProbeReadKernelStr + FnTcpSendAck + FnSendSignalThread + FnJiffies64 + FnReadBranchRecords + FnGetNsCurrentPidTgid + FnXdpOutput + FnGetNetnsCookie + FnGetCurrentAncestorCgroupId + FnSkAssign + FnKtimeGetBootNs + FnSeqPrintf + FnSeqWrite + FnSkCgroupId + FnSkAncestorCgroupId + FnRingbufOutput + FnRingbufReserve + FnRingbufSubmit + FnRingbufDiscard + FnRingbufQuery + FnCsumLevel + FnSkcToTcp6Sock + FnSkcToTcpSock + FnSkcToTcpTimewaitSock + FnSkcToTcpRequestSock + FnSkcToUdp6Sock + FnGetTaskStack + FnLoadHdrOpt + FnStoreHdrOpt + FnReserveHdrOpt + FnInodeStorageGet + FnInodeStorageDelete + FnDPath + FnCopyFromUser + FnSnprintfBtf + FnSeqPrintfBtf + FnSkbCgroupClassid + FnRedirectNeigh + FnPerCpuPtr + FnThisCpuPtr + FnRedirectPeer + FnTaskStorageGet + FnTaskStorageDelete + FnGetCurrentTaskBtf + FnBprmOptsSet + FnKtimeGetCoarseNs + FnImaInodeHash + FnSockFromFile ) // 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 8860b9fdb42b..a712c5da8af9 100644 --- a/vendor/github.com/cilium/ebpf/asm/func_string.go +++ b/vendor/github.com/cilium/ebpf/asm/func_string.go @@ -119,11 +119,63 @@ func _() { _ = x[FnSkStorageDelete-108] _ = x[FnSendSignal-109] _ = x[FnTcpGenSyncookie-110] + _ = x[FnSkbOutput-111] + _ = x[FnProbeReadUser-112] + _ = x[FnProbeReadKernel-113] + _ = x[FnProbeReadUserStr-114] + _ = x[FnProbeReadKernelStr-115] + _ = x[FnTcpSendAck-116] + _ = x[FnSendSignalThread-117] + _ = x[FnJiffies64-118] + _ = x[FnReadBranchRecords-119] + _ = x[FnGetNsCurrentPidTgid-120] + _ = x[FnXdpOutput-121] + _ = x[FnGetNetnsCookie-122] + _ = x[FnGetCurrentAncestorCgroupId-123] + _ = x[FnSkAssign-124] + _ = x[FnKtimeGetBootNs-125] + _ = x[FnSeqPrintf-126] + _ = x[FnSeqWrite-127] + _ = x[FnSkCgroupId-128] + _ = x[FnSkAncestorCgroupId-129] + _ = x[FnRingbufOutput-130] + _ = x[FnRingbufReserve-131] + _ = x[FnRingbufSubmit-132] + _ = x[FnRingbufDiscard-133] + _ = x[FnRingbufQuery-134] + _ = x[FnCsumLevel-135] + _ = x[FnSkcToTcp6Sock-136] + _ = x[FnSkcToTcpSock-137] + _ = x[FnSkcToTcpTimewaitSock-138] + _ = x[FnSkcToTcpRequestSock-139] + _ = x[FnSkcToUdp6Sock-140] + _ = x[FnGetTaskStack-141] + _ = x[FnLoadHdrOpt-142] + _ = x[FnStoreHdrOpt-143] + _ = x[FnReserveHdrOpt-144] + _ = x[FnInodeStorageGet-145] + _ = x[FnInodeStorageDelete-146] + _ = x[FnDPath-147] + _ = x[FnCopyFromUser-148] + _ = x[FnSnprintfBtf-149] + _ = x[FnSeqPrintfBtf-150] + _ = x[FnSkbCgroupClassid-151] + _ = x[FnRedirectNeigh-152] + _ = x[FnPerCpuPtr-153] + _ = x[FnThisCpuPtr-154] + _ = x[FnRedirectPeer-155] + _ = x[FnTaskStorageGet-156] + _ = x[FnTaskStorageDelete-157] + _ = x[FnGetCurrentTaskBtf-158] + _ = x[FnBprmOptsSet-159] + _ = x[FnKtimeGetCoarseNs-160] + _ = x[FnImaInodeHash-161] + _ = x[FnSockFromFile-162] } -const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookie" +const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFile" -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} +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} 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 f09b083efb9c..e7ac0109e2dc 100644 --- a/vendor/github.com/cilium/ebpf/asm/instruction.go +++ b/vendor/github.com/cilium/ebpf/asm/instruction.go @@ -57,7 +57,7 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err return 0, fmt.Errorf("can't unmarshal registers: %s", err) } - if !bi.OpCode.isDWordLoad() { + if !bi.OpCode.IsDWordLoad() { return InstructionSize, nil } @@ -80,7 +80,7 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error) return 0, errors.New("invalid opcode") } - isDWordLoad := ins.OpCode.isDWordLoad() + isDWordLoad := ins.OpCode.IsDWordLoad() cons := int32(ins.Constant) if isDWordLoad { @@ -123,7 +123,7 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error) // // Returns an error if the instruction doesn't load a map. func (ins *Instruction) RewriteMapPtr(fd int) error { - if !ins.OpCode.isDWordLoad() { + if !ins.OpCode.IsDWordLoad() { return fmt.Errorf("%s is not a 64 bit load", ins.OpCode) } @@ -138,15 +138,19 @@ func (ins *Instruction) RewriteMapPtr(fd int) error { return nil } -func (ins *Instruction) mapPtr() uint32 { - return uint32(uint64(ins.Constant) & math.MaxUint32) +// MapPtr returns the map fd for this instruction. +// +// The result is undefined if the instruction is not a load from a map, +// see IsLoadFromMap. +func (ins *Instruction) MapPtr() int { + return int(int32(uint64(ins.Constant) & math.MaxUint32)) } // RewriteMapOffset changes the offset of a direct load from a map. // // Returns an error if the instruction is not a direct load. func (ins *Instruction) RewriteMapOffset(offset uint32) error { - if !ins.OpCode.isDWordLoad() { + if !ins.OpCode.IsDWordLoad() { return fmt.Errorf("%s is not a 64 bit load", ins.OpCode) } @@ -163,10 +167,10 @@ func (ins *Instruction) mapOffset() uint32 { return uint32(uint64(ins.Constant) >> 32) } -// isLoadFromMap returns true if the instruction loads from a map. +// IsLoadFromMap returns true if the instruction loads from a map. // // This covers both loading the map pointer and direct map value loads. -func (ins *Instruction) isLoadFromMap() bool { +func (ins *Instruction) IsLoadFromMap() bool { return ins.OpCode == LoadImmOp(DWord) && (ins.Src == PseudoMapFD || ins.Src == PseudoMapValue) } @@ -177,6 +181,12 @@ func (ins *Instruction) IsFunctionCall() bool { return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall } +// IsConstantLoad returns true if the instruction loads a constant of the +// given size. +func (ins *Instruction) IsConstantLoad(size Size) bool { + return ins.OpCode == LoadImmOp(size) && ins.Src == R0 && ins.Offset == 0 +} + // Format implements fmt.Formatter. func (ins Instruction) Format(f fmt.State, c rune) { if c != 'v' { @@ -197,8 +207,8 @@ func (ins Instruction) Format(f fmt.State, c rune) { return } - if ins.isLoadFromMap() { - fd := int32(ins.mapPtr()) + if ins.IsLoadFromMap() { + fd := ins.MapPtr() switch ins.Src { case PseudoMapFD: fmt.Fprintf(f, "LoadMapPtr dst: %s fd: %d", ins.Dst, fd) @@ -403,7 +413,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error { func (insns Instructions) Tag(bo binary.ByteOrder) (string, error) { h := sha1.New() for i, ins := range insns { - if ins.isLoadFromMap() { + if ins.IsLoadFromMap() { ins.Constant = 0 } _, err := ins.Marshal(h, bo) diff --git a/vendor/github.com/cilium/ebpf/asm/load_store.go b/vendor/github.com/cilium/ebpf/asm/load_store.go index 2d0ec648e881..85ed286b02b0 100644 --- a/vendor/github.com/cilium/ebpf/asm/load_store.go +++ b/vendor/github.com/cilium/ebpf/asm/load_store.go @@ -111,7 +111,7 @@ func LoadMapPtr(dst Register, fd int) Instruction { OpCode: LoadImmOp(DWord), Dst: dst, Src: PseudoMapFD, - Constant: int64(fd), + Constant: int64(uint32(fd)), } } diff --git a/vendor/github.com/cilium/ebpf/asm/opcode.go b/vendor/github.com/cilium/ebpf/asm/opcode.go index dc4564a98d20..6edc3cf5917d 100644 --- a/vendor/github.com/cilium/ebpf/asm/opcode.go +++ b/vendor/github.com/cilium/ebpf/asm/opcode.go @@ -69,13 +69,13 @@ const InvalidOpCode OpCode = 0xff // rawInstructions returns the number of BPF instructions required // to encode this opcode. func (op OpCode) rawInstructions() int { - if op.isDWordLoad() { + if op.IsDWordLoad() { return 2 } return 1 } -func (op OpCode) isDWordLoad() bool { +func (op OpCode) IsDWordLoad() bool { return op == LoadImmOp(DWord) } diff --git a/vendor/github.com/cilium/ebpf/collection.go b/vendor/github.com/cilium/ebpf/collection.go index 8e362900326f..17cc69492ea9 100644 --- a/vendor/github.com/cilium/ebpf/collection.go +++ b/vendor/github.com/cilium/ebpf/collection.go @@ -3,6 +3,7 @@ package ebpf import ( "errors" "fmt" + "io" "math" "reflect" "strings" @@ -89,8 +90,8 @@ func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error { // // The constant must be defined like so in the C program: // -// static volatile const type foobar; -// static volatile const type foobar = default; +// volatile const type foobar; +// volatile const type foobar = default; // // Replacement values must be of the same length as the C sizeof(type). // If necessary, they are marshalled according to the same rules as @@ -269,11 +270,21 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co }, nil } -type btfHandleCache map[*btf.Spec]*btf.Handle +type handleCache struct { + btfHandles map[*btf.Spec]*btf.Handle + btfSpecs map[io.ReaderAt]*btf.Spec +} + +func newHandleCache() *handleCache { + return &handleCache{ + btfHandles: make(map[*btf.Spec]*btf.Handle), + btfSpecs: make(map[io.ReaderAt]*btf.Spec), + } +} -func (btfs btfHandleCache) load(spec *btf.Spec) (*btf.Handle, error) { - if btfs[spec] != nil { - return btfs[spec], nil +func (hc handleCache) btfHandle(spec *btf.Spec) (*btf.Handle, error) { + if hc.btfHandles[spec] != nil { + return hc.btfHandles[spec], nil } handle, err := btf.NewHandle(spec) @@ -281,14 +292,30 @@ func (btfs btfHandleCache) load(spec *btf.Spec) (*btf.Handle, error) { return nil, err } - btfs[spec] = handle + hc.btfHandles[spec] = handle return handle, nil } -func (btfs btfHandleCache) close() { - for _, handle := range btfs { +func (hc handleCache) btfSpec(rd io.ReaderAt) (*btf.Spec, error) { + if hc.btfSpecs[rd] != nil { + return hc.btfSpecs[rd], nil + } + + spec, err := btf.LoadSpecFromReader(rd) + if err != nil { + return nil, err + } + + hc.btfSpecs[rd] = spec + return spec, nil +} + +func (hc handleCache) close() { + for _, handle := range hc.btfHandles { handle.Close() } + hc.btfHandles = nil + hc.btfSpecs = nil } func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) ( @@ -300,12 +327,12 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) ( var ( maps = make(map[string]*Map) progs = make(map[string]*Program) - btfs = make(btfHandleCache) + handles = newHandleCache() skipMapsAndProgs = false ) cleanup = func() { - btfs.close() + handles.close() if skipMapsAndProgs { return @@ -335,7 +362,7 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) ( return nil, fmt.Errorf("missing map %s", mapName) } - m, err := newMapWithOptions(mapSpec, opts.Maps, btfs) + m, err := newMapWithOptions(mapSpec, opts.Maps, handles) if err != nil { return nil, fmt.Errorf("map %s: %w", mapName, err) } @@ -360,7 +387,7 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) ( for i := range progSpec.Instructions { ins := &progSpec.Instructions[i] - if ins.OpCode != asm.LoadImmOp(asm.DWord) || ins.Reference == "" { + if !ins.IsLoadFromMap() || ins.Reference == "" { continue } @@ -372,7 +399,7 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) ( m, err := loadMap(ins.Reference) if err != nil { - return nil, fmt.Errorf("program %s: %s", progName, err) + return nil, fmt.Errorf("program %s: %w", progName, err) } fd := m.FD() @@ -384,7 +411,7 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) ( } } - prog, err := newProgramWithOptions(progSpec, opts.Programs, btfs) + prog, err := newProgramWithOptions(progSpec, opts.Programs, handles) if err != nil { return nil, fmt.Errorf("program %s: %w", progName, err) } @@ -534,7 +561,7 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va } if err != nil { - return fmt.Errorf("field %s: %s", field.Name, err) + return fmt.Errorf("field %s: %w", field.Name, err) } } diff --git a/vendor/github.com/cilium/ebpf/elf_reader.go b/vendor/github.com/cilium/ebpf/elf_reader.go index 3ae44f68f424..c2afbc36a5a9 100644 --- a/vendor/github.com/cilium/ebpf/elf_reader.go +++ b/vendor/github.com/cilium/ebpf/elf_reader.go @@ -96,7 +96,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { } btfSpec, err := btf.LoadSpecFromReader(rd) - if err != nil { + if err != nil && !errors.Is(err, btf.ErrNotFound) { return nil, fmt.Errorf("load BTF: %w", err) } @@ -159,7 +159,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { } if target.Flags&elf.SHF_STRINGS > 0 { - return nil, fmt.Errorf("section %q: string %q is not stack allocated: %w", section.Name, rel.Name, ErrNotSupported) + return nil, fmt.Errorf("section %q: string is not stack allocated: %w", section.Name, ErrNotSupported) } target.references++ @@ -374,17 +374,25 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err } case dataSection: + var offset uint32 switch typ { case elf.STT_SECTION: if bind != elf.STB_LOCAL { return fmt.Errorf("direct load: %s: unsupported relocation %s", name, bind) } + // This is really a reference to a static symbol, which clang doesn't + // emit a symbol table entry for. Instead it encodes the offset in + // the instruction itself. + offset = uint32(uint64(ins.Constant)) + case elf.STT_OBJECT: if bind != elf.STB_GLOBAL { return fmt.Errorf("direct load: %s: unsupported relocation %s", name, bind) } + offset = uint32(rel.Value) + default: return fmt.Errorf("incorrect relocation type %v for direct map load", typ) } @@ -394,10 +402,8 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err // it's not clear how to encode that into Instruction. name = target.Name - // For some reason, clang encodes the offset of the symbol its - // section in the first basic BPF instruction, while the kernel - // expects it in the second one. - ins.Constant <<= 32 + // The kernel expects the offset in the second basic BPF instruction. + ins.Constant = int64(uint64(offset) << 32) ins.Src = asm.PseudoMapValue // Mark the instruction as needing an update when creating the @@ -491,33 +497,38 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error { return fmt.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset) } - if maps[mapSym.Name] != nil { + mapName := mapSym.Name + if maps[mapName] != nil { return fmt.Errorf("section %v: map %v already exists", sec.Name, mapSym) } lr := io.LimitReader(r, int64(size)) spec := MapSpec{ - Name: SanitizeName(mapSym.Name, -1), + Name: SanitizeName(mapName, -1), } switch { case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil: - return fmt.Errorf("map %v: missing type", mapSym) + return fmt.Errorf("map %s: missing type", mapName) case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil: - return fmt.Errorf("map %v: missing key size", mapSym) + return fmt.Errorf("map %s: missing key size", mapName) case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil: - return fmt.Errorf("map %v: missing value size", mapSym) + return fmt.Errorf("map %s: missing value size", mapName) case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil: - return fmt.Errorf("map %v: missing max entries", mapSym) + return fmt.Errorf("map %s: missing max entries", mapName) case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil: - return fmt.Errorf("map %v: missing flags", mapSym) + return fmt.Errorf("map %s: missing flags", mapName) } if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil { - return fmt.Errorf("map %v: unknown and non-zero fields in definition", mapSym) + return fmt.Errorf("map %s: unknown and non-zero fields in definition", mapName) + } + + if err := spec.clampPerfEventArraySize(); err != nil { + return fmt.Errorf("map %s: %w", mapName, err) } - maps[mapSym.Name] = &spec + maps[mapName] = &spec } } @@ -565,6 +576,10 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error { return fmt.Errorf("map %v: %w", name, err) } + if err := mapSpec.clampPerfEventArraySize(); err != nil { + return fmt.Errorf("map %v: %w", name, err) + } + maps[name] = mapSpec } } @@ -847,6 +862,8 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) { "uretprobe/": {Kprobe, AttachNone, 0}, "tracepoint/": {TracePoint, AttachNone, 0}, "raw_tracepoint/": {RawTracepoint, AttachNone, 0}, + "raw_tp/": {RawTracepoint, AttachNone, 0}, + "tp_btf/": {Tracing, AttachTraceRawTp, 0}, "xdp": {XDP, AttachNone, 0}, "perf_event": {PerfEvent, AttachNone, 0}, "lwt_in": {LWTIn, AttachNone, 0}, @@ -860,6 +877,9 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) { "lirc_mode2": {LircMode2, AttachLircMode2, 0}, "flow_dissector": {FlowDissector, AttachFlowDissector, 0}, "iter/": {Tracing, AttachTraceIter, 0}, + "fentry/": {Tracing, AttachTraceFEntry, 0}, + "fmod_ret/": {Tracing, AttachModifyReturn, 0}, + "fexit/": {Tracing, AttachTraceFExit, 0}, "fentry.s/": {Tracing, AttachTraceFEntry, unix.BPF_F_SLEEPABLE}, "fmod_ret.s/": {Tracing, AttachModifyReturn, unix.BPF_F_SLEEPABLE}, "fexit.s/": {Tracing, AttachTraceFExit, unix.BPF_F_SLEEPABLE}, diff --git a/vendor/github.com/cilium/ebpf/internal/btf/btf.go b/vendor/github.com/cilium/ebpf/internal/btf/btf.go index 1e66d94765a1..5da9e11921a3 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/btf.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/btf.go @@ -35,7 +35,7 @@ type Spec struct { namedTypes map[string][]namedType funcInfos map[string]extInfo lineInfos map[string]extInfo - coreRelos map[string]bpfCoreRelos + coreRelos map[string]coreRelos byteOrder binary.ByteOrder } @@ -53,7 +53,7 @@ type btfHeader struct { // LoadSpecFromReader reads BTF sections from an ELF. // -// Returns a nil Spec and no error if no BTF was present. +// Returns ErrNotFound if the reader contains no BTF. func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { file, err := internal.NewSafeELFFile(rd) if err != nil { @@ -67,7 +67,7 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { } if btfSection == nil { - return nil, nil + return nil, fmt.Errorf("btf: %w", ErrNotFound) } symbols, err := file.Symbols() @@ -377,7 +377,7 @@ func (s *Spec) marshal(opts marshalOpts) ([]byte, error) { for _, raw := range s.rawTypes { switch { case opts.StripFuncLinkage && raw.Kind() == kindFunc: - raw.SetLinkage(linkageStatic) + raw.SetLinkage(StaticFunc) } if err := raw.Marshal(&buf, opts.ByteOrder); err != nil { @@ -438,13 +438,13 @@ func (s *Spec) Program(name string, length uint64) (*Program, error) { funcInfos, funcOK := s.funcInfos[name] lineInfos, lineOK := s.lineInfos[name] - coreRelos, coreOK := s.coreRelos[name] + relos, coreOK := s.coreRelos[name] if !funcOK && !lineOK && !coreOK { return nil, fmt.Errorf("no extended BTF info for section %s", name) } - return &Program{s, length, funcInfos, lineInfos, coreRelos}, nil + return &Program{s, length, funcInfos, lineInfos, relos}, nil } // Datasec returns the BTF required to create maps which represent data sections. @@ -491,7 +491,8 @@ func (s *Spec) FindType(name string, typ Type) error { return fmt.Errorf("type %s: %w", name, ErrNotFound) } - value := reflect.Indirect(reflect.ValueOf(copyType(candidate))) + cpy, _ := copyType(candidate, nil) + value := reflect.Indirect(reflect.ValueOf(cpy)) reflect.Indirect(reflect.ValueOf(typ)).Set(value) return nil } @@ -606,7 +607,7 @@ type Program struct { spec *Spec length uint64 funcInfos, lineInfos extInfo - coreRelos bpfCoreRelos + coreRelos coreRelos } // ProgramSpec returns the Spec needed for loading function and line infos into the kernel. @@ -665,16 +666,23 @@ func ProgramLineInfos(s *Program) (recordSize uint32, bytes []byte, err error) { return s.lineInfos.recordSize, bytes, nil } -// ProgramRelocations returns the CO-RE relocations required to adjust the -// program to the target. +// ProgramFixups 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 ProgramRelocations(s *Program, target *Spec) (map[uint64]Relocation, error) { +func ProgramFixups(s *Program, target *Spec) (COREFixups, error) { if len(s.coreRelos) == 0 { return nil, nil } + if target == nil { + var err error + target, err = LoadKernelSpec() + if err != nil { + return nil, err + } + } + return coreRelocate(s.spec, target, s.coreRelos) } @@ -771,7 +779,7 @@ var haveFuncLinkage = internal.FeatureTest("BTF func linkage", "5.6", func() err types.Func.SetKind(kindFunc) types.Func.SizeType = 1 // aka FuncProto types.Func.NameOff = 1 - types.Func.SetLinkage(linkageGlobal) + types.Func.SetLinkage(GlobalFunc) btf := marshalBTF(&types, strings, internal.NativeEndian) 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 6d75cd6c0321..a5ef94512013 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go @@ -6,6 +6,8 @@ import ( "io" ) +//go:generate stringer -linecomment -output=btf_types_string.go -type=FuncLinkage,VarLinkage + // btfKind describes a Type. type btfKind uint8 @@ -31,14 +33,23 @@ const ( kindDatasec ) -// btfFuncLinkage describes BTF function linkage metadata. -type btfFuncLinkage uint8 +// FuncLinkage describes BTF function linkage metadata. +type FuncLinkage int // Equivalent of enum btf_func_linkage. const ( - linkageStatic btfFuncLinkage = iota - linkageGlobal - // linkageExtern // Currently unused in libbpf. + StaticFunc FuncLinkage = iota // static + GlobalFunc // global + ExternFunc // extern +) + +// VarLinkage describes BTF variable linkage metadata. +type VarLinkage int + +const ( + StaticVar VarLinkage = iota // static + GlobalVar // global + ExternVar // extern ) const ( @@ -144,11 +155,11 @@ func (bt *btfType) KindFlag() bool { return bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift) == 1 } -func (bt *btfType) Linkage() btfFuncLinkage { - return btfFuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift)) +func (bt *btfType) Linkage() FuncLinkage { + return FuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift)) } -func (bt *btfType) SetLinkage(linkage btfFuncLinkage) { +func (bt *btfType) SetLinkage(linkage FuncLinkage) { bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift) } diff --git a/vendor/github.com/cilium/ebpf/internal/btf/btf_types_string.go b/vendor/github.com/cilium/ebpf/internal/btf/btf_types_string.go new file mode 100644 index 000000000000..0e0c17d68ba9 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/btf/btf_types_string.go @@ -0,0 +1,44 @@ +// Code generated by "stringer -linecomment -output=btf_types_string.go -type=FuncLinkage,VarLinkage"; DO NOT EDIT. + +package btf + +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[StaticFunc-0] + _ = x[GlobalFunc-1] + _ = x[ExternFunc-2] +} + +const _FuncLinkage_name = "staticglobalextern" + +var _FuncLinkage_index = [...]uint8{0, 6, 12, 18} + +func (i FuncLinkage) String() string { + if i < 0 || i >= FuncLinkage(len(_FuncLinkage_index)-1) { + return "FuncLinkage(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _FuncLinkage_name[_FuncLinkage_index[i]:_FuncLinkage_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[StaticVar-0] + _ = x[GlobalVar-1] + _ = x[ExternVar-2] +} + +const _VarLinkage_name = "staticglobalextern" + +var _VarLinkage_index = [...]uint8{0, 6, 12, 18} + +func (i VarLinkage) String() string { + if i < 0 || i >= VarLinkage(len(_VarLinkage_index)-1) { + return "VarLinkage(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _VarLinkage_name[_VarLinkage_index[i]:_VarLinkage_index[i+1]] +} diff --git a/vendor/github.com/cilium/ebpf/internal/btf/core.go b/vendor/github.com/cilium/ebpf/internal/btf/core.go index 52b59ed189f4..7c888f602d0d 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/core.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/core.go @@ -3,43 +3,160 @@ package btf import ( "errors" "fmt" + "math" "reflect" + "sort" "strconv" "strings" + + "github.com/cilium/ebpf/asm" ) // Code in this file is derived from libbpf, which is available under a BSD // 2-Clause license. -// Relocation describes a CO-RE relocation. -type Relocation struct { - Current uint32 - New uint32 +// COREFixup is the result of computing a CO-RE relocation for a target. +type COREFixup struct { + Kind COREKind + Local uint32 + Target uint32 + Poison bool +} + +func (f COREFixup) equal(other COREFixup) bool { + return f.Local == other.Local && f.Target == other.Target +} + +func (f COREFixup) String() string { + if f.Poison { + return fmt.Sprintf("%s=poison", f.Kind) + } + return fmt.Sprintf("%s=%d->%d", f.Kind, f.Local, f.Target) +} + +func (f COREFixup) apply(ins *asm.Instruction) error { + if f.Poison { + return errors.New("can't poison individual instruction") + } + + switch class := ins.OpCode.Class(); class { + case asm.LdXClass, asm.StClass, asm.StXClass: + if want := int16(f.Local); want != ins.Offset { + return fmt.Errorf("invalid offset %d, expected %d", ins.Offset, want) + } + + if f.Target > math.MaxInt16 { + return fmt.Errorf("offset %d exceeds MaxInt16", f.Target) + } + + ins.Offset = int16(f.Target) + + case asm.LdClass: + if !ins.IsConstantLoad(asm.DWord) { + return fmt.Errorf("not a dword-sized immediate load") + } + + if want := int64(f.Local); want != ins.Constant { + return fmt.Errorf("invalid immediate %d, expected %d", ins.Constant, want) + } + + ins.Constant = int64(f.Target) + + case asm.ALUClass: + if ins.OpCode.ALUOp() == asm.Swap { + return fmt.Errorf("relocation against swap") + } + + fallthrough + + case asm.ALU64Class: + if src := ins.OpCode.Source(); src != asm.ImmSource { + return fmt.Errorf("invalid source %s", src) + } + + if want := int64(f.Local); want != ins.Constant { + return fmt.Errorf("invalid immediate %d, expected %d", ins.Constant, want) + } + + if f.Target > math.MaxInt32 { + return fmt.Errorf("immediate %d exceeds MaxInt32", f.Target) + } + + ins.Constant = int64(f.Target) + + default: + return fmt.Errorf("invalid class %s", class) + } + + return nil } -func (r Relocation) equal(other Relocation) bool { - return r.Current == other.Current && r.New == other.New +func (f COREFixup) isNonExistant() bool { + return f.Kind.checksForExistence() && f.Target == 0 } -// coreReloKind is the type of CO-RE relocation -type coreReloKind uint32 +type COREFixups map[uint64]COREFixup + +// Apply a set of CO-RE relocations to a BPF program. +func (fs COREFixups) Apply(insns asm.Instructions) (asm.Instructions, error) { + if len(fs) == 0 { + cpy := make(asm.Instructions, len(insns)) + copy(cpy, insns) + return insns, nil + } + + cpy := make(asm.Instructions, 0, len(insns)) + iter := insns.Iterate() + for iter.Next() { + fixup, ok := fs[iter.Offset.Bytes()] + if !ok { + cpy = append(cpy, *iter.Ins) + continue + } + + ins := *iter.Ins + if fixup.Poison { + const badRelo = asm.BuiltinFunc(0xbad2310) + + cpy = append(cpy, badRelo.Call()) + if ins.OpCode.IsDWordLoad() { + // 64 bit constant loads occupy two raw bpf instructions, so + // we need to add another instruction as padding. + cpy = append(cpy, badRelo.Call()) + } + + continue + } + + if err := fixup.apply(&ins); err != nil { + return nil, fmt.Errorf("instruction %d, offset %d: %s: %w", iter.Index, iter.Offset.Bytes(), fixup.Kind, err) + } + + cpy = append(cpy, ins) + } + + return cpy, nil +} + +// COREKind is the type of CO-RE relocation +type COREKind uint32 const ( - reloFieldByteOffset coreReloKind = iota /* field byte offset */ - reloFieldByteSize /* field size in bytes */ - reloFieldExists /* field existence in target kernel */ - reloFieldSigned /* field signedness (0 - unsigned, 1 - signed) */ - reloFieldLShiftU64 /* bitfield-specific left bitshift */ - reloFieldRShiftU64 /* bitfield-specific right bitshift */ - reloTypeIDLocal /* type ID in local BPF object */ - reloTypeIDTarget /* type ID in target kernel */ - reloTypeExists /* type existence in target kernel */ - reloTypeSize /* type size in bytes */ - reloEnumvalExists /* enum value existence in target kernel */ - reloEnumvalValue /* enum value integer value */ + reloFieldByteOffset COREKind = iota /* field byte offset */ + reloFieldByteSize /* field size in bytes */ + reloFieldExists /* field existence in target kernel */ + reloFieldSigned /* field signedness (0 - unsigned, 1 - signed) */ + reloFieldLShiftU64 /* bitfield-specific left bitshift */ + reloFieldRShiftU64 /* bitfield-specific right bitshift */ + reloTypeIDLocal /* type ID in local BPF object */ + reloTypeIDTarget /* type ID in target kernel */ + reloTypeExists /* type existence in target kernel */ + reloTypeSize /* type size in bytes */ + reloEnumvalExists /* enum value existence in target kernel */ + reloEnumvalValue /* enum value integer value */ ) -func (k coreReloKind) String() string { +func (k COREKind) String() string { switch k { case reloFieldByteOffset: return "byte_off" @@ -70,103 +187,249 @@ func (k coreReloKind) String() string { } } -func coreRelocate(local, target *Spec, coreRelos bpfCoreRelos) (map[uint64]Relocation, error) { - if target == nil { - var err error - target, err = loadKernelSpec() - if err != nil { - return nil, err - } - } +func (k COREKind) checksForExistence() bool { + return k == reloEnumvalExists || k == reloTypeExists || k == reloFieldExists +} +func coreRelocate(local, target *Spec, relos coreRelos) (COREFixups, error) { if local.byteOrder != target.byteOrder { return nil, fmt.Errorf("can't relocate %s against %s", local.byteOrder, target.byteOrder) } - relocations := make(map[uint64]Relocation, len(coreRelos)) - for _, relo := range coreRelos { - accessorStr, err := local.strings.Lookup(relo.AccessStrOff) - if err != nil { - return nil, err + var ids []TypeID + relosByID := make(map[TypeID]coreRelos) + result := make(COREFixups, len(relos)) + for _, relo := range relos { + if relo.kind == reloTypeIDLocal { + // Filtering out reloTypeIDLocal here makes our lives a lot easier + // down the line, since it doesn't have a target at all. + if len(relo.accessor) > 1 || relo.accessor[0] != 0 { + return nil, fmt.Errorf("%s: unexpected accessor %v", relo.kind, relo.accessor) + } + + result[uint64(relo.insnOff)] = COREFixup{ + relo.kind, + uint32(relo.typeID), + uint32(relo.typeID), + false, + } + continue } - accessor, err := parseCoreAccessor(accessorStr) + relos, ok := relosByID[relo.typeID] + if !ok { + ids = append(ids, relo.typeID) + } + relosByID[relo.typeID] = append(relos, relo) + } + + // Ensure we work on relocations in a deterministic order. + sort.Slice(ids, func(i, j int) bool { + return ids[i] < ids[j] + }) + + for _, id := range ids { + if int(id) >= len(local.types) { + return nil, fmt.Errorf("invalid type id %d", id) + } + + localType := local.types[id] + named, ok := localType.(namedType) + if !ok || named.name() == "" { + return nil, fmt.Errorf("relocate unnamed or anonymous type %s: %w", localType, ErrNotSupported) + } + + relos := relosByID[id] + targets := target.namedTypes[named.essentialName()] + fixups, err := coreCalculateFixups(localType, targets, relos) if err != nil { - return nil, fmt.Errorf("accessor %q: %s", accessorStr, err) + return nil, fmt.Errorf("relocate %s: %w", localType, err) } - if int(relo.TypeID) >= len(local.types) { - return nil, fmt.Errorf("invalid type id %d", relo.TypeID) + for i, relo := range relos { + result[uint64(relo.insnOff)] = fixups[i] } + } - typ := local.types[relo.TypeID] + return result, nil +} + +var errAmbiguousRelocation = errors.New("ambiguous relocation") +var errImpossibleRelocation = errors.New("impossible relocation") + +// coreCalculateFixups calculates the fixups for the given relocations using +// the "best" target. +// +// 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) { + localID := local.ID() + local, err := copyType(local, skipQualifierAndTypedef) + if err != nil { + return nil, err + } + + bestScore := len(relos) + var bestFixups []COREFixup + for i := range targets { + targetID := targets[i].ID() + target, err := copyType(targets[i], skipQualifierAndTypedef) + if err != nil { + return nil, err + } - if relo.ReloKind == reloTypeIDLocal { - relocations[uint64(relo.InsnOff)] = Relocation{ - uint32(typ.ID()), - uint32(typ.ID()), + score := 0 // lower is better + fixups := make([]COREFixup, 0, len(relos)) + for _, relo := range relos { + fixup, err := coreCalculateFixup(local, localID, target, targetID, relo) + if err != nil { + return nil, fmt.Errorf("target %s: %w", target, err) + } + if fixup.Poison || fixup.isNonExistant() { + score++ } + fixups = append(fixups, fixup) + } + + if score > bestScore { + // We have a better target already, ignore this one. continue } - named, ok := typ.(namedType) - if !ok || named.name() == "" { - return nil, fmt.Errorf("relocate anonymous type %s: %w", typ.String(), ErrNotSupported) + if score < bestScore { + // This is the best target yet, use it. + bestScore = score + bestFixups = fixups + continue } - name := essentialName(named.name()) - res, err := coreCalculateRelocation(typ, target.namedTypes[name], relo.ReloKind, accessor) - if err != nil { - return nil, fmt.Errorf("relocate %s: %w", name, err) + // Some other target has the same score as the current one. Make sure + // the fixups agree with each other. + for i, fixup := range bestFixups { + if !fixup.equal(fixups[i]) { + return nil, fmt.Errorf("%s: multiple types match: %w", fixup.Kind, errAmbiguousRelocation) + } } + } - relocations[uint64(relo.InsnOff)] = res + if bestFixups == nil { + // Nothing at all matched, probably because there are no suitable + // targets at all. Poison everything! + bestFixups = make([]COREFixup, len(relos)) + for i, relo := range relos { + bestFixups[i] = COREFixup{Kind: relo.kind, Poison: true} + } } - return relocations, nil + return bestFixups, nil } -var errAmbiguousRelocation = errors.New("ambiguous relocation") +// coreCalculateFixup calculates the fixup for a single local type, target type +// and relocation. +func coreCalculateFixup(local Type, localID TypeID, target Type, targetID TypeID, relo coreRelo) (COREFixup, error) { + fixup := func(local, target uint32) (COREFixup, error) { + return COREFixup{relo.kind, local, target, false}, nil + } + poison := func() (COREFixup, error) { + if relo.kind.checksForExistence() { + return fixup(1, 0) + } + return COREFixup{relo.kind, 0, 0, true}, nil + } + zero := COREFixup{} + + switch relo.kind { + case reloTypeIDTarget, reloTypeSize, reloTypeExists: + if len(relo.accessor) > 1 || relo.accessor[0] != 0 { + return zero, fmt.Errorf("%s: unexpected accessor %v", relo.kind, relo.accessor) + } + + err := coreAreTypesCompatible(local, target) + if errors.Is(err, errImpossibleRelocation) { + return poison() + } + if err != nil { + return zero, fmt.Errorf("relocation %s: %w", relo.kind, err) + } + + switch relo.kind { + case reloTypeExists: + return fixup(1, 1) -func coreCalculateRelocation(local Type, targets []namedType, kind coreReloKind, localAccessor coreAccessor) (Relocation, error) { - var relos []Relocation - var matches []Type - for _, target := range targets { - switch kind { case reloTypeIDTarget: - if localAccessor[0] != 0 { - return Relocation{}, fmt.Errorf("%s: unexpected non-zero accessor", kind) + return fixup(uint32(localID), uint32(targetID)) + + case reloTypeSize: + localSize, err := Sizeof(local) + if err != nil { + return zero, err } - if compat, err := coreAreTypesCompatible(local, target); err != nil { - return Relocation{}, fmt.Errorf("%s: %s", kind, err) - } else if !compat { - continue + targetSize, err := Sizeof(target) + if err != nil { + return zero, err } - relos = append(relos, Relocation{uint32(target.ID()), uint32(target.ID())}) + return fixup(uint32(localSize), uint32(targetSize)) + } - default: - return Relocation{}, fmt.Errorf("relocation %s: %w", kind, ErrNotSupported) + case reloEnumvalValue, reloEnumvalExists: + localValue, targetValue, err := coreFindEnumValue(local, relo.accessor, target) + if errors.Is(err, errImpossibleRelocation) { + return poison() + } + if err != nil { + return zero, fmt.Errorf("relocation %s: %w", relo.kind, err) } - matches = append(matches, target) - } - if len(relos) == 0 { - // TODO: Add switch for existence checks like reloEnumvalExists here. + switch relo.kind { + case reloEnumvalExists: + return fixup(1, 1) - // TODO: This might have to be poisoned. - return Relocation{}, fmt.Errorf("no relocation found, tried %v", targets) - } + case reloEnumvalValue: + return fixup(uint32(localValue.Value), uint32(targetValue.Value)) + } + + case reloFieldByteOffset, reloFieldByteSize, reloFieldExists: + if _, ok := target.(*Fwd); ok { + // We can't relocate fields using a forward declaration, so + // skip it. If a non-forward declaration is present in the BTF + // we'll find it in one of the other iterations. + return poison() + } + + localField, targetField, err := coreFindField(local, relo.accessor, target) + if errors.Is(err, errImpossibleRelocation) { + return poison() + } + if err != nil { + return zero, fmt.Errorf("target %s: %w", target, err) + } + + switch relo.kind { + case reloFieldExists: + return fixup(1, 1) + + case reloFieldByteOffset: + return fixup(localField.offset/8, targetField.offset/8) + + case reloFieldByteSize: + localSize, err := Sizeof(localField.Type) + if err != nil { + return zero, err + } + + targetSize, err := Sizeof(targetField.Type) + if err != nil { + return zero, err + } + + return fixup(uint32(localSize), uint32(targetSize)) - relo := relos[0] - for _, altRelo := range relos[1:] { - if !altRelo.equal(relo) { - return Relocation{}, fmt.Errorf("multiple types %v match: %w", matches, errAmbiguousRelocation) } } - return relo, nil + return zero, fmt.Errorf("relocation %s: %w", relo.kind, ErrNotSupported) } /* coreAccessor contains a path through a struct. It contains at least one index. @@ -219,6 +482,240 @@ func parseCoreAccessor(accessor string) (coreAccessor, error) { return result, nil } +func (ca coreAccessor) String() string { + strs := make([]string, 0, len(ca)) + for _, i := range ca { + strs = append(strs, strconv.Itoa(i)) + } + return strings.Join(strs, ":") +} + +func (ca coreAccessor) enumValue(t Type) (*EnumValue, error) { + e, ok := t.(*Enum) + if !ok { + return nil, fmt.Errorf("not an enum: %s", t) + } + + if len(ca) > 1 { + return nil, fmt.Errorf("invalid accessor %s for enum", ca) + } + + i := ca[0] + if i >= len(e.Values) { + return nil, fmt.Errorf("invalid index %d for %s", i, e) + } + + return &e.Values[i], nil +} + +type coreField struct { + Type Type + offset uint32 +} + +func adjustOffset(base uint32, t Type, n int) (uint32, error) { + size, err := Sizeof(t) + if err != nil { + return 0, err + } + + return base + (uint32(n) * uint32(size) * 8), nil +} + +// coreFindField descends into the local type using the accessor and tries to +// find an equivalent field in target at each step. +// +// Returns the field and the offset of the field from the start of +// target in bits. +func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreField, _ error) { + // The first index is used to offset a pointer of the base type like + // when accessing an array. + localOffset, err := adjustOffset(0, local, localAcc[0]) + if err != nil { + return coreField{}, coreField{}, err + } + + targetOffset, err := adjustOffset(0, target, localAcc[0]) + if err != nil { + return coreField{}, coreField{}, err + } + + if err := coreAreMembersCompatible(local, target); err != nil { + return coreField{}, coreField{}, fmt.Errorf("fields: %w", err) + } + + var localMaybeFlex, targetMaybeFlex bool + for _, acc := range localAcc[1:] { + switch localType := local.(type) { + case composite: + // For composite types acc is used to find the field in the local type, + // and then we try to find a field in target with the same name. + localMembers := localType.members() + if acc >= len(localMembers) { + return coreField{}, coreField{}, fmt.Errorf("invalid accessor %d for %s", acc, local) + } + + localMember := localMembers[acc] + if localMember.Name == "" { + _, ok := localMember.Type.(composite) + if !ok { + return coreField{}, coreField{}, fmt.Errorf("unnamed field with type %s: %s", localMember.Type, ErrNotSupported) + } + + // This is an anonymous struct or union, ignore it. + local = localMember.Type + localOffset += localMember.Offset + localMaybeFlex = false + continue + } + + targetType, ok := target.(composite) + if !ok { + return coreField{}, coreField{}, fmt.Errorf("target not composite: %w", errImpossibleRelocation) + } + + targetMember, last, err := coreFindMember(targetType, localMember.Name) + if err != nil { + return coreField{}, coreField{}, err + } + + if targetMember.BitfieldSize > 0 { + return coreField{}, coreField{}, fmt.Errorf("field %q is a bitfield: %w", targetMember.Name, ErrNotSupported) + } + + local = localMember.Type + localMaybeFlex = acc == len(localMembers)-1 + localOffset += localMember.Offset + target = targetMember.Type + targetMaybeFlex = last + targetOffset += targetMember.Offset + + case *Array: + // For arrays, acc is the index in the target. + targetType, ok := target.(*Array) + if !ok { + return coreField{}, coreField{}, fmt.Errorf("target not array: %w", errImpossibleRelocation) + } + + if localType.Nelems == 0 && !localMaybeFlex { + return coreField{}, coreField{}, fmt.Errorf("local type has invalid flexible array") + } + if targetType.Nelems == 0 && !targetMaybeFlex { + return coreField{}, coreField{}, fmt.Errorf("target type has invalid flexible array") + } + + if localType.Nelems > 0 && acc >= int(localType.Nelems) { + return coreField{}, coreField{}, fmt.Errorf("invalid access of %s at index %d", localType, acc) + } + if targetType.Nelems > 0 && acc >= int(targetType.Nelems) { + return coreField{}, coreField{}, fmt.Errorf("out of bounds access of target: %w", errImpossibleRelocation) + } + + local = localType.Type + localMaybeFlex = false + localOffset, err = adjustOffset(localOffset, local, acc) + if err != nil { + return coreField{}, coreField{}, err + } + + target = targetType.Type + targetMaybeFlex = false + targetOffset, err = adjustOffset(targetOffset, target, acc) + if err != nil { + return coreField{}, coreField{}, err + } + + default: + return coreField{}, coreField{}, fmt.Errorf("relocate field of %T: %w", localType, ErrNotSupported) + } + + if err := coreAreMembersCompatible(local, target); err != nil { + return coreField{}, coreField{}, err + } + } + + return coreField{local, localOffset}, coreField{target, targetOffset}, nil +} + +// coreFindMember finds a member in a composite type while handling anonymous +// structs and unions. +func coreFindMember(typ composite, name Name) (Member, bool, error) { + if name == "" { + return Member{}, false, errors.New("can't search for anonymous member") + } + + type offsetTarget struct { + composite + offset uint32 + } + + targets := []offsetTarget{{typ, 0}} + visited := make(map[composite]bool) + + for i := 0; i < len(targets); i++ { + target := targets[i] + + // Only visit targets once to prevent infinite recursion. + if visited[target] { + continue + } + if len(visited) >= maxTypeDepth { + // This check is different than libbpf, which restricts the entire + // path to BPF_CORE_SPEC_MAX_LEN items. + return Member{}, false, fmt.Errorf("type is nested too deep") + } + visited[target] = true + + members := target.members() + for j, member := range members { + if member.Name == name { + // NB: This is safe because member is a copy. + member.Offset += target.offset + return member, j == len(members)-1, nil + } + + // The names don't match, but this member could be an anonymous struct + // or union. + if member.Name != "" { + continue + } + + comp, ok := member.Type.(composite) + if !ok { + return Member{}, false, fmt.Errorf("anonymous non-composite type %T not allowed", member.Type) + } + + targets = append(targets, offsetTarget{comp, target.offset + member.Offset}) + } + } + + return Member{}, false, fmt.Errorf("no matching member: %w", errImpossibleRelocation) +} + +// coreFindEnumValue follows localAcc to find the equivalent enum value in target. +func coreFindEnumValue(local Type, localAcc coreAccessor, target Type) (localValue, targetValue *EnumValue, _ error) { + localValue, err := localAcc.enumValue(local) + if err != nil { + return nil, nil, err + } + + targetEnum, ok := target.(*Enum) + if !ok { + return nil, nil, errImpossibleRelocation + } + + localName := localValue.Name.essentialName() + for i, targetValue := range targetEnum.Values { + if targetValue.Name.essentialName() != localName { + continue + } + + return localValue, &targetEnum.Values[i], nil + } + + return nil, nil, errImpossibleRelocation +} + /* The comment below is from bpf_core_types_are_compat in libbpf.c: * * Check local and target types for compatibility. This check is used for @@ -239,8 +736,10 @@ func parseCoreAccessor(accessor string) (coreAccessor, error) { * number of input args and compatible return and argument types. * These rules are not set in stone and probably will be adjusted as we get * more experience with using BPF CO-RE relocations. + * + * Returns errImpossibleRelocation if types are not compatible. */ -func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) { +func coreAreTypesCompatible(localType Type, targetType Type) error { var ( localTs, targetTs typeDeque l, t = &localType, &targetType @@ -249,14 +748,14 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) { for ; l != nil && t != nil; l, t = localTs.shift(), targetTs.shift() { if depth >= maxTypeDepth { - return false, errors.New("types are nested too deep") + return errors.New("types are nested too deep") } - localType = skipQualifierAndTypedef(*l) - targetType = skipQualifierAndTypedef(*t) + localType = *l + targetType = *t if reflect.TypeOf(localType) != reflect.TypeOf(targetType) { - return false, nil + return fmt.Errorf("type mismatch: %w", errImpossibleRelocation) } switch lv := (localType).(type) { @@ -266,7 +765,7 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) { case *Int: tv := targetType.(*Int) if lv.isBitfield() || tv.isBitfield() { - return false, nil + return fmt.Errorf("bitfield: %w", errImpossibleRelocation) } case *Pointer, *Array: @@ -277,7 +776,7 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) { case *FuncProto: tv := targetType.(*FuncProto) if len(lv.Params) != len(tv.Params) { - return false, nil + return fmt.Errorf("function param mismatch: %w", errImpossibleRelocation) } depth++ @@ -285,22 +784,24 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) { targetType.walk(&targetTs) default: - return false, fmt.Errorf("unsupported type %T", localType) + return fmt.Errorf("unsupported type %T", localType) } } if l != nil { - return false, fmt.Errorf("dangling local type %T", *l) + return fmt.Errorf("dangling local type %T", *l) } if t != nil { - return false, fmt.Errorf("dangling target type %T", *t) + return fmt.Errorf("dangling target type %T", *t) } - return true, nil + return nil } -/* The comment below is from bpf_core_fields_are_compat in libbpf.c: +/* coreAreMembersCompatible checks two types for field-based relocation compatibility. + * + * The comment below is from bpf_core_fields_are_compat in libbpf.c: * * Check two types for compatibility for the purpose of field access * relocation. const/volatile/restrict and typedefs are skipped to ensure we @@ -314,65 +815,63 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) { * - for INT, size and signedness are ignored; * - for ARRAY, dimensionality is ignored, element types are checked for * compatibility recursively; + * [ NB: coreAreMembersCompatible doesn't recurse, this check is done + * by coreFindField. ] * - everything else shouldn't be ever a target of relocation. * These rules are not set in stone and probably will be adjusted as we get * more experience with using BPF CO-RE relocations. + * + * Returns errImpossibleRelocation if the members are not compatible. */ -func coreAreMembersCompatible(localType Type, targetType Type) (bool, error) { - doNamesMatch := func(a, b string) bool { +func coreAreMembersCompatible(localType Type, targetType Type) error { + doNamesMatch := func(a, b string) error { if a == "" || b == "" { // allow anonymous and named type to match - return true - } - - return essentialName(a) == essentialName(b) - } - - for depth := 0; depth <= maxTypeDepth; depth++ { - localType = skipQualifierAndTypedef(localType) - targetType = skipQualifierAndTypedef(targetType) - - _, lok := localType.(composite) - _, tok := targetType.(composite) - if lok && tok { - return true, nil + return nil } - if reflect.TypeOf(localType) != reflect.TypeOf(targetType) { - return false, nil + if essentialName(a) == essentialName(b) { + return nil } - switch lv := localType.(type) { - case *Pointer: - return true, nil + return fmt.Errorf("names don't match: %w", errImpossibleRelocation) + } - case *Enum: - tv := targetType.(*Enum) - return doNamesMatch(lv.name(), tv.name()), nil + _, lok := localType.(composite) + _, tok := targetType.(composite) + if lok && tok { + return nil + } - case *Fwd: - tv := targetType.(*Fwd) - return doNamesMatch(lv.name(), tv.name()), nil + if reflect.TypeOf(localType) != reflect.TypeOf(targetType) { + return fmt.Errorf("type mismatch: %w", errImpossibleRelocation) + } - case *Int: - tv := targetType.(*Int) - return !lv.isBitfield() && !tv.isBitfield(), nil + switch lv := localType.(type) { + case *Array, *Pointer: + return nil - case *Array: - tv := targetType.(*Array) + case *Enum: + tv := targetType.(*Enum) + return doNamesMatch(lv.name(), tv.name()) - localType = lv.Type - targetType = tv.Type + case *Fwd: + tv := targetType.(*Fwd) + return doNamesMatch(lv.name(), tv.name()) - default: - return false, fmt.Errorf("unsupported type %T", localType) + case *Int: + tv := targetType.(*Int) + if lv.isBitfield() || tv.isBitfield() { + return fmt.Errorf("bitfield: %w", errImpossibleRelocation) } - } + return nil - return false, errors.New("types are nested too deep") + default: + return fmt.Errorf("type %s: %w", localType, ErrNotSupported) + } } -func skipQualifierAndTypedef(typ Type) Type { +func skipQualifierAndTypedef(typ Type) (Type, error) { result := typ for depth := 0; depth <= maxTypeDepth; depth++ { switch v := (result).(type) { @@ -381,8 +880,8 @@ func skipQualifierAndTypedef(typ Type) Type { case *Typedef: result = v.Type default: - return result + return result, nil } } - return typ + return nil, errors.New("exceeded type depth") } 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 6a21b6bda5cc..beba1bce6980 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go @@ -30,7 +30,7 @@ type btfExtCoreHeader struct { CoreReloLen uint32 } -func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, coreRelos map[string]bpfCoreRelos, err error) { +func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, relos map[string]coreRelos, err error) { var header btfExtHeader var coreHeader btfExtCoreHeader if err := binary.Read(r, bo, &header); err != nil { @@ -94,13 +94,13 @@ func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (f return nil, nil, nil, fmt.Errorf("can't seek to CO-RE relocation section: %v", err) } - coreRelos, err = parseExtInfoRelos(io.LimitReader(r, int64(coreHeader.CoreReloLen)), bo, strings) + relos, err = parseExtInfoRelos(io.LimitReader(r, int64(coreHeader.CoreReloLen)), bo, strings) if err != nil { return nil, nil, nil, fmt.Errorf("CO-RE relocation info: %w", err) } } - return funcInfo, lineInfo, coreRelos, nil + return funcInfo, lineInfo, relos, nil } type btfExtInfoSec struct { @@ -208,18 +208,25 @@ type bpfCoreRelo struct { InsnOff uint32 TypeID TypeID AccessStrOff uint32 - ReloKind coreReloKind + Kind COREKind } -type bpfCoreRelos []bpfCoreRelo +type coreRelo struct { + insnOff uint32 + typeID TypeID + accessor coreAccessor + kind COREKind +} + +type coreRelos []coreRelo // append two slices of extInfoRelo to each other. The InsnOff of b are adjusted // by offset. -func (r bpfCoreRelos) append(other bpfCoreRelos, offset uint64) bpfCoreRelos { - result := make([]bpfCoreRelo, 0, len(r)+len(other)) +func (r coreRelos) append(other coreRelos, offset uint64) coreRelos { + result := make([]coreRelo, 0, len(r)+len(other)) result = append(result, r...) for _, relo := range other { - relo.InsnOff += uint32(offset) + relo.insnOff += uint32(offset) result = append(result, relo) } return result @@ -227,7 +234,7 @@ func (r bpfCoreRelos) append(other bpfCoreRelos, offset uint64) bpfCoreRelos { var extInfoReloSize = binary.Size(bpfCoreRelo{}) -func parseExtInfoRelos(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]bpfCoreRelos, error) { +func parseExtInfoRelos(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]coreRelos, error) { var recordSize uint32 if err := binary.Read(r, bo, &recordSize); err != nil { return nil, fmt.Errorf("read record size: %v", err) @@ -237,14 +244,14 @@ func parseExtInfoRelos(r io.Reader, bo binary.ByteOrder, strings stringTable) (m return nil, fmt.Errorf("expected record size %d, got %d", extInfoReloSize, recordSize) } - result := make(map[string]bpfCoreRelos) + result := make(map[string]coreRelos) for { secName, infoHeader, err := parseExtInfoHeader(r, bo, strings) if errors.Is(err, io.EOF) { return result, nil } - var relos []bpfCoreRelo + var relos coreRelos for i := uint32(0); i < infoHeader.NumInfo; i++ { var relo bpfCoreRelo if err := binary.Read(r, bo, &relo); err != nil { @@ -255,7 +262,22 @@ func parseExtInfoRelos(r io.Reader, bo binary.ByteOrder, strings stringTable) (m return nil, fmt.Errorf("section %v: offset %v is not aligned with instruction size", secName, relo.InsnOff) } - relos = append(relos, relo) + accessorStr, err := strings.Lookup(relo.AccessStrOff) + if err != nil { + return nil, err + } + + accessor, err := parseCoreAccessor(accessorStr) + if err != nil { + return nil, fmt.Errorf("accessor %q: %s", accessorStr, err) + } + + relos = append(relos, coreRelo{ + relo.InsnOff, + relo.TypeID, + accessor, + relo.Kind, + }) } result[secName] = relos diff --git a/vendor/github.com/cilium/ebpf/internal/btf/types.go b/vendor/github.com/cilium/ebpf/internal/btf/types.go index 9e1fd8d0b2df..62aa31bcd781 100644 --- a/vendor/github.com/cilium/ebpf/internal/btf/types.go +++ b/vendor/github.com/cilium/ebpf/internal/btf/types.go @@ -1,7 +1,6 @@ package btf import ( - "errors" "fmt" "math" "strings" @@ -37,6 +36,7 @@ type Type interface { type namedType interface { Type name() string + essentialName() string } // Name identifies a type. @@ -48,6 +48,10 @@ func (n Name) name() string { return string(n) } +func (n Name) essentialName() string { + return essentialName(string(n)) +} + // Void is the unit type of BTF. type Void struct{} @@ -174,8 +178,7 @@ func (s *Struct) walk(tdq *typeDeque) { func (s *Struct) copy() Type { cpy := *s - cpy.Members = make([]Member, len(s.Members)) - copy(cpy.Members, s.Members) + cpy.Members = copyMembers(s.Members) return &cpy } @@ -206,8 +209,7 @@ func (u *Union) walk(tdq *typeDeque) { func (u *Union) copy() Type { cpy := *u - cpy.Members = make([]Member, len(u.Members)) - copy(cpy.Members, u.Members) + cpy.Members = copyMembers(u.Members) return &cpy } @@ -215,6 +217,12 @@ func (u *Union) members() []Member { return u.Members } +func copyMembers(orig []Member) []Member { + cpy := make([]Member, len(orig)) + copy(cpy, orig) + return cpy +} + type composite interface { members() []Member } @@ -372,11 +380,12 @@ func (r *Restrict) copy() Type { type Func struct { TypeID Name - Type Type + Type Type + Linkage FuncLinkage } func (f *Func) String() string { - return fmt.Sprintf("func#%d[%q proto=#%d]", f.TypeID, f.Name, f.Type.ID()) + return fmt.Sprintf("func#%d[%s %q proto=#%d]", f.TypeID, f.Linkage, f.Name, f.Type.ID()) } func (f *Func) walk(tdq *typeDeque) { tdq.push(&f.Type) } @@ -425,12 +434,12 @@ type FuncParam struct { type Var struct { TypeID Name - Type Type + Type Type + Linkage VarLinkage } func (v *Var) String() string { - // TODO: Linkage - return fmt.Sprintf("var#%d[%q]", v.TypeID, v.Name) + return fmt.Sprintf("var#%d[%s %q]", v.TypeID, v.Linkage, v.Name) } func (v *Var) walk(tdq *typeDeque) { tdq.push(&v.Type) } @@ -511,7 +520,7 @@ func Sizeof(typ Type) (int, error) { switch v := typ.(type) { case *Array: if n > 0 && int64(v.Nelems) > math.MaxInt64/n { - return 0, errors.New("overflow") + return 0, fmt.Errorf("type %s: overflow", typ) } // Arrays may be of zero length, which allows @@ -532,28 +541,30 @@ func Sizeof(typ Type) (int, error) { continue default: - return 0, fmt.Errorf("unrecognized type %T", typ) + return 0, fmt.Errorf("unsized type %T", typ) } if n > 0 && elem > math.MaxInt64/n { - return 0, errors.New("overflow") + return 0, fmt.Errorf("type %s: overflow", typ) } size := n * elem if int64(int(size)) != size { - return 0, errors.New("overflow") + return 0, fmt.Errorf("type %s: overflow", typ) } return int(size), nil } - return 0, errors.New("exceeded type depth") + return 0, fmt.Errorf("type %s: exceeded type depth", typ) } // copy a Type recursively. // // typ may form a cycle. -func copyType(typ Type) Type { +// +// 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 @@ -566,7 +577,17 @@ func copyType(typ Type) Type { continue } - cpy := (*t).copy() + var cpy Type + if transform != nil { + tf, err := transform(*t) + if err != nil { + return nil, fmt.Errorf("copy %s: %w", typ, err) + } + cpy = tf.copy() + } else { + cpy = (*t).copy() + } + copies[*t] = cpy *t = cpy @@ -574,7 +595,7 @@ func copyType(typ Type) Type { cpy.walk(&work) } - return typ + return typ, nil } // typeDeque keeps track of pointers to types which still @@ -783,7 +804,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, typ = restrict case kindFunc: - fn := &Func{id, name, nil} + fn := &Func{id, name, nil, raw.Linkage()} fixup(raw.Type(), kindFuncProto, &fn.Type) typ = fn @@ -808,7 +829,8 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, typ = fp case kindVar: - v := &Var{id, name, nil} + variable := raw.data.(*btfVariable) + v := &Var{id, name, nil, VarLinkage(variable.Linkage)} fixup(raw.Type(), kindUnknown, &v.Type) typ = v diff --git a/vendor/github.com/cilium/ebpf/internal/elf.go b/vendor/github.com/cilium/ebpf/internal/elf.go index c3f9ea0f8a40..54a4313130a4 100644 --- a/vendor/github.com/cilium/ebpf/internal/elf.go +++ b/vendor/github.com/cilium/ebpf/internal/elf.go @@ -50,3 +50,19 @@ func (se *SafeELFFile) Symbols() (syms []elf.Symbol, err error) { syms, err = se.File.Symbols() return } + +// DynamicSymbols is the safe version of elf.File.DynamicSymbols. +func (se *SafeELFFile) DynamicSymbols() (syms []elf.Symbol, err error) { + defer func() { + r := recover() + if r == nil { + return + } + + syms = nil + err = fmt.Errorf("reading ELF dynamic symbols panicked: %s", r) + }() + + syms, err = se.File.DynamicSymbols() + return +} diff --git a/vendor/github.com/cilium/ebpf/internal/endian.go b/vendor/github.com/cilium/ebpf/internal/endian.go index ac8a94e512a9..6ae99fcd5f3b 100644 --- a/vendor/github.com/cilium/ebpf/internal/endian.go +++ b/vendor/github.com/cilium/ebpf/internal/endian.go @@ -9,11 +9,16 @@ import ( // depending on the host's endianness. var NativeEndian binary.ByteOrder +// Clang is set to either "el" or "eb" depending on the host's endianness. +var ClangEndian string + func init() { if isBigEndian() { NativeEndian = binary.BigEndian + ClangEndian = "eb" } else { NativeEndian = binary.LittleEndian + ClangEndian = "el" } } diff --git a/vendor/github.com/cilium/ebpf/internal/errors.go b/vendor/github.com/cilium/ebpf/internal/errors.go index b6aee81f7de2..877bd72ee266 100644 --- a/vendor/github.com/cilium/ebpf/internal/errors.go +++ b/vendor/github.com/cilium/ebpf/internal/errors.go @@ -29,6 +29,10 @@ type VerifierError struct { log string } +func (le *VerifierError) Unwrap() error { + return le.cause +} + func (le *VerifierError) Error() string { if le.log == "" { return le.cause.Error() diff --git a/vendor/github.com/cilium/ebpf/internal/ptr.go b/vendor/github.com/cilium/ebpf/internal/ptr.go index 66822a6acbc9..f295de72cfeb 100644 --- a/vendor/github.com/cilium/ebpf/internal/ptr.go +++ b/vendor/github.com/cilium/ebpf/internal/ptr.go @@ -22,10 +22,6 @@ func NewSlicePointer(buf []byte) Pointer { // NewStringPointer creates a 64-bit pointer from a string. func NewStringPointer(str string) Pointer { - if str == "" { - return Pointer{} - } - p, err := unix.BytePtrFromString(str) if err != nil { return Pointer{} diff --git a/vendor/github.com/cilium/ebpf/internal/syscall.go b/vendor/github.com/cilium/ebpf/internal/syscall.go index 0ba438d368c0..b766e643e07a 100644 --- a/vendor/github.com/cilium/ebpf/internal/syscall.go +++ b/vendor/github.com/cilium/ebpf/internal/syscall.go @@ -4,6 +4,7 @@ import ( "fmt" "path/filepath" "runtime" + "syscall" "unsafe" "github.com/cilium/ebpf/internal/unix" @@ -61,7 +62,7 @@ func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) { var err error if errNo != 0 { - err = errNo + err = wrappedErrno{errNo} } return r1, err @@ -178,3 +179,67 @@ func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error { } return nil } + +// BPFObjName is a null-terminated string made up of +// 'A-Za-z0-9_' characters. +type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte + +// NewBPFObjName truncates the result if it is too long. +func NewBPFObjName(name string) BPFObjName { + var result BPFObjName + copy(result[:unix.BPF_OBJ_NAME_LEN-1], name) + return result +} + +type BPFMapCreateAttr struct { + MapType uint32 + KeySize uint32 + ValueSize uint32 + MaxEntries uint32 + Flags uint32 + InnerMapFd uint32 // since 4.12 56f668dfe00d + NumaNode uint32 // since 4.14 96eabe7a40aa + MapName BPFObjName // since 4.15 ad5b177bd73f + MapIfIndex uint32 + BTFFd uint32 + BTFKeyTypeID uint32 + BTFValueTypeID uint32 +} + +func BPFMapCreate(attr *BPFMapCreateAttr) (*FD, error) { + fd, err := BPF(BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) + if err != nil { + return nil, err + } + + return NewFD(uint32(fd)), nil +} + +// wrappedErrno wraps syscall.Errno to prevent direct comparisons with +// syscall.E* or unix.E* constants. +// +// You should never export an error of this type. +type wrappedErrno struct { + syscall.Errno +} + +func (we wrappedErrno) Unwrap() error { + return we.Errno +} + +type syscallError struct { + error + errno syscall.Errno +} + +func SyscallError(err error, errno syscall.Errno) error { + return &syscallError{err, errno} +} + +func (se *syscallError) Is(target error) bool { + return target == se.error +} + +func (se *syscallError) Unwrap() error { + return se.errno +} 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 24bc76f7b8c3..0a18eaf0cf84 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go @@ -31,6 +31,8 @@ const ( BPF_F_RDONLY_PROG = linux.BPF_F_RDONLY_PROG BPF_F_WRONLY_PROG = linux.BPF_F_WRONLY_PROG BPF_F_SLEEPABLE = linux.BPF_F_SLEEPABLE + BPF_F_MMAPABLE = linux.BPF_F_MMAPABLE + 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 SYS_BPF = linux.SYS_BPF @@ -42,6 +44,7 @@ const ( PROT_READ = linux.PROT_READ PROT_WRITE = linux.PROT_WRITE MAP_SHARED = linux.MAP_SHARED + PERF_ATTR_SIZE_VER1 = linux.PERF_ATTR_SIZE_VER1 PERF_TYPE_SOFTWARE = linux.PERF_TYPE_SOFTWARE PERF_TYPE_TRACEPOINT = linux.PERF_TYPE_TRACEPOINT PERF_COUNT_SW_BPF_OUTPUT = linux.PERF_COUNT_SW_BPF_OUTPUT 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 714589ba1e14..1b06defc0a09 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_other.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_other.go @@ -31,6 +31,8 @@ const ( BPF_F_RDONLY_PROG = 0 BPF_F_WRONLY_PROG = 0 BPF_F_SLEEPABLE = 0 + BPF_F_MMAPABLE = 0 + BPF_F_INNER_MAP = 0 BPF_OBJ_NAME_LEN = 0x10 BPF_TAG_SIZE = 0x8 SYS_BPF = 321 @@ -43,6 +45,7 @@ const ( PROT_READ = 0x1 PROT_WRITE = 0x2 MAP_SHARED = 0x1 + PERF_ATTR_SIZE_VER1 = 0 PERF_TYPE_SOFTWARE = 0x1 PERF_TYPE_TRACEPOINT = 0 PERF_COUNT_SW_BPF_OUTPUT = 0xa diff --git a/vendor/github.com/cilium/ebpf/link/iter.go b/vendor/github.com/cilium/ebpf/link/iter.go index 04d24ef35a99..654d34ef8482 100644 --- a/vendor/github.com/cilium/ebpf/link/iter.go +++ b/vendor/github.com/cilium/ebpf/link/iter.go @@ -3,8 +3,10 @@ package link import ( "fmt" "io" + "unsafe" "github.com/cilium/ebpf" + "github.com/cilium/ebpf/internal" ) type IterOptions struct { @@ -15,19 +17,45 @@ type IterOptions struct { // AttachTo requires the kernel to include BTF of itself, // and it to be compiled with a recent pahole (>= 1.16). Program *ebpf.Program + + // Map specifies the target map for bpf_map_elem and sockmap iterators. + // It may be nil. + Map *ebpf.Map } // AttachIter attaches a BPF seq_file iterator. func AttachIter(opts IterOptions) (*Iter, error) { - link, err := AttachRawLink(RawLinkOptions{ - Program: opts.Program, - Attach: ebpf.AttachTraceIter, - }) + if err := haveBPFLink(); err != nil { + return nil, err + } + + progFd := opts.Program.FD() + if progFd < 0 { + return nil, fmt.Errorf("invalid program: %s", internal.ErrClosedFd) + } + + var info bpfIterLinkInfoMap + if opts.Map != nil { + mapFd := opts.Map.FD() + if mapFd < 0 { + return nil, fmt.Errorf("invalid map: %w", internal.ErrClosedFd) + } + info.map_fd = uint32(mapFd) + } + + attr := bpfLinkCreateIterAttr{ + prog_fd: uint32(progFd), + attach_type: ebpf.AttachTraceIter, + iter_info: internal.NewPointer(unsafe.Pointer(&info)), + iter_info_len: uint32(unsafe.Sizeof(info)), + } + + fd, err := bpfLinkCreateIter(&attr) if err != nil { return nil, fmt.Errorf("can't link iterator: %w", err) } - return &Iter{*link}, err + return &Iter{RawLink{fd, ""}}, err } // LoadPinnedIter loads a pinned iterator from a bpffs. @@ -65,3 +93,8 @@ func (it *Iter) Open() (io.ReadCloser, error) { return fd.File("bpf_iter"), nil } + +// union bpf_iter_link_info.map +type bpfIterLinkInfoMap struct { + map_fd uint32 +} diff --git a/vendor/github.com/cilium/ebpf/link/kprobe.go b/vendor/github.com/cilium/ebpf/link/kprobe.go index ad3a5949a94c..ea71d6d608a8 100644 --- a/vendor/github.com/cilium/ebpf/link/kprobe.go +++ b/vendor/github.com/cilium/ebpf/link/kprobe.go @@ -1,12 +1,16 @@ package link import ( + "bytes" "crypto/rand" "errors" "fmt" + "io/ioutil" "os" "path/filepath" "runtime" + "sync" + "unsafe" "github.com/cilium/ebpf" "github.com/cilium/ebpf/internal" @@ -15,13 +19,60 @@ import ( var ( kprobeEventsPath = filepath.Join(tracefsPath, "kprobe_events") + + kprobeRetprobeBit = struct { + once sync.Once + value uint64 + err error + }{} +) + +type probeType uint8 + +const ( + kprobeType probeType = iota + uprobeType ) +func (pt probeType) String() string { + if pt == kprobeType { + return "kprobe" + } + return "uprobe" +} + +func (pt probeType) EventsPath() string { + if pt == kprobeType { + return kprobeEventsPath + } + return uprobeEventsPath +} + +func (pt probeType) PerfEventType(ret bool) perfEventType { + if pt == kprobeType { + if ret { + return kretprobeEvent + } + return kprobeEvent + } + if ret { + return uretprobeEvent + } + return uprobeEvent +} + +func (pt probeType) RetprobeBit() (uint64, error) { + if pt == kprobeType { + return kretprobeBit() + } + return uretprobeBit() +} + // Kprobe attaches the given eBPF program to a perf event that fires when the // given kernel symbol starts executing. See /proc/kallsyms for available // symbols. For example, printk(): // -// Kprobe("printk") +// Kprobe("printk", prog) // // The resulting Link must be Closed during program shutdown to avoid leaking // system resources. @@ -44,7 +95,7 @@ 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") +// Kretprobe("printk", prog) // // The resulting Link must be Closed during program shutdown to avoid leaking // system resources. @@ -80,7 +131,10 @@ func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) { } // Use kprobe PMU if the kernel has it available. - tp, err := pmuKprobe(symbol, ret) + tp, err := pmuKprobe(platformPrefix(symbol), ret) + if errors.Is(err, os.ErrNotExist) { + tp, err = pmuKprobe(symbol, ret) + } if err == nil { return tp, nil } @@ -89,7 +143,10 @@ func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) { } // Use tracefs if kprobe PMU is missing. - tp, err = tracefsKprobe(symbol, ret) + tp, err = tracefsKprobe(platformPrefix(symbol), ret) + if errors.Is(err, os.ErrNotExist) { + tp, err = tracefsKprobe(symbol, ret) + } if err != nil { return nil, fmt.Errorf("creating trace event '%s' in tracefs: %w", symbol, err) } @@ -97,36 +154,70 @@ func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) { return tp, nil } -// pmuKprobe opens a perf event based on a Performance Monitoring Unit. -// Requires at least 4.17 (e12f03d7031a "perf/core: Implement the -// 'perf_kprobe' PMU"). -// Returns ErrNotSupported if the kernel doesn't support perf_kprobe PMU, -// or os.ErrNotExist if the given symbol does not exist in the kernel. +// 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) +} +// pmuProbe opens a perf event based on a Performance Monitoring Unit. +// +// Requires at least a 4.17 kernel. +// e12f03d7031a "perf/core: Implement the 'perf_kprobe' PMU" +// 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) { // Getting the PMU type will fail if the kernel doesn't support - // the perf_kprobe PMU. - et, err := getPMUEventType("kprobe") + // the perf_[k,u]probe PMU. + et, err := getPMUEventType(typ) if err != nil { return nil, err } - // Create a pointer to a NUL-terminated string for the kernel. - sp, err := unsafeStringPtr(symbol) - if err != nil { - return nil, err - } - - // TODO: Parse the position of the bit from /sys/bus/event_source/devices/%s/format/retprobe. - config := 0 + var config uint64 if ret { - config = 1 - } - - attr := unix.PerfEventAttr{ - Type: uint32(et), // PMU event type read from sysfs - Ext1: uint64(uintptr(sp)), // Kernel symbol to trace - Config: uint64(config), // perf_kprobe PMU treats config as flags + bit, err := typ.RetprobeBit() + if err != nil { + return nil, err + } + config |= 1 << bit + } + + var ( + attr unix.PerfEventAttr + sp unsafe.Pointer + ) + switch typ { + case kprobeType: + // Create a pointer to a NUL-terminated string for the kernel. + sp, err := unsafeStringPtr(symbol) + if err != nil { + return nil, err + } + + attr = unix.PerfEventAttr{ + Type: uint32(et), // PMU event type read from sysfs + Ext1: uint64(uintptr(sp)), // Kernel symbol to trace + Config: config, // Retprobe flag + } + case uprobeType: + sp, err := unsafeStringPtr(path) + if err != nil { + return nil, err + } + + attr = unix.PerfEventAttr{ + // The minimum size required for PMU uprobes is PERF_ATTR_SIZE_VER1, + // since it added the config2 (Ext2) field. The Size field controls the + // size of the internal buffer the kernel allocates for reading the + // perf_event_attr argument from userspace. + Size: unix.PERF_ATTR_SIZE_VER1, + Type: uint32(et), // PMU event type read from sysfs + Ext1: uint64(uintptr(sp)), // Uprobe path + Ext2: offset, // Uprobe offset + Config: config, // Retprobe flag + } } fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC) @@ -144,22 +235,27 @@ func pmuKprobe(symbol string, ret bool) (*perfEvent, error) { // Ensure the string pointer is not collected before PerfEventOpen returns. runtime.KeepAlive(sp) - // Kernel has perf_kprobe PMU available, initialize perf event. + // Kernel has perf_[k,u]probe PMU available, initialize perf event. return &perfEvent{ - fd: internal.NewFD(uint32(fd)), - pmuID: et, - name: symbol, - ret: ret, - progType: ebpf.Kprobe, + fd: internal.NewFD(uint32(fd)), + pmuID: et, + name: symbol, + typ: typ.PerfEventType(ret), }, nil } -// tracefsKprobe creates a trace event by writing an entry to /kprobe_events. -// A new trace event group name is generated on every call to support creating -// multiple trace events for the same kernel symbol. A perf event is then opened -// on the newly-created trace event and returned to the caller. +// tracefsKprobe creates a Kprobe tracefs entry. func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) { + return tracefsProbe(kprobeType, symbol, "", 0, ret) +} +// tracefsProbe creates a trace event by writing an entry to /[k,u]probe_events. +// A new trace event group name is generated on every call to support creating +// multiple trace events for the same kernel or userspace symbol. +// 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) { // 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. @@ -176,14 +272,13 @@ func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) { if err == nil { return nil, fmt.Errorf("trace event already exists: %s/%s", group, symbol) } - // The read is expected to fail with ErrNotSupported due to a non-existing event. - if err != nil && !errors.Is(err, ErrNotSupported) { + if err != nil && !errors.Is(err, os.ErrNotExist) { return nil, fmt.Errorf("checking trace event %s/%s: %w", group, symbol, err) } - // Create the kprobe trace event using tracefs. - if err := createTraceFSKprobeEvent(group, symbol, ret); err != nil { - return nil, fmt.Errorf("creating kprobe event on tracefs: %w", err) + // Create the [k,u]probe trace event using tracefs. + if err := createTraceFSProbeEvent(typ, group, symbol, path, offset, ret); err != nil { + return nil, fmt.Errorf("creating probe entry on tracefs: %w", err) } // Get the newly-created trace event's id. @@ -202,65 +297,83 @@ func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) { fd: fd, group: group, name: symbol, - ret: ret, tracefsID: tid, - progType: ebpf.Kprobe, // kernel only allows attaching kprobe programs to kprobe events + typ: typ.PerfEventType(ret), }, nil } -// createTraceFSKprobeEvent creates a new ephemeral trace event by writing to -// /kprobe_events. Returns ErrNotSupported if symbol is not a valid -// kernel symbol, or if it is not traceable with kprobes. -func createTraceFSKprobeEvent(group, symbol string, ret bool) error { +// createTraceFSProbeEvent creates a new ephemeral trace event by writing to +// /[k,u]probe_events. Returns os.ErrNotExist if symbol is not a valid +// kernel symbol, or if it is not traceable with kprobes. Returns os.ErrExist +// if a probe with the same group and symbol already exists. +func createTraceFSProbeEvent(typ probeType, group, symbol, path string, offset uint64, ret bool) error { // Open the kprobe_events file in tracefs. - f, err := os.OpenFile(kprobeEventsPath, os.O_APPEND|os.O_WRONLY, 0666) + f, err := os.OpenFile(typ.EventsPath(), os.O_APPEND|os.O_WRONLY, 0666) if err != nil { - return fmt.Errorf("error opening kprobe_events: %w", err) + return fmt.Errorf("error opening '%s': %w", typ.EventsPath(), err) } defer f.Close() - // The kprobe_events syntax is as follows (see Documentation/trace/kprobetrace.txt): - // p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe - // r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe - // -:[GRP/]EVENT : Clear a probe - // - // Some examples: - // r:ebpf_1234/r_my_kretprobe nf_conntrack_destroy - // p:ebpf_5678/p_my_kprobe __x64_sys_execve - // - // Leaving the kretprobe's MAXACTIVE set to 0 (or absent) will make the - // kernel default to NR_CPUS. This is desired in most eBPF cases since - // subsampling or rate limiting logic can be more accurately implemented in - // the eBPF program itself. See Documentation/kprobes.txt for more details. - pe := fmt.Sprintf("%s:%s/%s %s", kprobePrefix(ret), group, symbol, symbol) + var pe string + switch typ { + case kprobeType: + // The kprobe_events syntax is as follows (see Documentation/trace/kprobetrace.txt): + // p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe + // r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe + // -:[GRP/]EVENT : Clear a probe + // + // Some examples: + // r:ebpf_1234/r_my_kretprobe nf_conntrack_destroy + // p:ebpf_5678/p_my_kprobe __x64_sys_execve + // + // Leaving the kretprobe's MAXACTIVE set to 0 (or absent) will make the + // kernel default to NR_CPUS. This is desired in most eBPF cases since + // subsampling or rate limiting logic can be more accurately implemented in + // the eBPF program itself. + // See Documentation/kprobes.txt for more details. + pe = fmt.Sprintf("%s:%s/%s %s", probePrefix(ret), group, symbol, symbol) + case uprobeType: + // The uprobe_events syntax is as follows: + // p[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a probe + // r[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a return probe + // -:[GRP/]EVENT : Clear a probe + // + // Some examples: + // r:ebpf_1234/readline /bin/bash:0x12345 + // p:ebpf_5678/main_mySymbol /bin/mybin:0x12345 + // + // See Documentation/trace/uprobetracer.txt for more details. + pathOffset := uprobePathOffset(path, offset) + pe = fmt.Sprintf("%s:%s/%s %s", probePrefix(ret), group, symbol, pathOffset) + } _, err = f.WriteString(pe) // Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL // when trying to create a kretprobe for a missing symbol. Make sure ENOENT // is returned to the caller. if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) { - return fmt.Errorf("kernel symbol %s not found: %w", symbol, os.ErrNotExist) + return fmt.Errorf("symbol %s not found: %w", symbol, os.ErrNotExist) } if err != nil { - return fmt.Errorf("writing '%s' to kprobe_events: %w", pe, err) + return fmt.Errorf("writing '%s' to '%s': %w", pe, typ.EventsPath(), err) } return nil } -// closeTraceFSKprobeEvent removes the kprobe with the given group, symbol and kind -// from /kprobe_events. -func closeTraceFSKprobeEvent(group, symbol string) error { - f, err := os.OpenFile(kprobeEventsPath, os.O_APPEND|os.O_WRONLY, 0666) +// closeTraceFSProbeEvent removes the [k,u]probe with the given type, group and symbol +// from /[k,u]probe_events. +func closeTraceFSProbeEvent(typ probeType, group, symbol string) error { + f, err := os.OpenFile(typ.EventsPath(), os.O_APPEND|os.O_WRONLY, 0666) if err != nil { - return fmt.Errorf("error opening kprobe_events: %w", err) + return fmt.Errorf("error opening %s: %w", typ.EventsPath(), err) } defer f.Close() - // See kprobe_events syntax above. Kprobe type does not need to be specified + // See [k,u]probe_events syntax above. The probe type does not need to be specified // for removals. pe := fmt.Sprintf("-:%s/%s", group, symbol) if _, err = f.WriteString(pe); err != nil { - return fmt.Errorf("writing '%s' to kprobe_events: %w", pe, err) + return fmt.Errorf("writing '%s' to '%s': %w", pe, typ.EventsPath(), err) } return nil @@ -288,9 +401,38 @@ func randomGroup(prefix string) (string, error) { return group, nil } -func kprobePrefix(ret bool) string { +func probePrefix(ret bool) string { if ret { return "r" } return "p" } + +// determineRetprobeBit reads a Performance Monitoring Unit's retprobe bit +// from /sys/bus/event_source/devices//format/retprobe. +func determineRetprobeBit(typ probeType) (uint64, error) { + p := filepath.Join("/sys/bus/event_source/devices/", typ.String(), "/format/retprobe") + + data, err := ioutil.ReadFile(p) + if err != nil { + return 0, err + } + + var rp uint64 + n, err := fmt.Sscanf(string(bytes.TrimSpace(data)), "config:%d", &rp) + if err != nil { + return 0, fmt.Errorf("parse retprobe bit: %w", err) + } + if n != 1 { + return 0, fmt.Errorf("parse retprobe bit: expected 1 item, got %d", n) + } + + return rp, nil +} + +func kretprobeBit() (uint64, error) { + kprobeRetprobeBit.once.Do(func() { + kprobeRetprobeBit.value, kprobeRetprobeBit.err = determineRetprobeBit(kprobeType) + }) + return kprobeRetprobeBit.value, kprobeRetprobeBit.err +} diff --git a/vendor/github.com/cilium/ebpf/link/perf_event.go b/vendor/github.com/cilium/ebpf/link/perf_event.go index de973c7412e2..5267a47ec9bb 100644 --- a/vendor/github.com/cilium/ebpf/link/perf_event.go +++ b/vendor/github.com/cilium/ebpf/link/perf_event.go @@ -31,6 +31,10 @@ import ( // exported kernel symbols. kprobe-based (tracefs) trace events can be // created system-wide by writing to the /kprobe_events file, or // they can be scoped to the current process by creating PMU perf events. +// - u(ret)probe: Ephemeral trace events based on user provides ELF binaries +// and offsets. uprobe-based (tracefs) trace events can be +// created system-wide by writing to the /uprobe_events file, or +// they can be scoped to the current process by creating PMU perf events. // - perf event: An object instantiated based on an existing trace event or // kernel symbol. Referred to by fd in userspace. // Exactly one eBPF program can be attached to a perf event. Multiple perf @@ -52,6 +56,16 @@ const ( perfAllThreads = -1 ) +type perfEventType uint8 + +const ( + tracepointEvent perfEventType = iota + kprobeEvent + kretprobeEvent + uprobeEvent + uretprobeEvent +) + // A perfEvent represents a perf event kernel object. Exactly one eBPF program // can be attached to it. It is created based on a tracefs trace event or a // Performance Monitoring Unit (PMU). @@ -66,11 +80,10 @@ type perfEvent struct { // ID of the trace event read from tracefs. Valid IDs are non-zero. tracefsID uint64 - // True for kretprobes/uretprobes. - ret bool + // The event type determines the types of programs that can be attached. + typ perfEventType - fd *internal.FD - progType ebpf.ProgramType + fd *internal.FD } func (pe *perfEvent) isLink() {} @@ -117,13 +130,18 @@ func (pe *perfEvent) Close() error { return fmt.Errorf("closing perf event fd: %w", err) } - switch t := pe.progType; t { - case ebpf.Kprobe: - // For kprobes created using tracefs, clean up the /kprobe_events entry. + switch pe.typ { + case kprobeEvent, kretprobeEvent: + // Clean up kprobe tracefs entry. + if pe.tracefsID != 0 { + return closeTraceFSProbeEvent(kprobeType, pe.group, pe.name) + } + case uprobeEvent, uretprobeEvent: + // Clean up uprobe tracefs entry. if pe.tracefsID != 0 { - return closeTraceFSKprobeEvent(pe.group, pe.name) + return closeTraceFSProbeEvent(uprobeType, pe.group, pe.name) } - case ebpf.TracePoint: + case tracepointEvent: // Tracepoint trace events don't hold any extra resources. return nil } @@ -141,12 +159,21 @@ func (pe *perfEvent) attach(prog *ebpf.Program) error { if pe.fd == nil { return errors.New("cannot attach to nil perf event") } - if t := prog.Type(); t != pe.progType { - return fmt.Errorf("invalid program type (expected %s): %s", pe.progType, t) - } if prog.FD() < 0 { return fmt.Errorf("invalid program: %w", internal.ErrClosedFd) } + switch pe.typ { + case kprobeEvent, kretprobeEvent, uprobeEvent, uretprobeEvent: + if t := prog.Type(); t != ebpf.Kprobe { + return fmt.Errorf("invalid program type (expected %s): %s", ebpf.Kprobe, t) + } + case tracepointEvent: + if t := prog.Type(); t != ebpf.TracePoint { + return fmt.Errorf("invalid program type (expected %s): %s", ebpf.TracePoint, t) + } + default: + return fmt.Errorf("unknown perf event type: %d", pe.typ) + } // The ioctl below will fail when the fd is invalid. kfd, _ := pe.fd.Value() @@ -180,8 +207,8 @@ func unsafeStringPtr(str string) (unsafe.Pointer, error) { // group and name must be alphanumeric or underscore, as required by the kernel. func getTraceEventID(group, name string) (uint64, error) { tid, err := uint64FromFile(tracefsPath, "events", group, name, "id") - if errors.Is(err, ErrNotSupported) { - return 0, fmt.Errorf("trace event %s/%s: %w", group, name, ErrNotSupported) + if errors.Is(err, os.ErrNotExist) { + return 0, fmt.Errorf("trace event %s/%s: %w", group, name, os.ErrNotExist) } if err != nil { return 0, fmt.Errorf("reading trace event ID of %s/%s: %w", group, name, err) @@ -192,20 +219,22 @@ func getTraceEventID(group, name string) (uint64, error) { // getPMUEventType reads a Performance Monitoring Unit's type (numeric identifier) // from /sys/bus/event_source/devices//type. -func getPMUEventType(pmu string) (uint64, error) { - et, err := uint64FromFile("/sys/bus/event_source/devices", pmu, "type") - if errors.Is(err, ErrNotSupported) { - return 0, fmt.Errorf("pmu type %s: %w", pmu, ErrNotSupported) +// +// Returns ErrNotSupported if the pmu type is not supported. +func getPMUEventType(typ probeType) (uint64, error) { + et, err := uint64FromFile("/sys/bus/event_source/devices", typ.String(), "type") + if errors.Is(err, os.ErrNotExist) { + return 0, fmt.Errorf("pmu type %s: %w", typ, ErrNotSupported) } if err != nil { - return 0, fmt.Errorf("reading pmu type %s: %w", pmu, err) + return 0, fmt.Errorf("reading pmu type %s: %w", typ, err) } return et, nil } // openTracepointPerfEvent opens a tracepoint-type perf event. System-wide -// kprobes created by writing to /kprobe_events are tracepoints +// [k,u]probes created by writing to /[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) { attr := unix.PerfEventAttr{ @@ -228,22 +257,13 @@ func openTracepointPerfEvent(tid uint64) (*internal.FD, error) { // and joined onto base. Returns error if base no longer prefixes the path after // joining all components. func uint64FromFile(base string, path ...string) (uint64, error) { - - // Resolve leaf path separately for error feedback. Makes the join onto - // base more readable (can't mix with variadic args). l := filepath.Join(path...) - p := filepath.Join(base, l) if !strings.HasPrefix(p, base) { return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput) } data, err := ioutil.ReadFile(p) - if os.IsNotExist(err) { - // Only echo leaf path, the base path can be prepended at the call site - // if more verbosity is required. - return 0, fmt.Errorf("symbol %s: %w", l, ErrNotSupported) - } if err != nil { return 0, fmt.Errorf("reading file %s: %w", p, err) } diff --git a/vendor/github.com/cilium/ebpf/link/platform.go b/vendor/github.com/cilium/ebpf/link/platform.go new file mode 100644 index 000000000000..eb6f7b7a3769 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/link/platform.go @@ -0,0 +1,25 @@ +package link + +import ( + "fmt" + "runtime" +) + +func platformPrefix(symbol string) string { + + prefix := runtime.GOARCH + + // per https://github.com/golang/go/blob/master/src/go/build/syslist.go + switch prefix { + case "386": + prefix = "ia32" + case "amd64", "amd64p32": + prefix = "x64" + case "arm64", "arm64be": + prefix = "arm64" + default: + return symbol + } + + return fmt.Sprintf("__%s_%s", prefix, symbol) +} diff --git a/vendor/github.com/cilium/ebpf/link/program.go b/vendor/github.com/cilium/ebpf/link/program.go index 0fe9d37c4f89..b90c4574676e 100644 --- a/vendor/github.com/cilium/ebpf/link/program.go +++ b/vendor/github.com/cilium/ebpf/link/program.go @@ -43,7 +43,7 @@ func RawAttachProgram(opts RawAttachProgramOptions) error { } if err := internal.BPFProgAttach(&attr); err != nil { - return fmt.Errorf("can't attach program: %s", err) + return fmt.Errorf("can't attach program: %w", err) } return nil } @@ -69,7 +69,7 @@ func RawDetachProgram(opts RawDetachProgramOptions) error { AttachType: uint32(opts.Attach), } if err := internal.BPFProgDetach(&attr); err != nil { - return fmt.Errorf("can't detach program: %s", err) + return fmt.Errorf("can't detach program: %w", err) } return nil diff --git a/vendor/github.com/cilium/ebpf/link/syscalls.go b/vendor/github.com/cilium/ebpf/link/syscalls.go index 19326c8af800..30e8a8805072 100644 --- a/vendor/github.com/cilium/ebpf/link/syscalls.go +++ b/vendor/github.com/cilium/ebpf/link/syscalls.go @@ -102,6 +102,23 @@ func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) { return internal.NewFD(uint32(ptr)), nil } +type bpfLinkCreateIterAttr struct { + prog_fd uint32 + target_fd uint32 + attach_type ebpf.AttachType + flags uint32 + iter_info internal.Pointer + iter_info_len uint32 +} + +func bpfLinkCreateIter(attr *bpfLinkCreateIterAttr) (*internal.FD, error) { + ptr, err := internal.BPF(internal.BPF_LINK_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) + if err != nil { + return nil, err + } + return internal.NewFD(uint32(ptr)), nil +} + type bpfLinkUpdateAttr struct { linkFd uint32 newProgFd uint32 diff --git a/vendor/github.com/cilium/ebpf/link/tracepoint.go b/vendor/github.com/cilium/ebpf/link/tracepoint.go index 588466b9d856..b8ae04bf0a05 100644 --- a/vendor/github.com/cilium/ebpf/link/tracepoint.go +++ b/vendor/github.com/cilium/ebpf/link/tracepoint.go @@ -11,7 +11,7 @@ import ( // tracepoints. The top-level directory is the group, the event's subdirectory // is the name. Example: // -// Tracepoint("syscalls", "sys_enter_fork") +// Tracepoint("syscalls", "sys_enter_fork", prog) // // Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is // only possible as of kernel 4.14 (commit cf5f5ce). @@ -44,7 +44,7 @@ func Tracepoint(group, name string, prog *ebpf.Program) (Link, error) { tracefsID: tid, group: group, name: name, - progType: ebpf.TracePoint, + typ: tracepointEvent, } if err := pe.attach(prog); err != nil { diff --git a/vendor/github.com/cilium/ebpf/link/uprobe.go b/vendor/github.com/cilium/ebpf/link/uprobe.go new file mode 100644 index 000000000000..2bc395ee3cd2 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/link/uprobe.go @@ -0,0 +1,237 @@ +package link + +import ( + "debug/elf" + "errors" + "fmt" + "os" + "path/filepath" + "regexp" + "sync" + + "github.com/cilium/ebpf" + "github.com/cilium/ebpf/internal" +) + +var ( + uprobeEventsPath = filepath.Join(tracefsPath, "uprobe_events") + + // rgxUprobeSymbol is used to strip invalid characters from the uprobe symbol + // as they are not allowed to be used as the EVENT token in tracefs. + rgxUprobeSymbol = regexp.MustCompile("[^a-zA-Z0-9]+") + + uprobeRetprobeBit = struct { + once sync.Once + value uint64 + err error + }{} +) + +// 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 +} + +// UprobeOptions defines additional parameters that will be used +// when loading Uprobes. +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 +} + +// To open a new Executable, use: +// +// OpenExecutable("/bin/bash") +// +// The returned value can then be used to open Uprobe(s). +func OpenExecutable(path string) (*Executable, error) { + if path == "" { + return nil, fmt.Errorf("path cannot be empty") + } + + f, err := os.Open(path) + if err != nil { + return nil, fmt.Errorf("open file '%s': %w", path, err) + } + defer f.Close() + + se, err := internal.NewSafeELFFile(f) + if err != nil { + return nil, fmt.Errorf("parse ELF file: %w", err) + } + + var ex = Executable{ + path: path, + symbols: make(map[string]elf.Symbol), + } + if err := ex.addSymbols(se.Symbols); err != nil { + return nil, err + } + + if err := ex.addSymbols(se.DynamicSymbols); 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() + if err != nil && !errors.Is(err, elf.ErrNoSymbols) { + return err + } + 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 + } + return nil +} + +func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) { + if s, ok := ex.symbols[symbol]; ok { + return &s, nil + } + return nil, fmt.Errorf("symbol %s not found", symbol) +} + +// Uprobe attaches the given eBPF program to a perf event that fires when the +// given symbol starts executing in the given Executable. +// For example, /bin/bash::main(): +// +// ex, _ = OpenExecutable("/bin/bash") +// ex.Uprobe("main", prog, nil) +// +// When using symbols which belongs to shared libraries, +// an offset must be provided via options: +// +// ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123}) +// +// 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. +func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) { + u, err := ex.uprobe(symbol, prog, opts, false) + if err != nil { + return nil, err + } + + err = u.attach(prog) + if err != nil { + u.Close() + return nil, err + } + + return u, nil +} + +// Uretprobe attaches the given eBPF program to a perf event that fires right +// before the given symbol exits. For example, /bin/bash::main(): +// +// ex, _ = OpenExecutable("/bin/bash") +// ex.Uretprobe("main", prog, nil) +// +// When using symbols which belongs to shared libraries, +// an offset must be provided via options: +// +// ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123}) +// +// 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. +func (ex *Executable) Uretprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) { + u, err := ex.uprobe(symbol, prog, opts, true) + if err != nil { + return nil, err + } + + err = u.attach(prog) + if err != nil { + u.Close() + return nil, err + } + + return u, nil +} + +// uprobe opens a perf event for the given binary/symbol and attaches prog to it. +// If ret is true, create a uretprobe. +func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions, ret bool) (*perfEvent, error) { + if prog == nil { + return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput) + } + if prog.Type() != ebpf.Kprobe { + return nil, fmt.Errorf("eBPF program type %s is not Kprobe: %w", prog.Type(), errInvalidInput) + } + + var offset uint64 + if opts != nil && opts.Offset != 0 { + offset = opts.Offset + } else { + sym, err := ex.symbol(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) + } + + offset = sym.Value + } + + // Use uprobe PMU if the kernel has it available. + tp, err := pmuUprobe(symbol, ex.path, offset, ret) + if err == nil { + return tp, nil + } + if err != nil && !errors.Is(err, ErrNotSupported) { + return nil, fmt.Errorf("creating perf_uprobe PMU: %w", err) + } + + // Use tracefs if uprobe PMU is missing. + tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, ret) + if err != nil { + return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err) + } + + return tp, nil +} + +// 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) +} + +// tracefsUprobe creates a Uprobe tracefs entry. +func tracefsUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) { + return tracefsProbe(uprobeType, symbol, path, offset, ret) +} + +// uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore. +func uprobeSanitizedSymbol(symbol string) string { + return rgxUprobeSymbol.ReplaceAllString(symbol, "_") +} + +// uprobePathOffset creates the PATH:OFFSET token for the tracefs api. +func uprobePathOffset(path string, offset uint64) string { + return fmt.Sprintf("%s:%#x", path, offset) +} + +func uretprobeBit() (uint64, error) { + uprobeRetprobeBit.once.Do(func() { + uprobeRetprobeBit.value, uprobeRetprobeBit.err = determineRetprobeBit(uprobeType) + }) + return uprobeRetprobeBit.value, uprobeRetprobeBit.err +} diff --git a/vendor/github.com/cilium/ebpf/linker.go b/vendor/github.com/cilium/ebpf/linker.go index f843bb25e7ba..6c2efef9e42c 100644 --- a/vendor/github.com/cilium/ebpf/linker.go +++ b/vendor/github.com/cilium/ebpf/linker.go @@ -108,12 +108,16 @@ func fixupJumpsAndCalls(insns asm.Instructions) error { offset := iter.Offset ins := iter.Ins + if ins.Reference == "" { + continue + } + switch { case ins.IsFunctionCall() && ins.Constant == -1: // Rewrite bpf to bpf call callOffset, ok := symbolOffsets[ins.Reference] if !ok { - return fmt.Errorf("instruction %d: reference to missing symbol %q", i, ins.Reference) + return fmt.Errorf("call at %d: reference to missing symbol %q", i, ins.Reference) } ins.Constant = int64(callOffset - offset - 1) @@ -122,10 +126,13 @@ func fixupJumpsAndCalls(insns asm.Instructions) error { // Rewrite jump to label jumpOffset, ok := symbolOffsets[ins.Reference] if !ok { - return fmt.Errorf("instruction %d: reference to missing symbol %q", i, ins.Reference) + return fmt.Errorf("jump at %d: reference to missing symbol %q", i, ins.Reference) } ins.Offset = int16(jumpOffset - offset - 1) + + case ins.IsLoadFromMap() && ins.MapPtr() == -1: + return fmt.Errorf("map %s: %w", ins.Reference, errUnsatisfiedReference) } } diff --git a/vendor/github.com/cilium/ebpf/map.go b/vendor/github.com/cilium/ebpf/map.go index 7ff756b89bae..f257d88c03e3 100644 --- a/vendor/github.com/cilium/ebpf/map.go +++ b/vendor/github.com/cilium/ebpf/map.go @@ -18,6 +18,7 @@ var ( ErrKeyNotExist = errors.New("key does not exist") ErrKeyExist = errors.New("key already exists") ErrIterationAborted = errors.New("iteration aborted") + ErrMapIncompatible = errors.New("map's spec is incompatible with pinned map") ) // MapOptions control loading a map into the kernel. @@ -87,6 +88,23 @@ func (ms *MapSpec) Copy() *MapSpec { return &cpy } +func (ms *MapSpec) clampPerfEventArraySize() error { + if ms.Type != PerfEventArray { + return nil + } + + n, err := internal.PossibleCPUs() + if err != nil { + return fmt.Errorf("perf event array: %w", err) + } + + if n := uint32(n); ms.MaxEntries > n { + ms.MaxEntries = n + } + + return nil +} + // MapKV is used to initialize the contents of a Map. type MapKV struct { Key interface{} @@ -96,19 +114,19 @@ type MapKV struct { func (ms *MapSpec) checkCompatibility(m *Map) error { switch { case m.typ != ms.Type: - return fmt.Errorf("expected type %v, got %v", ms.Type, m.typ) + return fmt.Errorf("expected type %v, got %v: %w", ms.Type, m.typ, ErrMapIncompatible) case m.keySize != ms.KeySize: - return fmt.Errorf("expected key size %v, got %v", ms.KeySize, m.keySize) + return fmt.Errorf("expected key size %v, got %v: %w", ms.KeySize, m.keySize, ErrMapIncompatible) case m.valueSize != ms.ValueSize: - return fmt.Errorf("expected value size %v, got %v", ms.ValueSize, m.valueSize) + return fmt.Errorf("expected value size %v, got %v: %w", ms.ValueSize, m.valueSize, ErrMapIncompatible) case m.maxEntries != ms.MaxEntries: - return fmt.Errorf("expected max entries %v, got %v", ms.MaxEntries, m.maxEntries) + return fmt.Errorf("expected max entries %v, got %v: %w", ms.MaxEntries, m.maxEntries, ErrMapIncompatible) case m.flags != ms.Flags: - return fmt.Errorf("expected flags %v, got %v", ms.Flags, m.flags) + return fmt.Errorf("expected flags %v, got %v: %w", ms.Flags, m.flags, ErrMapIncompatible) } return nil } @@ -171,14 +189,16 @@ 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. +// +// May return an error wrapping ErrMapIncompatible. func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) { - btfs := make(btfHandleCache) - defer btfs.close() + handles := newHandleCache() + defer handles.close() - return newMapWithOptions(spec, opts, btfs) + return newMapWithOptions(spec, opts, handles) } -func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (_ *Map, err error) { +func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) { closeOnError := func(c io.Closer) { if err != nil { c.Close() @@ -202,7 +222,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (_ * defer closeOnError(m) if err := spec.checkCompatibility(m); err != nil { - return nil, fmt.Errorf("use pinned map %s: %s", spec.Name, err) + return nil, fmt.Errorf("use pinned map %s: %w", spec.Name, err) } return m, nil @@ -211,7 +231,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (_ * // Nothing to do here default: - return nil, fmt.Errorf("unsupported pin type %d", int(spec.Pinning)) + return nil, fmt.Errorf("pin type %d: %w", int(spec.Pinning), ErrNotSupported) } var innerFd *internal.FD @@ -224,7 +244,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (_ * return nil, errors.New("inner maps cannot be pinned") } - template, err := createMap(spec.InnerMap, nil, opts, btfs) + template, err := createMap(spec.InnerMap, nil, opts, handles) if err != nil { return nil, err } @@ -233,7 +253,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (_ * innerFd = template.fd } - m, err := createMap(spec, innerFd, opts, btfs) + m, err := createMap(spec, innerFd, opts, handles) if err != nil { return nil, err } @@ -249,7 +269,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (_ * return m, nil } -func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, btfs btfHandleCache) (_ *Map, err error) { +func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) { closeOnError := func(closer io.Closer) { if err != nil { closer.Close() @@ -296,44 +316,54 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, btfs btfHandl return nil, fmt.Errorf("map create: %w", err) } } + if spec.Flags&unix.BPF_F_MMAPABLE > 0 { + if err := haveMmapableMaps(); err != nil { + return nil, fmt.Errorf("map create: %w", err) + } + } + if spec.Flags&unix.BPF_F_INNER_MAP > 0 { + if err := haveInnerMaps(); err != nil { + return nil, fmt.Errorf("map create: %w", err) + } + } - attr := bpfMapCreateAttr{ - mapType: spec.Type, - keySize: spec.KeySize, - valueSize: spec.ValueSize, - maxEntries: spec.MaxEntries, - flags: spec.Flags, - numaNode: spec.NumaNode, + attr := internal.BPFMapCreateAttr{ + MapType: uint32(spec.Type), + KeySize: spec.KeySize, + ValueSize: spec.ValueSize, + MaxEntries: spec.MaxEntries, + Flags: spec.Flags, + NumaNode: spec.NumaNode, } if inner != nil { var err error - attr.innerMapFd, err = inner.Value() + attr.InnerMapFd, err = inner.Value() if err != nil { return nil, fmt.Errorf("map create: %w", err) } } if haveObjName() == nil { - attr.mapName = newBPFObjName(spec.Name) + attr.MapName = internal.NewBPFObjName(spec.Name) } var btfDisabled bool if spec.BTF != nil { - handle, err := btfs.load(btf.MapSpec(spec.BTF)) + handle, err := handles.btfHandle(btf.MapSpec(spec.BTF)) btfDisabled = errors.Is(err, btf.ErrNotSupported) if err != nil && !btfDisabled { return nil, fmt.Errorf("load BTF: %w", err) } if handle != nil { - attr.btfFd = uint32(handle.FD()) - attr.btfKeyTypeID = btf.MapKey(spec.BTF).ID() - attr.btfValueTypeID = btf.MapValue(spec.BTF).ID() + attr.BTFFd = uint32(handle.FD()) + attr.BTFKeyTypeID = uint32(btf.MapKey(spec.BTF).ID()) + attr.BTFValueTypeID = uint32(btf.MapValue(spec.BTF).ID()) } } - fd, err := bpfMapCreate(&attr) + 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) diff --git a/vendor/github.com/cilium/ebpf/prog.go b/vendor/github.com/cilium/ebpf/prog.go index 18edb5453cbb..13bdb6ddad1e 100644 --- a/vendor/github.com/cilium/ebpf/prog.go +++ b/vendor/github.com/cilium/ebpf/prog.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "errors" "fmt" + "io" "math" "path/filepath" "strings" @@ -19,6 +20,8 @@ import ( // ErrNotSupported is returned whenever the kernel doesn't support a feature. var ErrNotSupported = internal.ErrNotSupported +var errUnsatisfiedReference = errors.New("unsatisfied reference") + // ProgramID represents the unique ID of an eBPF program. type ProgramID uint32 @@ -41,6 +44,12 @@ type ProgramOptions struct { // Controls the output buffer size for the verifier. Defaults to // DefaultVerifierLogSize. LogSize int + // An ELF containing the target BTF for this program. It is used both to + // find the correct function to trace and to apply CO-RE relocations. + // This is useful in environments where the kernel BTF is not available + // (containers) or where it is in a non-standard location. Defaults to + // use the kernel BTF from a well-known location. + TargetBTF io.ReaderAt } // ProgramSpec defines a Program. @@ -125,21 +134,21 @@ func NewProgram(spec *ProgramSpec) (*Program, error) { // Loading a program for the first time will perform // feature detection by loading small, temporary programs. func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, error) { - btfs := make(btfHandleCache) - defer btfs.close() + handles := newHandleCache() + defer handles.close() - return newProgramWithOptions(spec, opts, btfs) + prog, err := newProgramWithOptions(spec, opts, handles) + if errors.Is(err, errUnsatisfiedReference) { + return nil, fmt.Errorf("cannot load program without loading its whole collection: %w", err) + } + return prog, err } -func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, btfs btfHandleCache) (*Program, error) { +func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *handleCache) (*Program, error) { if len(spec.Instructions) == 0 { return nil, errors.New("Instructions cannot be empty") } - if len(spec.License) == 0 { - return nil, errors.New("License cannot be empty") - } - if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian { return nil, fmt.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian) } @@ -157,44 +166,36 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, btfs btfHandl kv = v.Kernel() } - insns := make(asm.Instructions, len(spec.Instructions)) - copy(insns, spec.Instructions) - - if err := fixupJumpsAndCalls(insns); err != nil { - return nil, err - } - - buf := bytes.NewBuffer(make([]byte, 0, len(spec.Instructions)*asm.InstructionSize)) - err := insns.Marshal(buf, internal.NativeEndian) - if err != nil { - return nil, err - } - - bytecode := buf.Bytes() - insCount := uint32(len(bytecode) / asm.InstructionSize) attr := &bpfProgLoadAttr{ progType: spec.Type, progFlags: spec.Flags, expectedAttachType: spec.AttachType, - insCount: insCount, - instructions: internal.NewSlicePointer(bytecode), license: internal.NewStringPointer(spec.License), kernelVersion: kv, } if haveObjName() == nil { - attr.progName = newBPFObjName(spec.Name) + attr.progName = internal.NewBPFObjName(spec.Name) + } + + var err error + var targetBTF *btf.Spec + if opts.TargetBTF != nil { + targetBTF, err = handles.btfSpec(opts.TargetBTF) + if err != nil { + return nil, fmt.Errorf("load target BTF: %w", err) + } } var btfDisabled bool + var core btf.COREFixups if spec.BTF != nil { - if relos, err := btf.ProgramRelocations(spec.BTF, nil); err != nil { - return nil, fmt.Errorf("CO-RE relocations: %s", err) - } else if len(relos) > 0 { - return nil, fmt.Errorf("applying CO-RE relocations: %w", ErrNotSupported) + core, err = btf.ProgramFixups(spec.BTF, targetBTF) + if err != nil { + return nil, fmt.Errorf("CO-RE relocations: %w", err) } - handle, err := btfs.load(btf.ProgramSpec(spec.BTF)) + handle, err := handles.btfHandle(btf.ProgramSpec(spec.BTF)) btfDisabled = errors.Is(err, btf.ErrNotSupported) if err != nil && !btfDisabled { return nil, fmt.Errorf("load BTF: %w", err) @@ -221,8 +222,27 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, btfs btfHandl } } + insns, err := core.Apply(spec.Instructions) + if err != nil { + return nil, fmt.Errorf("CO-RE fixup: %w", err) + } + + if err := fixupJumpsAndCalls(insns); err != nil { + return nil, err + } + + buf := bytes.NewBuffer(make([]byte, 0, len(spec.Instructions)*asm.InstructionSize)) + err = insns.Marshal(buf, internal.NativeEndian) + if err != nil { + return nil, err + } + + bytecode := buf.Bytes() + attr.instructions = internal.NewSlicePointer(bytecode) + attr.insCount = uint32(len(bytecode) / asm.InstructionSize) + if spec.AttachTo != "" { - target, err := resolveBTFType(spec.AttachTo, spec.Type, spec.AttachType) + target, err := resolveBTFType(targetBTF, spec.AttachTo, spec.Type, spec.AttachType) if err != nil { return nil, err } @@ -250,7 +270,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, btfs btfHandl } logErr := err - if opts.LogLevel == 0 { + 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 @@ -664,52 +684,45 @@ func (p *Program) ID() (ProgramID, error) { return ProgramID(info.id), nil } -func findKernelType(name string, typ btf.Type) error { - kernel, err := btf.LoadKernelSpec() - if err != nil { - return fmt.Errorf("can't load kernel spec: %w", err) - } - - return kernel.FindType(name, typ) -} - -func resolveBTFType(name string, progType ProgramType, attachType AttachType) (btf.Type, error) { +func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) { type match struct { p ProgramType a AttachType } - target := match{progType, attachType} - switch target { + var target btf.Type + var typeName, featureName string + switch (match{progType, attachType}) { case match{LSM, AttachLSMMac}: - var target btf.Func - err := findKernelType("bpf_lsm_"+name, &target) - if errors.Is(err, btf.ErrNotFound) { - return nil, &internal.UnsupportedFeatureError{ - Name: name + " LSM hook", - } - } - if err != nil { - return nil, fmt.Errorf("resolve BTF for LSM hook %s: %w", name, err) - } - - return &target, nil + target = new(btf.Func) + typeName = "bpf_lsm_" + name + featureName = name + " LSM hook" case match{Tracing, AttachTraceIter}: - var target btf.Func - err := findKernelType("bpf_iter_"+name, &target) - if errors.Is(err, btf.ErrNotFound) { - return nil, &internal.UnsupportedFeatureError{ - Name: name + " iterator", - } - } - if err != nil { - return nil, fmt.Errorf("resolve BTF for iterator %s: %w", name, err) - } - - return &target, nil + target = new(btf.Func) + typeName = "bpf_iter_" + name + featureName = name + " iterator" default: return nil, nil } + + if kernel == nil { + var err error + kernel, err = btf.LoadKernelSpec() + if err != nil { + return nil, fmt.Errorf("load kernel spec: %w", err) + } + } + + err := kernel.FindType(typeName, target) + if errors.Is(err, btf.ErrNotFound) { + return nil, &internal.UnsupportedFeatureError{ + Name: featureName, + } + } + 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 ed8679fa6638..e2437beed2a5 100644 --- a/vendor/github.com/cilium/ebpf/run-tests.sh +++ b/vendor/github.com/cilium/ebpf/run-tests.sh @@ -1,56 +1,95 @@ #!/bin/bash # Test the current package under a different kernel. # Requires virtme and qemu to be installed. +# Examples: +# 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 + +set -euo pipefail + +script="$(realpath "$0")" +readonly script + +# This script is a bit like a Matryoshka doll since it keeps re-executing itself +# in various different contexts: +# +# 1. invoked by the user like run-tests.sh 5.4 +# 2. invoked by go test like run-tests.sh --exec-vm +# 3. invoked by init in the vm like run-tests.sh --exec-test +# +# This allows us to use all available CPU on the host machine to compile our +# code, and then only use the VM to execute the test. This is because the VM +# is usually slower at compiling than the host. +if [[ "${1:-}" = "--exec-vm" ]]; then + shift + + input="$1" + shift + + # Use sudo if /dev/kvm isn't accessible by the current user. + sudo="" + if [[ ! -r /dev/kvm || ! -w /dev/kvm ]]; then + sudo="sudo" + fi + readonly sudo + + testdir="$(dirname "$1")" + output="$(mktemp -d)" + printf -v cmd "%q " "$@" + + if [[ "$(stat -c '%t:%T' -L /proc/$$/fd/0)" == "1:3" ]]; then + # stdin is /dev/null, which doesn't play well with qemu. Use a fifo as a + # blocking substitute. + mkfifo "${output}/fake-stdin" + # Open for reading and writing to avoid blocking. + exec 0<> "${output}/fake-stdin" + 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 -set -eu -set -o pipefail + if [[ ! -e "${output}/success" ]]; then + exit 1 + fi -if [[ "${1:-}" = "--in-vm" ]]; then + $sudo rm -r "$output" + exit 0 +elif [[ "${1:-}" = "--exec-test" ]]; then shift mount -t bpf bpf /sys/fs/bpf mount -t tracefs tracefs /sys/kernel/debug/tracing - export CGO_ENABLED=0 - export GOFLAGS=-mod=readonly - export GOPATH=/run/go-path - export GOPROXY=file:///run/go-path/pkg/mod/cache/download - export GOSUMDB=off - export GOCACHE=/run/go-cache if [[ -d "/run/input/bpf" ]]; then export KERNEL_SELFTESTS="/run/input/bpf" fi - readonly output="${1}" - shift - - echo Running tests... - go test -v -coverpkg=./... -coverprofile="$output/coverage.txt" -count 1 ./... - touch "$output/success" + dmesg -C + if ! "$@"; then + dmesg + exit 1 + fi + touch "/run/output/success" exit 0 fi -# Pull all dependencies, so that we can run tests without the -# vm having network access. -go mod download - -# Use sudo if /dev/kvm isn't accessible by the current user. -sudo="" -if [[ ! -r /dev/kvm || ! -w /dev/kvm ]]; then - sudo="sudo" -fi -readonly sudo - readonly kernel_version="${1:-}" if [[ -z "${kernel_version}" ]]; then echo "Expecting kernel version as first argument" exit 1 fi +shift readonly kernel="linux-${kernel_version}.bz" readonly selftests="linux-${kernel_version}-selftests-bpf.bz" readonly input="$(mktemp -d)" -readonly output="$(mktemp -d)" readonly tmp_dir="${TMPDIR:-/tmp}" readonly branch="${BRANCH:-master}" @@ -60,6 +99,7 @@ fetch() { } fetch "${kernel}" +cp "${tmp_dir}/${kernel}" "${input}/bzImage" if fetch "${selftests}"; then mkdir "${input}/bpf" @@ -68,25 +108,16 @@ else echo "No selftests found, disabling" fi -echo Testing on "${kernel_version}" -$sudo virtme-run --kimg "${tmp_dir}/${kernel}" --memory 512M --pwd \ - --rw \ - --rwdir=/run/input="${input}" \ - --rwdir=/run/output="${output}" \ - --rodir=/run/go-path="$(go env GOPATH)" \ - --rwdir=/run/go-cache="$(go env GOCACHE)" \ - --script-sh "PATH=\"$PATH\" $(realpath "$0") --in-vm /run/output" \ - --qemu-opts -smp 2 # need at least two CPUs for some tests - -if [[ ! -e "${output}/success" ]]; then - echo "Test failed on ${kernel_version}" - exit 1 -else - echo "Test successful on ${kernel_version}" - if [[ -v COVERALLS_TOKEN ]]; then - goveralls -coverprofile="${output}/coverage.txt" -service=semaphore -repotoken "$COVERALLS_TOKEN" - fi +args=(-v -short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...) +if (( $# > 0 )); then + args=("$@") fi -$sudo rm -r "${input}" -$sudo rm -r "${output}" +export GOFLAGS=-mod=readonly +export CGO_ENABLED=0 + +echo Testing on "${kernel_version}" +go test -exec "$script --exec-vm $input" "${args[@]}" +echo "Test successful on ${kernel_version}" + +rm -r "${input}" diff --git a/vendor/github.com/cilium/ebpf/syscalls.go b/vendor/github.com/cilium/ebpf/syscalls.go index c530aadd9a5b..f5a38549bb7c 100644 --- a/vendor/github.com/cilium/ebpf/syscalls.go +++ b/vendor/github.com/cilium/ebpf/syscalls.go @@ -3,6 +3,7 @@ package ebpf import ( "errors" "fmt" + "os" "unsafe" "github.com/cilium/ebpf/internal" @@ -10,19 +11,10 @@ import ( "github.com/cilium/ebpf/internal/unix" ) -// Generic errors returned by BPF syscalls. -var ErrNotExist = errors.New("requested object does not exist") - -// bpfObjName is a null-terminated string made up of -// 'A-Za-z0-9_' characters. -type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte - -// newBPFObjName truncates the result if it is too long. -func newBPFObjName(name string) bpfObjName { - var result bpfObjName - copy(result[:unix.BPF_OBJ_NAME_LEN-1], name) - return result -} +// ErrNotExist is returned when loading a non-existing map or program. +// +// Deprecated: use os.ErrNotExist instead. +var ErrNotExist = os.ErrNotExist // invalidBPFObjNameChar returns true if char may not appear in // a BPF object name. @@ -45,21 +37,6 @@ func invalidBPFObjNameChar(char rune) bool { } } -type bpfMapCreateAttr struct { - mapType MapType - keySize uint32 - valueSize uint32 - maxEntries uint32 - flags uint32 - innerMapFd uint32 // since 4.12 56f668dfe00d - numaNode uint32 // since 4.14 96eabe7a40aa - mapName bpfObjName // since 4.15 ad5b177bd73f - mapIfIndex uint32 - btfFd uint32 - btfKeyTypeID btf.TypeID - btfValueTypeID btf.TypeID -} - type bpfMapOpAttr struct { mapFd uint32 padding uint32 @@ -86,10 +63,10 @@ type bpfMapInfo struct { value_size uint32 max_entries uint32 map_flags uint32 - name bpfObjName // since 4.15 ad5b177bd73f - ifindex uint32 // since 4.16 52775b33bb50 - btf_vmlinux_value_type_id uint32 // since 5.6 85d33df357b6 - netns_dev uint64 // since 4.16 52775b33bb50 + name internal.BPFObjName // since 4.15 ad5b177bd73f + ifindex uint32 // since 4.16 52775b33bb50 + btf_vmlinux_value_type_id uint32 // since 5.6 85d33df357b6 + netns_dev uint64 // since 4.16 52775b33bb50 netns_ino uint64 btf_id uint32 // since 4.18 78958fca7ead btf_key_type_id uint32 // since 4.18 9b2cf328b2ec @@ -104,11 +81,11 @@ type bpfProgLoadAttr struct { logLevel uint32 logSize uint32 logBuf internal.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 AttachType // since 4.17 5e43f899b03a + 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 @@ -132,7 +109,7 @@ type bpfProgInfo struct { created_by_uid uint32 nr_map_ids uint32 map_ids internal.Pointer - name bpfObjName // since 4.15 067cae47771c + name internal.BPFObjName // since 4.15 067cae47771c ifindex uint32 gpl_compatible uint32 netns_dev uint64 @@ -188,7 +165,7 @@ func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) { fd, err := internal.BPF(internal.BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) // As of ~4.20 the verifier can be interrupted by a signal, // and returns EAGAIN in that case. - if err == unix.EAGAIN { + if errors.Is(err, unix.EAGAIN) { continue } @@ -205,23 +182,14 @@ func bpfProgTestRun(attr *bpfProgTestRunAttr) error { return err } -func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) { - fd, err := internal.BPF(internal.BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) - if err != nil { - return nil, err - } - - return internal.NewFD(uint32(fd)), nil -} - var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() error { - _, err := bpfMapCreate(&bpfMapCreateAttr{ - mapType: ArrayOfMaps, - keySize: 4, - valueSize: 4, - maxEntries: 1, + _, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{ + MapType: uint32(ArrayOfMaps), + KeySize: 4, + ValueSize: 4, + MaxEntries: 1, // Invalid file descriptor. - innerMapFd: ^uint32(0), + InnerMapFd: ^uint32(0), }) if errors.Is(err, unix.EINVAL) { return internal.ErrNotSupported @@ -235,12 +203,44 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() error { var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() error { // This checks BPF_F_RDONLY_PROG and BPF_F_WRONLY_PROG. Since // BPF_MAP_FREEZE appeared in 5.2 as well we don't do a separate check. - m, err := bpfMapCreate(&bpfMapCreateAttr{ - mapType: Array, - keySize: 4, - valueSize: 4, - maxEntries: 1, - flags: unix.BPF_F_RDONLY_PROG, + m, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{ + MapType: uint32(Array), + KeySize: 4, + ValueSize: 4, + MaxEntries: 1, + Flags: unix.BPF_F_RDONLY_PROG, + }) + if err != nil { + return internal.ErrNotSupported + } + _ = m.Close() + return nil +}) + +var haveMmapableMaps = internal.FeatureTest("mmapable maps", "5.5", func() error { + // This checks BPF_F_MMAPABLE, which appeared in 5.5 for array maps. + m, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{ + MapType: uint32(Array), + KeySize: 4, + ValueSize: 4, + MaxEntries: 1, + Flags: unix.BPF_F_MMAPABLE, + }) + if err != nil { + return internal.ErrNotSupported + } + _ = m.Close() + return nil +}) + +var haveInnerMaps = internal.FeatureTest("inner maps", "5.10", func() error { + // This checks BPF_F_INNER_MAP, which appeared in 5.10. + m, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{ + MapType: uint32(Array), + KeySize: 4, + ValueSize: 4, + MaxEntries: 1, + Flags: unix.BPF_F_INNER_MAP, }) if err != nil { return internal.ErrNotSupported @@ -329,7 +329,7 @@ func objGetNextID(cmd internal.BPFCmd, start uint32) (uint32, error) { startID: start, } _, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) - return attr.nextID, wrapObjError(err) + return attr.nextID, err } func bpfMapBatch(cmd internal.BPFCmd, m *internal.FD, inBatch, outBatch, keys, values internal.Pointer, count uint32, opts *BatchOptions) (uint32, error) { @@ -355,32 +355,21 @@ func bpfMapBatch(cmd internal.BPFCmd, m *internal.FD, inBatch, outBatch, keys, v return attr.count, wrapMapError(err) } -func wrapObjError(err error) error { - if err == nil { - return nil - } - if errors.Is(err, unix.ENOENT) { - return fmt.Errorf("%w", ErrNotExist) - } - - return errors.New(err.Error()) -} - func wrapMapError(err error) error { if err == nil { return nil } if errors.Is(err, unix.ENOENT) { - return ErrKeyNotExist + return internal.SyscallError(ErrKeyNotExist, unix.ENOENT) } if errors.Is(err, unix.EEXIST) { - return ErrKeyExist + return internal.SyscallError(ErrKeyExist, unix.EEXIST) } if errors.Is(err, unix.ENOTSUPP) { - return ErrNotSupported + return internal.SyscallError(ErrNotSupported, unix.ENOTSUPP) } return err @@ -417,15 +406,15 @@ func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) { } var haveObjName = internal.FeatureTest("object names", "4.15", func() error { - attr := bpfMapCreateAttr{ - mapType: Array, - keySize: 4, - valueSize: 4, - maxEntries: 1, - mapName: newBPFObjName("feature_test"), + attr := internal.BPFMapCreateAttr{ + MapType: uint32(Array), + KeySize: 4, + ValueSize: 4, + MaxEntries: 1, + MapName: internal.NewBPFObjName("feature_test"), } - fd, err := bpfMapCreate(&attr) + fd, err := internal.BPFMapCreate(&attr) if err != nil { return internal.ErrNotSupported } @@ -439,15 +428,15 @@ var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func() return err } - attr := bpfMapCreateAttr{ - mapType: Array, - keySize: 4, - valueSize: 4, - maxEntries: 1, - mapName: newBPFObjName(".test"), + attr := internal.BPFMapCreateAttr{ + MapType: uint32(Array), + KeySize: 4, + ValueSize: 4, + MaxEntries: 1, + MapName: internal.NewBPFObjName(".test"), } - fd, err := bpfMapCreate(&attr) + fd, err := internal.BPFMapCreate(&attr) if err != nil { return internal.ErrNotSupported } @@ -458,14 +447,14 @@ var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func() var haveBatchAPI = internal.FeatureTest("map batch api", "5.6", func() error { var maxEntries uint32 = 2 - attr := bpfMapCreateAttr{ - mapType: Hash, - keySize: 4, - valueSize: 4, - maxEntries: maxEntries, + attr := internal.BPFMapCreateAttr{ + MapType: uint32(Hash), + KeySize: 4, + ValueSize: 4, + MaxEntries: maxEntries, } - fd, err := bpfMapCreate(&attr) + fd, err := internal.BPFMapCreate(&attr) if err != nil { return internal.ErrNotSupported } @@ -487,5 +476,5 @@ func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) { id: id, } ptr, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) - return internal.NewFD(uint32(ptr)), wrapObjError(err) + return internal.NewFD(uint32(ptr)), err } diff --git a/vendor/github.com/cilium/ebpf/types.go b/vendor/github.com/cilium/ebpf/types.go index f4d1a8c41006..441a82fe4c1c 100644 --- a/vendor/github.com/cilium/ebpf/types.go +++ b/vendor/github.com/cilium/ebpf/types.go @@ -85,6 +85,10 @@ const ( SkStorage // DevMapHash - Hash-based indexing scheme for references to network devices. DevMapHash + StructOpts + RingBuf + InodeStorage + TaskStorage ) // hasPerCPUValue returns true if the Map stores a value per CPU. diff --git a/vendor/github.com/cilium/ebpf/types_string.go b/vendor/github.com/cilium/ebpf/types_string.go index 976bd76be010..c25f7656479b 100644 --- a/vendor/github.com/cilium/ebpf/types_string.go +++ b/vendor/github.com/cilium/ebpf/types_string.go @@ -34,11 +34,15 @@ func _() { _ = x[Stack-23] _ = x[SkStorage-24] _ = x[DevMapHash-25] + _ = x[StructOpts-26] + _ = x[RingBuf-27] + _ = x[InodeStorage-28] + _ = x[TaskStorage-29] } -const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHash" +const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOptsRingBufInodeStorageTaskStorage" -var _MapType_index = [...]uint8{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248} +var _MapType_index = [...]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} func (i MapType) String() string { if i >= MapType(len(_MapType_index)-1) { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go new file mode 100644 index 000000000000..4b03d4c715c5 --- /dev/null +++ b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go @@ -0,0 +1,16 @@ +package apparmor + +import "errors" + +var ( + // IsEnabled returns true if apparmor is enabled for the host. + IsEnabled = isEnabled + + // ApplyProfile will apply the profile with the specified name to the process after + // the next exec. It is only supported on Linux and produces an ErrApparmorNotEnabled + // on other platforms. + ApplyProfile = applyProfile + + // ErrApparmorNotEnabled indicates that AppArmor is not enabled or not supported. + ErrApparmorNotEnabled = errors.New("apparmor: config provided but apparmor not supported") +) diff --git a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go index 5da14fb3b16a..744d4e57054d 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go @@ -15,8 +15,8 @@ var ( checkAppArmor sync.Once ) -// IsEnabled returns true if apparmor is enabled for the host. -func IsEnabled() bool { +// isEnabled returns true if apparmor is enabled for the host. +func isEnabled() bool { checkAppArmor.Do(func() { if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil { buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled") @@ -57,9 +57,10 @@ func changeOnExec(name string) error { return nil } -// ApplyProfile will apply the profile with the specified name to the process after -// the next exec. -func ApplyProfile(name string) error { +// applyProfile will apply the profile with the specified name to the process after +// the next exec. It is only supported on Linux and produces an error on other +// platforms. +func applyProfile(name string) error { if name == "" { return nil } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go index 0bc473f810bc..1adadafec8ec 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go @@ -2,17 +2,11 @@ package apparmor -import ( - "errors" -) - -var ErrApparmorNotEnabled = errors.New("apparmor: config provided but apparmor not supported") - -func IsEnabled() bool { +func isEnabled() bool { return false } -func ApplyProfile(name string) error { +func applyProfile(name string) error { if name != "" { return ErrApparmorNotEnabled } 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 3572a5eae8ee..c08477cbb354 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 @@ -258,9 +258,9 @@ func (e *Emulator) Apply(rule devices.Rule) error { if rule.Allow { return e.allow(innerRule) - } else { - return e.deny(innerRule) } + + return e.deny(innerRule) } // EmulatorFromList takes a reader to a "devices.list"-like source, and returns @@ -371,3 +371,12 @@ func (source *Emulator) Transition(target *Emulator) ([]*devices.Rule, error) { } return transitionRules, nil } + +// Rules returns the minimum set of rules necessary to convert a *deny-all* +// cgroup to the emulated filter state (note that this is not the same as a +// default cgroupv1 cgroup -- which is allow-all). This is effectively just a +// wrapper around Transition() with the source emulator being an empty cgroup. +func (e *Emulator) Rules() ([]*devices.Rule, error) { + defaultCgroup := &Emulator{defaultAllow: false} + return defaultCgroup.Transition(e) +} 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 fcd3746e0238..96cbca3916e5 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 @@ -11,6 +11,7 @@ import ( "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" @@ -22,11 +23,44 @@ const ( ) // DeviceFilter returns eBPF device filter program and its license string -func DeviceFilter(devices []*devices.Rule) (asm.Instructions, string, error) { - p := &program{} +func DeviceFilter(rules []*devices.Rule) (asm.Instructions, string, error) { + // Generate the minimum ruleset for the device rules we are given. While we + // don't care about minimum transitions in cgroupv2, using the emulator + // gives us a guarantee that the behaviour of devices filtering is the same + // as cgroupv1, including security hardenings to avoid misconfiguration + // (such as punching holes in wildcard rules). + emu := new(devicesemulator.Emulator) + for _, rule := range rules { + if err := emu.Apply(*rule); err != nil { + return nil, "", err + } + } + cleanRules, err := emu.Rules() + if err != nil { + return nil, "", err + } + + p := &program{ + defaultAllow: emu.IsBlacklist(), + } p.init() - for i := len(devices) - 1; i >= 0; i-- { - if err := p.appendDevice(devices[i]); err != nil { + + for idx, rule := range cleanRules { + if rule.Type == devices.WildcardDevice { + // We can safely skip over wildcard entries because there should + // 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()) + } + 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()) + } + if err := p.appendRule(rule); err != nil { return nil, "", err } } @@ -35,9 +69,9 @@ func DeviceFilter(devices []*devices.Rule) (asm.Instructions, string, error) { } type program struct { - insts asm.Instructions - hasWildCard bool - blockID int + insts asm.Instructions + defaultAllow bool + blockID int } func (p *program) init() { @@ -67,39 +101,35 @@ func (p *program) init() { asm.LoadMem(asm.R5, asm.R1, 8, asm.Word)) } -// appendDevice needs to be called from the last element of OCI linux.resources.devices to the head element. -func (p *program) appendDevice(dev *devices.Rule) error { +// appendRule rule converts an OCI rule to the relevant eBPF block and adds it +// to the in-progress filter program. In order to operate properly, it must be +// called with a "clean" rule list (generated by devices.Emulator.Rules() -- +// with any "a" rules removed). +func (p *program) appendRule(rule *devices.Rule) error { if p.blockID < 0 { return errors.New("the program is finalized") } - if p.hasWildCard { - // All entries after wildcard entry are ignored - return nil - } - bpfType := int32(-1) - hasType := true - switch dev.Type { - case 'c': + var bpfType int32 + switch rule.Type { + case devices.CharDevice: bpfType = int32(unix.BPF_DEVCG_DEV_CHAR) - case 'b': + case devices.BlockDevice: bpfType = int32(unix.BPF_DEVCG_DEV_BLOCK) - case 'a': - hasType = false default: - // if not specified in OCI json, typ is set to DeviceTypeAll - return errors.Errorf("invalid Type %q", string(dev.Type)) + // We do not permit 'a', nor any other types we don't know about. + return errors.Errorf("invalid type %q", string(rule.Type)) } - if dev.Major > math.MaxUint32 { - return errors.Errorf("invalid major %d", dev.Major) + if rule.Major > math.MaxUint32 { + return errors.Errorf("invalid major %d", rule.Major) } - if dev.Minor > math.MaxUint32 { - return errors.Errorf("invalid minor %d", dev.Major) + if rule.Minor > math.MaxUint32 { + return errors.Errorf("invalid minor %d", rule.Major) } - hasMajor := dev.Major >= 0 // if not specified in OCI json, major is set to -1 - hasMinor := dev.Minor >= 0 + hasMajor := rule.Major >= 0 // if not specified in OCI json, major is set to -1 + hasMinor := rule.Minor >= 0 bpfAccess := int32(0) - for _, r := range dev.Permissions { + for _, r := range rule.Permissions { switch r { case 'r': bpfAccess |= unix.BPF_DEVCG_ACC_READ @@ -119,12 +149,10 @@ func (p *program) appendDevice(dev *devices.Rule) error { nextBlockSym = "block-" + strconv.Itoa(p.blockID+1) prevBlockLastIdx = len(p.insts) - 1 ) - if hasType { - p.insts = append(p.insts, - // if (R2 != bpfType) goto next - asm.JNE.Imm(asm.R2, bpfType, nextBlockSym), - ) - } + p.insts = append(p.insts, + // if (R2 != bpfType) goto next + asm.JNE.Imm(asm.R2, bpfType, nextBlockSym), + ) if hasAccess { p.insts = append(p.insts, // if (R3 & bpfAccess != R3 /* use R1 as a temp var */) goto next @@ -136,19 +164,16 @@ func (p *program) appendDevice(dev *devices.Rule) error { if hasMajor { p.insts = append(p.insts, // if (R4 != major) goto next - asm.JNE.Imm(asm.R4, int32(dev.Major), nextBlockSym), + asm.JNE.Imm(asm.R4, int32(rule.Major), nextBlockSym), ) } if hasMinor { p.insts = append(p.insts, // if (R5 != minor) goto next - asm.JNE.Imm(asm.R5, int32(dev.Minor), nextBlockSym), + asm.JNE.Imm(asm.R5, int32(rule.Minor), nextBlockSym), ) } - if !hasType && !hasAccess && !hasMajor && !hasMinor { - p.hasWildCard = true - } - p.insts = append(p.insts, acceptBlock(dev.Allow)...) + p.insts = append(p.insts, acceptBlock(rule.Allow)...) // set blockSym to the first instruction we added in this iteration p.insts[prevBlockLastIdx+1] = p.insts[prevBlockLastIdx+1].Sym(blockSym) p.blockID++ @@ -156,14 +181,14 @@ func (p *program) appendDevice(dev *devices.Rule) error { } func (p *program) finalize() (asm.Instructions, error) { - if p.hasWildCard { - // acceptBlock with asm.Return() is already inserted - return p.insts, nil + var v int32 + if p.defaultAllow { + v = 1 } blockSym := "block-" + strconv.Itoa(p.blockID) p.insts = append(p.insts, - // R0 <- 0 - asm.Mov.Imm32(asm.R0, 0).Sym(blockSym), + // R0 <- v + asm.Mov.Imm32(asm.R0, v).Sym(blockSym), asm.Return(), ) p.blockID = -1 @@ -171,7 +196,7 @@ func (p *program) finalize() (asm.Instructions, error) { } func acceptBlock(accept bool) asm.Instructions { - v := int32(0) + var v int32 if accept { v = 1 } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf.go deleted file mode 100644 index 3bee21cb7de3..000000000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf.go +++ /dev/null @@ -1,57 +0,0 @@ -package ebpf - -import ( - "github.com/cilium/ebpf" - "github.com/cilium/ebpf/asm" - "github.com/cilium/ebpf/link" - "github.com/pkg/errors" - "golang.org/x/sys/unix" -) - -// LoadAttachCgroupDeviceFilter installs eBPF device filter program to /sys/fs/cgroup/ directory. -// -// Requires the system to be running in cgroup2 unified-mode with kernel >= 4.15 . -// -// https://github.com/torvalds/linux/commit/ebc614f687369f9df99828572b1d85a7c2de3d92 -func LoadAttachCgroupDeviceFilter(insts asm.Instructions, license string, dirFD int) (func() error, error) { - nilCloser := func() error { - return nil - } - // Increase `ulimit -l` limit to avoid BPF_PROG_LOAD error (#2167). - // This limit is not inherited into the container. - memlockLimit := &unix.Rlimit{ - Cur: unix.RLIM_INFINITY, - Max: unix.RLIM_INFINITY, - } - _ = unix.Setrlimit(unix.RLIMIT_MEMLOCK, memlockLimit) - spec := &ebpf.ProgramSpec{ - Type: ebpf.CGroupDevice, - Instructions: insts, - License: license, - } - prog, err := ebpf.NewProgram(spec) - if err != nil { - return nilCloser, err - } - err = link.RawAttachProgram(link.RawAttachProgramOptions{ - Target: dirFD, - Program: prog, - Attach: ebpf.AttachCGroupDevice, - Flags: unix.BPF_F_ALLOW_MULTI, - }) - if err != nil { - return nilCloser, errors.Wrap(err, "failed to call BPF_PROG_ATTACH (BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI)") - } - closer := func() error { - err = link.RawDetachProgram(link.RawDetachProgramOptions{ - Target: dirFD, - Program: prog, - Attach: ebpf.AttachCGroupDevice, - }) - if err != nil { - return errors.Wrap(err, "failed to call BPF_PROG_DETACH (BPF_CGROUP_DEVICE)") - } - return nil - } - return closer, nil -} 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 new file mode 100644 index 000000000000..6c8de80dd865 --- /dev/null +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/ebpf/ebpf_linux.go @@ -0,0 +1,253 @@ +package ebpf + +import ( + "fmt" + "os" + "runtime" + "sync" + "unsafe" + + "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" +) + +func nilCloser() error { + return nil +} + +func findAttachedCgroupDeviceFilters(dirFd int) ([]*ebpf.Program, error) { + type bpfAttrQuery struct { + TargetFd uint32 + AttachType uint32 + QueryType uint32 + AttachFlags uint32 + ProgIds uint64 // __aligned_u64 + ProgCnt uint32 + } + + // Currently you can only have 64 eBPF programs attached to a cgroup. + size := 64 + retries := 0 + for retries < 10 { + progIds := make([]uint32, size) + query := bpfAttrQuery{ + TargetFd: uint32(dirFd), + AttachType: uint32(unix.BPF_CGROUP_DEVICE), + ProgIds: uint64(uintptr(unsafe.Pointer(&progIds[0]))), + ProgCnt: uint32(len(progIds)), + } + + // Fetch the list of program ids. + _, _, errno := unix.Syscall(unix.SYS_BPF, + uintptr(unix.BPF_PROG_QUERY), + uintptr(unsafe.Pointer(&query)), + unsafe.Sizeof(query)) + size = int(query.ProgCnt) + runtime.KeepAlive(query) + if errno != 0 { + // On ENOSPC we get the correct number of programs. + if errno == unix.ENOSPC { + retries++ + continue + } + return nil, fmt.Errorf("bpf_prog_query(BPF_CGROUP_DEVICE) failed: %w", errno) + } + + // Convert the ids to program handles. + progIds = progIds[:size] + programs := make([]*ebpf.Program, 0, len(progIds)) + for _, progId := range progIds { + program, err := ebpf.NewProgramFromID(ebpf.ProgramID(progId)) + if err != nil { + // We skip over programs that give us -EACCES or -EPERM. This + // is necessary because there may be BPF programs that have + // been attached (such as with --systemd-cgroup) which have an + // LSM label that blocks us from interacting with the program. + // + // Because additional BPF_CGROUP_DEVICE programs only can add + // restrictions, there's no real issue with just ignoring these + // programs (and stops runc from breaking on distributions with + // very strict SELinux policies). + if errors.Is(err, os.ErrPermission) { + logrus.Debugf("ignoring existing CGROUP_DEVICE program (prog_id=%v) which cannot be accessed by runc -- likely due to LSM policy: %v", progId, err) + continue + } + return nil, fmt.Errorf("cannot fetch program from id: %w", err) + } + programs = append(programs, program) + } + runtime.KeepAlive(progIds) + return programs, nil + } + + return nil, errors.New("could not get complete list of CGROUP_DEVICE programs") +} + +var ( + haveBpfProgReplaceBool bool + haveBpfProgReplaceOnce sync.Once +) + +// Loosely based on the BPF_F_REPLACE support check in +// . +// +// TODO: move this logic to cilium/ebpf +func haveBpfProgReplace() bool { + haveBpfProgReplaceOnce.Do(func() { + prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ + Type: ebpf.CGroupDevice, + License: "MIT", + Instructions: asm.Instructions{ + asm.Mov.Imm(asm.R0, 0), + asm.Return(), + }, + }) + if err != nil { + logrus.Debugf("checking for BPF_F_REPLACE support: ebpf.NewProgram failed: %v", err) + return + } + defer prog.Close() + + devnull, err := os.Open("/dev/null") + if err != nil { + logrus.Debugf("checking for BPF_F_REPLACE support: open dummy target fd: %v", err) + return + } + defer devnull.Close() + + // We know that we have BPF_PROG_ATTACH since we can load + // BPF_CGROUP_DEVICE programs. If passing BPF_F_REPLACE gives us EINVAL + // we know that the feature isn't present. + err = link.RawAttachProgram(link.RawAttachProgramOptions{ + // We rely on this fd being checked after attachFlags. + Target: int(devnull.Fd()), + // Attempt to "replace" bad fds with this program. + Program: prog, + Attach: ebpf.AttachCGroupDevice, + Flags: unix.BPF_F_ALLOW_MULTI | unix.BPF_F_REPLACE, + }) + if errors.Is(err, unix.EINVAL) { + // not supported + return + } + // attach_flags test succeded. + if !errors.Is(err, unix.EBADF) { + logrus.Debugf("checking for BPF_F_REPLACE: got unexpected (not EBADF or EINVAL) error: %v", err) + } + haveBpfProgReplaceBool = true + }) + return haveBpfProgReplaceBool +} + +// LoadAttachCgroupDeviceFilter installs eBPF device filter program to /sys/fs/cgroup/ directory. +// +// Requires the system to be running in cgroup2 unified-mode with kernel >= 4.15 . +// +// https://github.com/torvalds/linux/commit/ebc614f687369f9df99828572b1d85a7c2de3d92 +func LoadAttachCgroupDeviceFilter(insts asm.Instructions, license string, dirFd int) (func() error, error) { + // Increase `ulimit -l` limit to avoid BPF_PROG_LOAD error (#2167). + // This limit is not inherited into the container. + memlockLimit := &unix.Rlimit{ + Cur: unix.RLIM_INFINITY, + Max: unix.RLIM_INFINITY, + } + _ = unix.Setrlimit(unix.RLIMIT_MEMLOCK, memlockLimit) + + // Get the list of existing programs. + oldProgs, err := findAttachedCgroupDeviceFilters(dirFd) + if err != nil { + return nilCloser, err + } + useReplaceProg := haveBpfProgReplace() && len(oldProgs) == 1 + + // Generate new program. + spec := &ebpf.ProgramSpec{ + Type: ebpf.CGroupDevice, + Instructions: insts, + License: license, + } + prog, err := ebpf.NewProgram(spec) + if err != nil { + return nilCloser, err + } + + // If there is only one old program, we can just replace it directly. + var ( + replaceProg *ebpf.Program + attachFlags uint32 = unix.BPF_F_ALLOW_MULTI + ) + if useReplaceProg { + replaceProg = oldProgs[0] + attachFlags |= unix.BPF_F_REPLACE + } + err = link.RawAttachProgram(link.RawAttachProgramOptions{ + Target: dirFd, + Program: prog, + Replace: replaceProg, + Attach: ebpf.AttachCGroupDevice, + Flags: attachFlags, + }) + if err != nil { + return nilCloser, fmt.Errorf("failed to call BPF_PROG_ATTACH (BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI): %w", err) + } + closer := func() error { + err = link.RawDetachProgram(link.RawDetachProgramOptions{ + Target: dirFd, + Program: prog, + Attach: ebpf.AttachCGroupDevice, + }) + if err != nil { + return fmt.Errorf("failed to call BPF_PROG_DETACH (BPF_CGROUP_DEVICE): %w", err) + } + // TODO: Should we attach the old filters back in this case? Otherwise + // we fail-open on a security feature, which is a bit scary. + return nil + } + if !useReplaceProg { + logLevel := logrus.DebugLevel + // If there was more than one old program, give a warning (since this + // really shouldn't happen with runc-managed cgroups) and then detach + // all the old programs. + if len(oldProgs) > 1 { + // NOTE: Ideally this should be a warning but it turns out that + // systemd-managed cgroups trigger this warning (apparently + // systemd doesn't delete old non-systemd programs when + // setting properties). + logrus.Infof("found more than one filter (%d) attached to a cgroup -- removing extra filters!", len(oldProgs)) + logLevel = logrus.InfoLevel + } + for idx, oldProg := range oldProgs { + // Output some extra debug info. + if info, err := oldProg.Info(); err == nil { + fields := logrus.Fields{ + "type": info.Type.String(), + "tag": info.Tag, + "name": info.Name, + } + if id, ok := info.ID(); ok { + fields["id"] = id + } + if runCount, ok := info.RunCount(); ok { + fields["run_count"] = runCount + } + if runtime, ok := info.Runtime(); ok { + fields["runtime"] = runtime.String() + } + logrus.WithFields(fields).Logf(logLevel, "removing old filter %d from cgroup", idx) + } + err = link.RawDetachProgram(link.RawDetachProgramOptions{ + Target: dirFd, + Program: oldProg, + Attach: ebpf.AttachCGroupDevice, + }) + if err != nil { + return closer, fmt.Errorf("failed to call BPF_PROG_DETACH (BPF_CGROUP_DEVICE) on old filter program: %w", err) + } + } + } + return closer, nil +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/open.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go similarity index 71% rename from vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/open.go rename to vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go index 49af83b3c0dd..5f6ab9fd6999 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/open.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go @@ -1,6 +1,7 @@ -package fscommon +package cgroups import ( + "bytes" "os" "strings" "sync" @@ -10,6 +11,54 @@ import ( "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. +func OpenFile(dir, file string, flags int) (*os.File, error) { + if dir == "" { + return nil, errors.Errorf("no directory specified for %s", file) + } + return openFile(dir, file, flags) +} + +// ReadFile reads data from a cgroup file in dir. +// It is supposed to be used for cgroup files only. +func ReadFile(dir, file string) (string, error) { + fd, err := OpenFile(dir, file, unix.O_RDONLY) + if err != nil { + return "", err + } + defer fd.Close() + var buf bytes.Buffer + + _, err = buf.ReadFrom(fd) + return buf.String(), err +} + +// WriteFile writes data to a cgroup file in dir. +// It is supposed to be used for cgroup files only. +func WriteFile(dir, file, data string) error { + fd, err := OpenFile(dir, file, unix.O_WRONLY) + if err != nil { + return err + } + defer fd.Close() + if err := retryingWriteFile(fd, data); err != nil { + return errors.Wrapf(err, "failed to write %q", data) + } + return nil +} + +func retryingWriteFile(fd *os.File, data string) error { + for { + _, err := fd.Write([]byte(data)) + if errors.Is(err, unix.EINTR) { + logrus.Infof("interrupted while writing %s to %s", data, fd.Name()) + continue + } + return err + } +} + const ( cgroupfsDir = "/sys/fs/cgroup" cgroupfsPrefix = cgroupfsDir + "/" @@ -28,7 +77,8 @@ var ( func prepareOpenat2() error { prepOnce.Do(func() { fd, err := unix.Openat2(-1, cgroupfsDir, &unix.OpenHow{ - Flags: unix.O_DIRECTORY | unix.O_PATH}) + Flags: unix.O_DIRECTORY | unix.O_PATH, + }) if err != nil { prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err} if err != unix.ENOSYS { @@ -52,7 +102,6 @@ func prepareOpenat2() error { // cgroupv2 has a single mountpoint and no "cpu,cpuacct" symlinks resolveFlags |= unix.RESOLVE_NO_XDEV | unix.RESOLVE_NO_SYMLINKS } - }) return prepErr @@ -60,10 +109,7 @@ func prepareOpenat2() error { // 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) { - if dir == "" { - return nil, errors.Errorf("no directory specified for %s", file) - } +func openFile(dir, file string, flags int) (*os.File, error) { mode := os.FileMode(0) if TestMode && flags&os.O_WRONLY != 0 { // "emulate" cgroup fs for unit tests 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 05fec2603072..88012a2f5f18 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go @@ -6,15 +6,17 @@ import ( "bufio" "fmt" "os" + "path/filepath" "strconv" "strings" "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) type BlkioGroup struct { + weightFilename string + weightDeviceFilename string } func (s *BlkioGroup) Name() string { @@ -26,42 +28,47 @@ func (s *BlkioGroup) Apply(path string, d *cgroupData) error { } func (s *BlkioGroup) Set(path string, r *configs.Resources) error { + s.detectWeightFilenames(path) if r.BlkioWeight != 0 { - if err := fscommon.WriteFile(path, "blkio.weight", strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil { + if err := cgroups.WriteFile(path, s.weightFilename, strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil { return err } } if r.BlkioLeafWeight != 0 { - if err := fscommon.WriteFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(r.BlkioLeafWeight), 10)); err != nil { + if err := cgroups.WriteFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(r.BlkioLeafWeight), 10)); err != nil { return err } } for _, wd := range r.BlkioWeightDevice { - if err := fscommon.WriteFile(path, "blkio.weight_device", wd.WeightString()); err != nil { - return err + if wd.Weight != 0 { + if err := cgroups.WriteFile(path, s.weightDeviceFilename, wd.WeightString()); err != nil { + return err + } } - if err := fscommon.WriteFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { - return err + if wd.LeafWeight != 0 { + if err := cgroups.WriteFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { + return err + } } } for _, td := range r.BlkioThrottleReadBpsDevice { - if err := fscommon.WriteFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil { + if err := cgroups.WriteFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil { return err } } for _, td := range r.BlkioThrottleWriteBpsDevice { - if err := fscommon.WriteFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil { + if err := cgroups.WriteFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil { return err } } for _, td := range r.BlkioThrottleReadIOPSDevice { - if err := fscommon.WriteFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil { + if err := cgroups.WriteFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil { return err } } for _, td := range r.BlkioThrottleWriteIOPSDevice { - if err := fscommon.WriteFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil { + if err := cgroups.WriteFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil { return err } } @@ -106,7 +113,7 @@ func splitBlkioStatLine(r rune) bool { func getBlkioStat(dir, file string) ([]cgroups.BlkioStatEntry, error) { var blkioStats []cgroups.BlkioStatEntry - f, err := fscommon.OpenFile(dir, file, os.O_RDONLY) + f, err := cgroups.OpenFile(dir, file, os.O_RDONLY) if err != nil { if os.IsNotExist(err) { return blkioStats, nil @@ -161,7 +168,7 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { filename string blkioStatEntriesPtr *[]cgroups.BlkioStatEntry } - var bfqDebugStats = []blkioStatInfo{ + bfqDebugStats := []blkioStatInfo{ { filename: "blkio.bfq.sectors_recursive", blkioStatEntriesPtr: &stats.BlkioStats.SectorsRecursive, @@ -195,7 +202,7 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { blkioStatEntriesPtr: &stats.BlkioStats.IoServiceBytesRecursive, }, } - var bfqStats = []blkioStatInfo{ + bfqStats := []blkioStatInfo{ { filename: "blkio.bfq.io_serviced_recursive", blkioStatEntriesPtr: &stats.BlkioStats.IoServicedRecursive, @@ -205,7 +212,7 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { blkioStatEntriesPtr: &stats.BlkioStats.IoServiceBytesRecursive, }, } - var cfqStats = []blkioStatInfo{ + cfqStats := []blkioStatInfo{ { filename: "blkio.sectors_recursive", blkioStatEntriesPtr: &stats.BlkioStats.SectorsRecursive, @@ -239,7 +246,7 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { blkioStatEntriesPtr: &stats.BlkioStats.IoServiceBytesRecursive, }, } - var throttleRecursiveStats = []blkioStatInfo{ + throttleRecursiveStats := []blkioStatInfo{ { filename: "blkio.throttle.io_serviced_recursive", blkioStatEntriesPtr: &stats.BlkioStats.IoServicedRecursive, @@ -249,7 +256,7 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { blkioStatEntriesPtr: &stats.BlkioStats.IoServiceBytesRecursive, }, } - var baseStats = []blkioStatInfo{ + baseStats := []blkioStatInfo{ { filename: "blkio.throttle.io_serviced", blkioStatEntriesPtr: &stats.BlkioStats.IoServicedRecursive, @@ -259,7 +266,7 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { blkioStatEntriesPtr: &stats.BlkioStats.IoServiceBytesRecursive, }, } - var orderedStats = [][]blkioStatInfo{ + orderedStats := [][]blkioStatInfo{ bfqDebugStats, bfqStats, cfqStats, @@ -280,7 +287,7 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { return err } *statInfo.blkioStatEntriesPtr = blkioStats - //finish if all stats are gathered + // finish if all stats are gathered if i == len(statGroup)-1 { return nil } @@ -288,3 +295,17 @@ func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error { } return nil } + +func (s *BlkioGroup) detectWeightFilenames(path string) { + if s.weightFilename != "" { + // Already detected. + return + } + if cgroups.PathExists(filepath.Join(path, "blkio.weight")) { + s.weightFilename = "blkio.weight" + s.weightDeviceFilename = "blkio.weight_device" + } else { + s.weightFilename = "blkio.bfq.weight" + s.weightDeviceFilename = "blkio.bfq.weight_device" + } +} 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 975df1c4e8a2..31c1c874ea09 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go @@ -13,8 +13,7 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" ) -type CpuGroup struct { -} +type CpuGroup struct{} func (s *CpuGroup) Name() string { return "cpu" @@ -26,7 +25,7 @@ func (s *CpuGroup) Apply(path string, d *cgroupData) error { if path == "" { return nil } - if err := os.MkdirAll(path, 0755); err != nil { + if err := os.MkdirAll(path, 0o755); err != nil { return err } // We should set the real-Time group scheduling settings before moving @@ -42,12 +41,12 @@ func (s *CpuGroup) Apply(path string, d *cgroupData) error { func (s *CpuGroup) SetRtSched(path string, r *configs.Resources) error { if r.CpuRtPeriod != 0 { - if err := fscommon.WriteFile(path, "cpu.rt_period_us", strconv.FormatUint(r.CpuRtPeriod, 10)); err != nil { + if err := cgroups.WriteFile(path, "cpu.rt_period_us", strconv.FormatUint(r.CpuRtPeriod, 10)); err != nil { return err } } if r.CpuRtRuntime != 0 { - if err := fscommon.WriteFile(path, "cpu.rt_runtime_us", strconv.FormatInt(r.CpuRtRuntime, 10)); err != nil { + if err := cgroups.WriteFile(path, "cpu.rt_runtime_us", strconv.FormatInt(r.CpuRtRuntime, 10)); err != nil { return err } } @@ -57,7 +56,7 @@ func (s *CpuGroup) SetRtSched(path string, r *configs.Resources) error { func (s *CpuGroup) Set(path string, r *configs.Resources) error { if r.CpuShares != 0 { shares := r.CpuShares - if err := fscommon.WriteFile(path, "cpu.shares", strconv.FormatUint(shares, 10)); err != nil { + if err := cgroups.WriteFile(path, "cpu.shares", strconv.FormatUint(shares, 10)); err != nil { return err } // read it back @@ -73,12 +72,12 @@ func (s *CpuGroup) Set(path string, r *configs.Resources) error { } } if r.CpuPeriod != 0 { - if err := fscommon.WriteFile(path, "cpu.cfs_period_us", strconv.FormatUint(r.CpuPeriod, 10)); err != nil { + if err := cgroups.WriteFile(path, "cpu.cfs_period_us", strconv.FormatUint(r.CpuPeriod, 10)); err != nil { return err } } if r.CpuQuota != 0 { - if err := fscommon.WriteFile(path, "cpu.cfs_quota_us", strconv.FormatInt(r.CpuQuota, 10)); err != nil { + if err := cgroups.WriteFile(path, "cpu.cfs_quota_us", strconv.FormatInt(r.CpuQuota, 10)); err != nil { return err } } @@ -86,7 +85,7 @@ func (s *CpuGroup) Set(path string, r *configs.Resources) error { } func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error { - f, err := fscommon.OpenFile(path, "cpu.stat", os.O_RDONLY) + f, err := cgroups.OpenFile(path, "cpu.stat", os.O_RDONLY) if err != nil { if os.IsNotExist(err) { return nil 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 0445cd45b4d4..4fbf078494c2 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go @@ -32,8 +32,7 @@ const ( clockTicks uint64 = 100 ) -type CpuacctGroup struct { -} +type CpuacctGroup struct{} func (s *CpuacctGroup) Name() string { return "cpuacct" @@ -91,7 +90,7 @@ func getCpuUsageBreakdown(path string) (uint64, uint64, error) { // Expected format: // user // system - data, err := fscommon.ReadFile(path, cgroupCpuacctStat) + data, err := cgroups.ReadFile(path, cgroupCpuacctStat) if err != nil { return 0, 0, err } @@ -117,7 +116,7 @@ func getCpuUsageBreakdown(path string) (uint64, uint64, error) { func getPercpuUsage(path string) ([]uint64, error) { percpuUsage := []uint64{} - data, err := fscommon.ReadFile(path, "cpuacct.usage_percpu") + data, err := cgroups.ReadFile(path, "cpuacct.usage_percpu") if err != nil { return percpuUsage, err } @@ -135,7 +134,7 @@ func getPercpuUsageInModes(path string) ([]uint64, []uint64, error) { usageKernelMode := []uint64{} usageUserMode := []uint64{} - file, err := fscommon.OpenFile(path, cgroupCpuacctUsageAll, os.O_RDONLY) + file, err := cgroups.OpenFile(path, cgroupCpuacctUsageAll, os.O_RDONLY) if os.IsNotExist(err) { return usageKernelMode, usageUserMode, nil } else if err != nil { @@ -144,7 +143,7 @@ func getPercpuUsageInModes(path string) ([]uint64, []uint64, error) { defer file.Close() scanner := bufio.NewScanner(file) - scanner.Scan() //skipping header line + scanner.Scan() // skipping header line for scanner.Scan() { lineFields := strings.SplitN(scanner.Text(), " ", cuacctUsageAllColumnsNumber+1) 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 0591122bca50..58a0f0406444 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go @@ -16,8 +16,7 @@ import ( "golang.org/x/sys/unix" ) -type CpusetGroup struct { -} +type CpusetGroup struct{} func (s *CpusetGroup) Name() string { return "cpuset" @@ -29,12 +28,12 @@ func (s *CpusetGroup) Apply(path string, d *cgroupData) error { func (s *CpusetGroup) Set(path string, r *configs.Resources) error { if r.CpusetCpus != "" { - if err := fscommon.WriteFile(path, "cpuset.cpus", r.CpusetCpus); err != nil { + if err := cgroups.WriteFile(path, "cpuset.cpus", r.CpusetCpus); err != nil { return err } } if r.CpusetMems != "" { - if err := fscommon.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil { + if err := cgroups.WriteFile(path, "cpuset.mems", r.CpusetMems); err != nil { return err } } @@ -156,7 +155,7 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error if err := cpusetEnsureParent(filepath.Dir(dir)); err != nil { return err } - if err := os.Mkdir(dir, 0755); err != nil && !os.IsExist(err) { + if err := os.Mkdir(dir, 0o755); err != nil && !os.IsExist(err) { return err } // We didn't inherit cpuset configs from parent, but we have @@ -176,10 +175,10 @@ func (s *CpusetGroup) ApplyDir(dir string, r *configs.Resources, pid int) error } func getCpusetSubsystemSettings(parent string) (cpus, mems string, err error) { - if cpus, err = fscommon.ReadFile(parent, "cpuset.cpus"); err != nil { + if cpus, err = cgroups.ReadFile(parent, "cpuset.cpus"); err != nil { return } - if mems, err = fscommon.ReadFile(parent, "cpuset.mems"); err != nil { + if mems, err = cgroups.ReadFile(parent, "cpuset.mems"); err != nil { return } return cpus, mems, nil @@ -206,7 +205,7 @@ func cpusetEnsureParent(current string) error { if err := cpusetEnsureParent(parent); err != nil { return err } - if err := os.Mkdir(current, 0755); err != nil && !os.IsExist(err) { + if err := os.Mkdir(current, 0o755); err != nil && !os.IsExist(err) { return err } return cpusetCopyIfNeeded(current, parent) @@ -225,12 +224,12 @@ func cpusetCopyIfNeeded(current, parent string) error { } if isEmptyCpuset(currentCpus) { - if err := fscommon.WriteFile(current, "cpuset.cpus", string(parentCpus)); err != nil { + if err := cgroups.WriteFile(current, "cpuset.cpus", string(parentCpus)); err != nil { return err } } if isEmptyCpuset(currentMems) { - if err := fscommon.WriteFile(current, "cpuset.mems", string(parentMems)); err != nil { + if err := cgroups.WriteFile(current, "cpuset.mems", string(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 048f11398a9c..dcf69ce13e73 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go @@ -9,7 +9,6 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups" cgroupdevices "github.com/opencontainers/runc/libcontainer/cgroups/devices" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/devices" "github.com/opencontainers/runc/libcontainer/userns" @@ -36,7 +35,7 @@ func (s *DevicesGroup) Apply(path string, d *cgroupData) error { } func loadEmulator(path string) (*cgroupdevices.Emulator, error) { - list, err := fscommon.ReadFile(path, "devices.list") + list, err := cgroups.ReadFile(path, "devices.list") if err != nil { return nil, err } @@ -81,7 +80,7 @@ func (s *DevicesGroup) Set(path string, r *configs.Resources) error { if rule.Allow { file = "devices.allow" } - if err := fscommon.WriteFile(path, file, rule.CgroupString()); err != nil { + if err := cgroups.WriteFile(path, file, rule.CgroupString()); err != nil { return err } } 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 cf2f948fe3fd..4baa2798ac9c 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go @@ -10,14 +10,12 @@ import ( "time" "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) -type FreezerGroup struct { -} +type FreezerGroup struct{} func (s *FreezerGroup) Name() string { return "freezer" @@ -35,7 +33,7 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) { // Freezing failed, and it is bad and dangerous // to leave the cgroup in FROZEN or FREEZING // state, so (try to) thaw it back. - _ = fscommon.WriteFile(path, "freezer.state", string(configs.Thawed)) + _ = cgroups.WriteFile(path, "freezer.state", string(configs.Thawed)) } }() @@ -68,11 +66,11 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) { // the chances to succeed in freezing // in case new processes keep appearing // in the cgroup. - _ = fscommon.WriteFile(path, "freezer.state", string(configs.Thawed)) + _ = cgroups.WriteFile(path, "freezer.state", string(configs.Thawed)) time.Sleep(10 * time.Millisecond) } - if err := fscommon.WriteFile(path, "freezer.state", string(configs.Frozen)); err != nil { + if err := cgroups.WriteFile(path, "freezer.state", string(configs.Frozen)); err != nil { return err } @@ -83,7 +81,7 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) { // system. time.Sleep(10 * time.Microsecond) } - state, err := fscommon.ReadFile(path, "freezer.state") + state, err := cgroups.ReadFile(path, "freezer.state") if err != nil { return err } @@ -104,7 +102,7 @@ func (s *FreezerGroup) Set(path string, r *configs.Resources) (Err error) { // Despite our best efforts, it got stuck in FREEZING. return errors.New("unable to freeze") case configs.Thawed: - return fscommon.WriteFile(path, "freezer.state", string(configs.Thawed)) + return cgroups.WriteFile(path, "freezer.state", string(configs.Thawed)) case configs.Undefined: return nil default: @@ -118,7 +116,7 @@ func (s *FreezerGroup) GetStats(path string, stats *cgroups.Stats) error { func (s *FreezerGroup) GetState(path string) (configs.FreezerState, error) { for { - state, err := fscommon.ReadFile(path, "freezer.state") + state, err := cgroups.ReadFile(path, "freezer.state") if err != nil { // If the kernel is too old, then we just treat the freezer as // being in an "undefined" state. @@ -131,7 +129,25 @@ func (s *FreezerGroup) GetState(path string) (configs.FreezerState, error) { case "THAWED": return configs.Thawed, nil case "FROZEN": - return configs.Frozen, nil + // Find out whether the cgroup is frozen directly, + // or indirectly via an ancestor. + self, err := cgroups.ReadFile(path, "freezer.self_freezing") + if err != nil { + // If the kernel is too old, then we just treat + // it as being frozen. + if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.ENODEV) { + err = nil + } + return configs.Frozen, err + } + switch self { + case "0\n": + return configs.Thawed, nil + case "1\n": + return configs.Frozen, nil + default: + return configs.Undefined, fmt.Errorf(`unknown "freezer.self_freezing" state: %q`, self) + } case "FREEZING": // Make sure we get a stable freezer state, so retry if the cgroup // is still undergoing freezing. This should be a temporary delay. 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 7dc4b9e37844..777b94f03569 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go @@ -64,8 +64,10 @@ func NewManager(cg *configs.Cgroup, paths map[string]string, rootless bool) cgro } // The absolute path to the root of the cgroup hierarchies. -var cgroupRootLock sync.Mutex -var cgroupRoot string +var ( + cgroupRootLock sync.Mutex + cgroupRoot string +) const defaultCgroupRoot = "/sys/fs/cgroup" @@ -393,7 +395,7 @@ func join(path string, pid int) error { if path == "" { return nil } - if err := os.MkdirAll(path, 0755); err != 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/hugetlb.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go index cf2b93bc5366..3cafc5399eed 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go @@ -11,8 +11,7 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" ) -type HugetlbGroup struct { -} +type HugetlbGroup struct{} func (s *HugetlbGroup) Name() string { return "hugetlb" @@ -24,7 +23,7 @@ func (s *HugetlbGroup) Apply(path string, d *cgroupData) error { func (s *HugetlbGroup) Set(path string, r *configs.Resources) error { for _, hugetlb := range r.HugetlbLimit { - if err := fscommon.WriteFile(path, "hugetlb."+hugetlb.Pagesize+".limit_in_bytes", strconv.FormatUint(hugetlb.Limit, 10)); err != nil { + if err := cgroups.WriteFile(path, "hugetlb."+hugetlb.Pagesize+".limit_in_bytes", strconv.FormatUint(hugetlb.Limit, 10)); err != nil { return err } } 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 dc27cb9e9c91..33946726f150 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go @@ -25,8 +25,7 @@ const ( cgroupMemoryMaxUsage = "memory.max_usage_in_bytes" ) -type MemoryGroup struct { -} +type MemoryGroup struct{} func (s *MemoryGroup) Name() string { return "memory" @@ -41,7 +40,7 @@ func setMemory(path string, val int64) error { return nil } - err := fscommon.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(val, 10)) + err := cgroups.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(val, 10)) if !errors.Is(err, unix.EBUSY) { return err } @@ -65,7 +64,7 @@ func setSwap(path string, val int64) error { return nil } - return fscommon.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(val, 10)) + return cgroups.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(val, 10)) } func setMemoryAndSwap(path string, r *configs.Resources) error { @@ -118,20 +117,20 @@ func (s *MemoryGroup) Set(path string, r *configs.Resources) error { // ignore KernelMemory and KernelMemoryTCP if r.MemoryReservation != 0 { - if err := fscommon.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(r.MemoryReservation, 10)); err != nil { + if err := cgroups.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(r.MemoryReservation, 10)); err != nil { return err } } if r.OomKillDisable { - if err := fscommon.WriteFile(path, "memory.oom_control", "1"); err != nil { + if err := cgroups.WriteFile(path, "memory.oom_control", "1"); err != nil { return err } } if r.MemorySwappiness == nil || int64(*r.MemorySwappiness) == -1 { return nil } else if *r.MemorySwappiness <= 100 { - if err := fscommon.WriteFile(path, "memory.swappiness", strconv.FormatUint(*r.MemorySwappiness, 10)); err != nil { + if err := cgroups.WriteFile(path, "memory.swappiness", strconv.FormatUint(*r.MemorySwappiness, 10)); err != nil { return err } } else { @@ -143,7 +142,7 @@ func (s *MemoryGroup) Set(path string, r *configs.Resources) error { func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error { // Set stats from memory.stat. - statsFile, err := fscommon.OpenFile(path, "memory.stat", os.O_RDONLY) + statsFile, err := cgroups.OpenFile(path, "memory.stat", os.O_RDONLY) if err != nil { if os.IsNotExist(err) { return nil @@ -200,14 +199,6 @@ func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error { return nil } -func memoryAssigned(cgroup *configs.Cgroup) bool { - return cgroup.Resources.Memory != 0 || - cgroup.Resources.MemoryReservation != 0 || - cgroup.Resources.MemorySwap > 0 || - cgroup.Resources.OomKillDisable || - (cgroup.Resources.MemorySwappiness != nil && int64(*cgroup.Resources.MemorySwappiness) != -1) -} - func getMemoryData(path, name string) (cgroups.MemoryData, error) { memoryData := cgroups.MemoryData{} @@ -258,12 +249,13 @@ func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) { ) stats := cgroups.PageUsageByNUMA{} - file, err := fscommon.OpenFile(cgroupPath, filename, os.O_RDONLY) + file, err := cgroups.OpenFile(cgroupPath, filename, os.O_RDONLY) if os.IsNotExist(err) { return stats, nil } else if err != nil { return stats, err } + defer file.Close() // File format is documented in linux/Documentation/cgroup-v1/memory.txt // and it looks like this: 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 c824db34dc01..f2617aa44425 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 @@ -6,12 +6,10 @@ import ( "strconv" "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) -type NetClsGroup struct { -} +type NetClsGroup struct{} func (s *NetClsGroup) Name() string { return "net_cls" @@ -23,7 +21,7 @@ func (s *NetClsGroup) Apply(path string, d *cgroupData) error { func (s *NetClsGroup) Set(path string, r *configs.Resources) error { if r.NetClsClassid != 0 { - if err := fscommon.WriteFile(path, "net_cls.classid", strconv.FormatUint(uint64(r.NetClsClassid), 10)); err != nil { + if err := cgroups.WriteFile(path, "net_cls.classid", strconv.FormatUint(uint64(r.NetClsClassid), 10)); err != nil { return err } } 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 ce4bebc26c7b..d0ac5e66bbbb 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 @@ -4,12 +4,10 @@ package fs import ( "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) -type NetPrioGroup struct { -} +type NetPrioGroup struct{} func (s *NetPrioGroup) Name() string { return "net_prio" @@ -21,7 +19,7 @@ func (s *NetPrioGroup) Apply(path string, d *cgroupData) error { func (s *NetPrioGroup) Set(path string, r *configs.Resources) error { for _, prioMap := range r.NetPrioIfpriomap { - if err := fscommon.WriteFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil { + if err := cgroups.WriteFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil { return err } } 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 5da4845fb843..1a306fbe3f75 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 @@ -7,8 +7,7 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" ) -type PerfEventGroup struct { -} +type PerfEventGroup struct{} func (s *PerfEventGroup) Name() string { return "perf_event" 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 c12dafd16598..1b08433c4502 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids.go @@ -12,8 +12,7 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" ) -type PidsGroup struct { -} +type PidsGroup struct{} func (s *PidsGroup) Name() string { return "pids" @@ -32,7 +31,7 @@ func (s *PidsGroup) Set(path string, r *configs.Resources) error { limit = strconv.FormatInt(r.PidsLimit, 10) } - if err := fscommon.WriteFile(path, "pids.max", limit); err != nil { + if err := cgroups.WriteFile(path, "pids.max", limit); err != nil { return err } } 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 404800e99e1e..25c47c9617e7 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpu.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpu.go @@ -23,7 +23,7 @@ func setCpu(dirPath string, r *configs.Resources) error { // NOTE: .CpuShares is not used here. Conversion is the caller's responsibility. if r.CpuWeight != 0 { - if err := fscommon.WriteFile(dirPath, "cpu.weight", strconv.FormatUint(r.CpuWeight, 10)); err != nil { + if err := cgroups.WriteFile(dirPath, "cpu.weight", strconv.FormatUint(r.CpuWeight, 10)); err != nil { return err } } @@ -40,15 +40,16 @@ func setCpu(dirPath string, r *configs.Resources) error { period = 100000 } str += " " + strconv.FormatUint(period, 10) - if err := fscommon.WriteFile(dirPath, "cpu.max", str); err != nil { + if err := cgroups.WriteFile(dirPath, "cpu.max", str); err != nil { return err } } return nil } + func statCpu(dirPath string, stats *cgroups.Stats) error { - f, err := fscommon.OpenFile(dirPath, "cpu.stat", os.O_RDONLY) + f, err := cgroups.OpenFile(dirPath, "cpu.stat", os.O_RDONLY) if err != nil { return err } 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 713c430dc4df..da29d7f2bbb5 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpuset.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/cpuset.go @@ -3,7 +3,7 @@ package fs2 import ( - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -17,12 +17,12 @@ func setCpuset(dirPath string, r *configs.Resources) error { } if r.CpusetCpus != "" { - if err := fscommon.WriteFile(dirPath, "cpuset.cpus", r.CpusetCpus); err != nil { + if err := cgroups.WriteFile(dirPath, "cpuset.cpus", r.CpusetCpus); err != nil { return err } } if r.CpusetMems != "" { - if err := fscommon.WriteFile(dirPath, "cpuset.mems", r.CpusetMems); err != nil { + if err := cgroups.WriteFile(dirPath, "cpuset.mems", r.CpusetMems); err != nil { return err } } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/create.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/create.go index f7a9999b6e07..641123a4d84c 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/create.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/create.go @@ -6,12 +6,12 @@ import ( "path/filepath" "strings" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" ) func supportedControllers() (string, error) { - return fscommon.ReadFile(UnifiedMountpoint, "/cgroup.controllers") + return cgroups.ReadFile(UnifiedMountpoint, "/cgroup.controllers") } // needAnyControllers returns whether we enable some supported controllers or not, @@ -92,7 +92,7 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) { for i, e := range elements { current = filepath.Join(current, e) if i > 0 { - if err := os.Mkdir(current, 0755); err != nil { + if err := os.Mkdir(current, 0o755); err != nil { if !os.IsExist(err) { return err } @@ -105,7 +105,7 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) { } }() } - cgType, _ := fscommon.ReadFile(current, cgTypeFile) + cgType, _ := cgroups.ReadFile(current, cgTypeFile) cgType = strings.TrimSpace(cgType) switch cgType { // If the cgroup is in an invalid mode (usually this means there's an internal @@ -122,7 +122,7 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) { // since that means we're a properly delegated cgroup subtree) but in // this case there's not much we can do and it's better than giving an // error. - _ = fscommon.WriteFile(current, cgTypeFile, "threaded") + _ = cgroups.WriteFile(current, cgTypeFile, "threaded") } // If the cgroup is in (threaded) or (domain threaded) mode, we can only use thread-aware controllers // (and you cannot usually take a cgroup out of threaded mode). @@ -136,11 +136,11 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) { } // enable all supported controllers if i < len(elements)-1 { - if err := fscommon.WriteFile(current, cgStCtlFile, res); err != nil { + if err := cgroups.WriteFile(current, cgStCtlFile, res); err != nil { // try write one by one allCtrs := strings.Split(res, " ") for _, ctr := range allCtrs { - _ = fscommon.WriteFile(current, cgStCtlFile, ctr) + _ = cgroups.WriteFile(current, cgStCtlFile, ctr) } } // Some controllers might not be enabled when rootless or containerized, 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 0091264539f6..ba81ce0b41be 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/defaultpath.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/defaultpath.go @@ -82,9 +82,7 @@ func parseCgroupFile(path string) (string, error) { } func parseCgroupFromReader(r io.Reader) (string, error) { - var ( - s = bufio.NewScanner(r) - ) + s := bufio.NewScanner(r) for s.Scan() { var ( text = s.Text() 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 fa9194b557a4..7c501cad8a63 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go @@ -58,29 +58,15 @@ func setDevices(dirPath string, r *configs.Resources) error { if r.SkipDevices { return nil } - // XXX: This is currently a white-list (but all callers pass a blacklist of - // devices). This is bad for a whole variety of reasons, but will need - // to be fixed with co-ordinated effort with downstreams. insts, license, err := devicefilter.DeviceFilter(r.Devices) if err != nil { return err } - dirFD, err := unix.Open(dirPath, unix.O_DIRECTORY|unix.O_RDONLY, 0600) + 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) } defer unix.Close(dirFD) - // XXX: This code is currently incorrect when it comes to updating an - // existing cgroup with new rules (new rulesets are just appended to - // the program list because this uses BPF_F_ALLOW_MULTI). If we didn't - // use BPF_F_ALLOW_MULTI we could actually atomically swap the - // programs. - // - // The real issue is that BPF_F_ALLOW_MULTI makes it hard to have a - // race-free blacklist because it acts as a whitelist by default, and - // having a deny-everything program cannot be overridden by other - // programs. You could temporarily insert a deny-everything program - // but that would result in spurrious failures during updates. if _, err := ebpf.LoadAttachCgroupDeviceFilter(insts, license, dirFD); err != nil { if !canSkipEBPFError(r) { return err 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 441531fd77d9..e901f7a07b1d 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/freezer.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/freezer.go @@ -3,27 +3,20 @@ package fs2 import ( + "bufio" stdErrors "errors" + "fmt" "os" "strings" + "time" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "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 { - if err := supportsFreezer(dirPath); err != nil { - // We can ignore this request as long as the user didn't ask us to - // freeze the container (since without the freezer cgroup, that's a - // no-op). - if state == configs.Undefined || state == configs.Thawed { - return nil - } - return errors.Wrap(err, "freezer not supported") - } - var stateStr string switch state { case configs.Undefined: @@ -36,11 +29,23 @@ func setFreezer(dirPath string, state configs.FreezerState) error { return errors.Errorf("invalid freezer state %q requested", state) } - if err := fscommon.WriteFile(dirPath, "cgroup.freeze", stateStr); err != nil { + fd, err := cgroups.OpenFile(dirPath, "cgroup.freeze", unix.O_RDWR) + if err != nil { + // We can ignore this request as long as the user didn't ask us to + // freeze the container (since without the freezer cgroup, that's a + // no-op). + if state != configs.Frozen { + return nil + } + return errors.Wrap(err, "freezer not supported") + } + defer fd.Close() + + if _, err := fd.WriteString(stateStr); err != nil { return err } // Confirm that the cgroup did actually change states. - if actualState, err := getFreezer(dirPath); err != nil { + 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) @@ -48,13 +53,8 @@ func setFreezer(dirPath string, state configs.FreezerState) error { return nil } -func supportsFreezer(dirPath string) error { - _, err := fscommon.ReadFile(dirPath, "cgroup.freeze") - return err -} - func getFreezer(dirPath string) (configs.FreezerState, error) { - state, err := fscommon.ReadFile(dirPath, "cgroup.freeze") + fd, err := cgroups.OpenFile(dirPath, "cgroup.freeze", unix.O_RDONLY) if err != nil { // If the kernel is too old, then we just treat the freezer as being in // an "undefined" state. @@ -63,12 +63,67 @@ func getFreezer(dirPath string) (configs.FreezerState, error) { } return configs.Undefined, err } - switch strings.TrimSpace(state) { - case "0": + defer fd.Close() + + return readFreezer(dirPath, fd) +} + +func readFreezer(dirPath string, fd *os.File) (configs.FreezerState, error) { + if _, err := fd.Seek(0, 0); err != nil { + return configs.Undefined, err + } + state := make([]byte, 2) + if _, err := fd.Read(state); err != nil { + return configs.Undefined, err + } + switch string(state) { + case "0\n": return configs.Thawed, nil - case "1": - return configs.Frozen, nil + case "1\n": + return waitFrozen(dirPath) default: return configs.Undefined, errors.Errorf(`unknown "cgroup.freeze" state: %q`, state) } } + +// waitFrozen polls cgroup.events until it sees "frozen 1" in it. +func waitFrozen(dirPath string) (configs.FreezerState, error) { + fd, err := cgroups.OpenFile(dirPath, "cgroup.events", unix.O_RDONLY) + if err != nil { + return configs.Undefined, err + } + defer fd.Close() + + // XXX: Simple wait/read/retry is used here. An implementation + // based on poll(2) or inotify(7) is possible, but it makes the code + // much more complicated. Maybe address this later. + const ( + // Perform maxIter with waitTime in between iterations. + waitTime = 10 * time.Millisecond + maxIter = 1000 + ) + scanner := bufio.NewScanner(fd) + for i := 0; scanner.Scan(); { + if i == maxIter { + return configs.Undefined, fmt.Errorf("timeout of %s reached waiting for the cgroup to freeze", waitTime*maxIter) + } + line := scanner.Text() + val := strings.TrimPrefix(line, "frozen ") + if val != line { // got prefix + if val[0] == '1' { + return configs.Frozen, nil + } + + i++ + // wait, then re-read + time.Sleep(waitTime) + _, err := fd.Seek(0, 0) + if err != nil { + return configs.Undefined, err + } + } + } + // Should only reach here either on read error, + // or if the file does not contain "frozen " line. + return configs.Undefined, scanner.Err() +} 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 5da6c51e52e4..afba0ab1c88d 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/fs2.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/fs2.go @@ -51,7 +51,7 @@ func (m *manager) getControllers() error { return nil } - data, err := fscommon.ReadFile(m.dirPath, "cgroup.controllers") + data, err := cgroups.ReadFile(m.dirPath, "cgroup.controllers") if err != nil { if m.rootless && m.config.Path == "" { return nil @@ -98,9 +98,7 @@ func (m *manager) GetAllPids() ([]int, error) { } func (m *manager) GetStats() (*cgroups.Stats, error) { - var ( - errs []error - ) + var errs []error st := cgroups.NewStats() @@ -199,7 +197,7 @@ func (m *manager) setUnified(res map[string]string) error { if strings.Contains(k, "/") { return fmt.Errorf("unified resource %q must be a file name (no slashes)", k) } - if err := fscommon.WriteFile(m.dirPath, k, v); err != nil { + 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) { 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 76df770109c4..3f513975bd30 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/hugetlb.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/hugetlb.go @@ -21,7 +21,7 @@ func setHugeTlb(dirPath string, r *configs.Resources) error { return nil } for _, hugetlb := range r.HugetlbLimit { - if err := fscommon.WriteFile(dirPath, "hugetlb."+hugetlb.Pagesize+".max", strconv.FormatUint(hugetlb.Limit, 10)); err != nil { + if err := cgroups.WriteFile(dirPath, "hugetlb."+hugetlb.Pagesize+".max", strconv.FormatUint(hugetlb.Limit, 10)); err != nil { return err } } 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 c07a00867ae8..fd3f0993ea0c 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/io.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/io.go @@ -4,60 +4,95 @@ package fs2 import ( "bufio" + "bytes" + "fmt" "os" "strconv" "strings" + "github.com/sirupsen/logrus" + "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) func isIoSet(r *configs.Resources) bool { return r.BlkioWeight != 0 || + len(r.BlkioWeightDevice) > 0 || len(r.BlkioThrottleReadBpsDevice) > 0 || len(r.BlkioThrottleWriteBpsDevice) > 0 || len(r.BlkioThrottleReadIOPSDevice) > 0 || len(r.BlkioThrottleWriteIOPSDevice) > 0 } +// bfqDeviceWeightSupported checks for per-device BFQ weight support (added +// in kernel v5.4, commit 795fe54c2a8) by reading from "io.bfq.weight". +func bfqDeviceWeightSupported(bfq *os.File) bool { + if bfq == nil { + return false + } + _, _ = bfq.Seek(0, 0) + buf := make([]byte, 32) + _, _ = bfq.Read(buf) + // If only a single number (default weight) if read back, we have older kernel. + _, err := strconv.ParseInt(string(bytes.TrimSpace(buf)), 10, 64) + return err != nil +} + func setIo(dirPath string, r *configs.Resources) error { if !isIoSet(r) { return nil } + // If BFQ IO scheduler is available, use it. + var bfq *os.File + if r.BlkioWeight != 0 || len(r.BlkioWeightDevice) > 0 { + var err error + bfq, err = cgroups.OpenFile(dirPath, "io.bfq.weight", os.O_RDWR) + if err == nil { + defer bfq.Close() + } else if !os.IsNotExist(err) { + return err + } + } + if r.BlkioWeight != 0 { - filename := "io.bfq.weight" - if err := fscommon.WriteFile(dirPath, filename, - strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil { - // if io.bfq.weight does not exist, then bfq module is not loaded. - // Fallback to use io.weight with a conversion scheme - if !os.IsNotExist(err) { + if bfq != nil { // Use BFQ. + if _, err := bfq.WriteString(strconv.FormatUint(uint64(r.BlkioWeight), 10)); err != nil { return err } + } else { + // Fallback to io.weight with a conversion scheme. v := cgroups.ConvertBlkIOToIOWeightValue(r.BlkioWeight) - if err := fscommon.WriteFile(dirPath, "io.weight", strconv.FormatUint(v, 10)); err != nil { + if err := cgroups.WriteFile(dirPath, "io.weight", strconv.FormatUint(v, 10)); err != nil { return err } } } + if bfqDeviceWeightSupported(bfq) { + for _, wd := range r.BlkioWeightDevice { + if _, err := bfq.WriteString(wd.WeightString() + "\n"); err != nil { + return fmt.Errorf("setting device weight %q: %w", wd.WeightString(), err) + } + } + } for _, td := range r.BlkioThrottleReadBpsDevice { - if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("rbps")); err != nil { + if err := cgroups.WriteFile(dirPath, "io.max", td.StringName("rbps")); err != nil { return err } } for _, td := range r.BlkioThrottleWriteBpsDevice { - if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("wbps")); err != nil { + if err := cgroups.WriteFile(dirPath, "io.max", td.StringName("wbps")); err != nil { return err } } for _, td := range r.BlkioThrottleReadIOPSDevice { - if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("riops")); err != nil { + if err := cgroups.WriteFile(dirPath, "io.max", td.StringName("riops")); err != nil { return err } } for _, td := range r.BlkioThrottleWriteIOPSDevice { - if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("wiops")); err != nil { + if err := cgroups.WriteFile(dirPath, "io.max", td.StringName("wiops")); err != nil { return err } } @@ -67,7 +102,7 @@ func setIo(dirPath string, r *configs.Resources) error { func readCgroup2MapFile(dirPath string, name string) (map[string][]string, error) { ret := map[string][]string{} - f, err := fscommon.OpenFile(dirPath, name, os.O_RDONLY) + f, err := cgroups.OpenFile(dirPath, name, os.O_RDONLY) if err != nil { return nil, err } @@ -88,22 +123,22 @@ func readCgroup2MapFile(dirPath string, name string) (map[string][]string, error } func statIo(dirPath string, stats *cgroups.Stats) error { - // more details on the io.stat file format: https://www.kernel.org/doc/Documentation/cgroup-v2.txt - var ioServiceBytesRecursive []cgroups.BlkioStatEntry values, err := readCgroup2MapFile(dirPath, "io.stat") if err != nil { return err } + // more details on the io.stat file format: https://www.kernel.org/doc/Documentation/cgroup-v2.txt + var parsedStats cgroups.BlkioStats for k, v := range values { d := strings.Split(k, ":") if len(d) != 2 { continue } - major, err := strconv.ParseUint(d[0], 10, 0) + major, err := strconv.ParseUint(d[0], 10, 64) if err != nil { return err } - minor, err := strconv.ParseUint(d[1], 10, 0) + minor, err := strconv.ParseUint(d[1], 10, 64) if err != nil { return err } @@ -115,15 +150,32 @@ func statIo(dirPath string, stats *cgroups.Stats) error { } op := d[0] - // Accommodate the cgroup v1 naming + // Map to the cgroupv1 naming and layout (in separate tables). + var targetTable *[]cgroups.BlkioStatEntry switch op { + // Equivalent to cgroupv1's blkio.io_service_bytes. case "rbytes": - op = "read" + op = "Read" + targetTable = &parsedStats.IoServiceBytesRecursive case "wbytes": - op = "write" + op = "Write" + targetTable = &parsedStats.IoServiceBytesRecursive + // Equivalent to cgroupv1's blkio.io_serviced. + case "rios": + op = "Read" + targetTable = &parsedStats.IoServicedRecursive + case "wios": + op = "Write" + targetTable = &parsedStats.IoServicedRecursive + default: + // Skip over entries we cannot map to cgroupv1 stats for now. + // In the future we should expand the stats struct to include + // them. + logrus.Debugf("cgroupv2 io stats: skipping over unmappable %s entry", item) + continue } - value, err := strconv.ParseUint(d[1], 10, 0) + value, err := strconv.ParseUint(d[1], 10, 64) if err != nil { return err } @@ -134,9 +186,9 @@ func statIo(dirPath string, stats *cgroups.Stats) error { Minor: minor, Value: value, } - ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry) + *targetTable = append(*targetTable, entry) } } - stats.BlkioStats = cgroups.BlkioStats{IoServiceBytesRecursive: ioServiceBytesRecursive} + stats.BlkioStats = parsedStats return nil } 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 7308f5a205cc..53e8f1e93498 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/memory.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/memory.go @@ -52,13 +52,13 @@ func setMemory(dirPath string, r *configs.Resources) error { } // never write empty string to `memory.swap.max`, it means set to 0. if swapStr != "" { - if err := fscommon.WriteFile(dirPath, "memory.swap.max", swapStr); err != nil { + if err := cgroups.WriteFile(dirPath, "memory.swap.max", swapStr); err != nil { return err } } if val := numToStr(r.Memory); val != "" { - if err := fscommon.WriteFile(dirPath, "memory.max", val); err != nil { + if err := cgroups.WriteFile(dirPath, "memory.max", val); err != nil { return err } } @@ -66,7 +66,7 @@ func setMemory(dirPath string, r *configs.Resources) error { // cgroup.Resources.KernelMemory is ignored if val := numToStr(r.MemoryReservation); val != "" { - if err := fscommon.WriteFile(dirPath, "memory.low", val); err != nil { + if err := cgroups.WriteFile(dirPath, "memory.low", val); err != nil { return err } } @@ -76,7 +76,7 @@ func setMemory(dirPath string, r *configs.Resources) error { func statMemory(dirPath string, stats *cgroups.Stats) error { // Set stats from memory.stat. - statsFile, err := fscommon.OpenFile(dirPath, "memory.stat", os.O_RDONLY) + statsFile, err := cgroups.OpenFile(dirPath, "memory.stat", os.O_RDONLY) if err != nil { return err } 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 346fdb678735..e2050002d0e5 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/pids.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/pids.go @@ -23,7 +23,7 @@ func setPids(dirPath string, r *configs.Resources) error { return nil } if val := numToStr(r.PidsLimit); val != "" { - if err := fscommon.WriteFile(dirPath, "pids.max", val); err != nil { + if err := cgroups.WriteFile(dirPath, "pids.max", val); err != nil { return err } } @@ -34,9 +34,9 @@ func setPids(dirPath string, r *configs.Resources) error { func statPidsFromCgroupProcs(dirPath string, stats *cgroups.Stats) error { // if the controller is not enabled, let's read PIDS from cgroups.procs // (or threads if cgroup.threads is enabled) - contents, err := fscommon.ReadFile(dirPath, "cgroup.procs") + contents, err := cgroups.ReadFile(dirPath, "cgroup.procs") if errors.Is(err, unix.ENOTSUP) { - contents, err = fscommon.ReadFile(dirPath, "cgroup.threads") + contents, err = cgroups.ReadFile(dirPath, "cgroup.threads") } if err != nil { return err diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/fscommon.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/fscommon.go deleted file mode 100644 index ae2613cdbd1e..000000000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/fscommon.go +++ /dev/null @@ -1,51 +0,0 @@ -// +build linux - -package fscommon - -import ( - "bytes" - "os" - - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -// WriteFile writes data to a cgroup file in dir. -// It is supposed to be used for cgroup files only. -func WriteFile(dir, file, data string) error { - fd, err := OpenFile(dir, file, unix.O_WRONLY) - if err != nil { - return err - } - defer fd.Close() - if err := retryingWriteFile(fd, data); err != nil { - return errors.Wrapf(err, "failed to write %q", data) - } - return nil -} - -// ReadFile reads data from a cgroup file in dir. -// It is supposed to be used for cgroup files only. -func ReadFile(dir, file string) (string, error) { - fd, err := OpenFile(dir, file, unix.O_RDONLY) - if err != nil { - return "", err - } - defer fd.Close() - var buf bytes.Buffer - - _, err = buf.ReadFrom(fd) - return buf.String(), err -} - -func retryingWriteFile(fd *os.File, data string) error { - for { - _, err := fd.Write([]byte(data)) - if errors.Is(err, unix.EINTR) { - logrus.Infof("interrupted while writing %s to %s", data, fd.Name()) - continue - } - return err - } -} 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 db0caded1518..e31146ae9dfc 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go @@ -8,10 +8,19 @@ import ( "math" "strconv" "strings" + + "github.com/opencontainers/runc/libcontainer/cgroups" ) 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. + ReadFile = cgroups.ReadFile + // Deprecated: use cgroups.WriteFile instead. + WriteFile = cgroups.WriteFile ) // ParseUint converts a string to an uint64 integer. @@ -57,7 +66,7 @@ func ParseKeyValue(t string) (string, uint64, error) { // and returns a value of the specified key. ParseUint is used for value // conversion. func GetValueByKey(path, file, key string) (uint64, error) { - content, err := ReadFile(path, file) + content, err := cgroups.ReadFile(path, file) if err != nil { return 0, err } @@ -95,7 +104,7 @@ func GetCgroupParamUint(path, file string) (uint64, error) { // GetCgroupParamInt reads a single int64 value from specified cgroup file. // If the value read is "max", the math.MaxInt64 is returned. func GetCgroupParamInt(path, file string) (int64, error) { - contents, err := ReadFile(path, file) + contents, err := cgroups.ReadFile(path, file) if err != nil { return 0, err } @@ -113,7 +122,7 @@ func GetCgroupParamInt(path, file string) (int64, error) { // GetCgroupParamString reads a string from the specified cgroup file. func GetCgroupParamString(path, file string) (string, error) { - contents, err := ReadFile(path, file) + contents, err := cgroups.ReadFile(path, file) if err != nil { return "", err } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go index 91c314e09eaa..3506c82746da 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go @@ -158,14 +158,27 @@ func findDeviceGroup(ruleType devices.Type, ruleMajor int64) (string, error) { return "", nil } +// DeviceAllow is the dbus type "a(ss)" which means we need a struct +// to represent it in Go. +type deviceAllowEntry struct { + Path string + Perms string +} + +func allowAllDevices() []systemdDbus.Property { + // Setting mode to auto and removing all DeviceAllow rules + // results in allowing access to all devices. + return []systemdDbus.Property{ + newProp("DevicePolicy", "auto"), + newProp("DeviceAllow", []deviceAllowEntry{}), + } +} + // generateDeviceProperties takes the configured device rules and generates a // corresponding set of systemd properties to configure the devices correctly. -func generateDeviceProperties(rules []*devices.Rule) ([]systemdDbus.Property, error) { - // DeviceAllow is the type "a(ss)" which means we need a temporary struct - // to represent it in Go. - type deviceAllowEntry struct { - Path string - Perms string +func generateDeviceProperties(r *configs.Resources) ([]systemdDbus.Property, error) { + if r.SkipDevices { + return nil, nil } properties := []systemdDbus.Property{ @@ -177,7 +190,7 @@ func generateDeviceProperties(rules []*devices.Rule) ([]systemdDbus.Property, er // Figure out the set of rules. configEmu := &cgroupdevices.Emulator{} - for _, rule := range rules { + for _, rule := range r.Devices { if err := configEmu.Apply(*rule); err != nil { return nil, errors.Wrap(err, "apply rule for systemd") } @@ -189,12 +202,7 @@ func generateDeviceProperties(rules []*devices.Rule) ([]systemdDbus.Property, er if configEmu.IsBlacklist() { // However, if we're dealing with an allow-all rule then we can do it. if configEmu.IsAllowAll() { - return []systemdDbus.Property{ - // Run in white-list mode by setting to "auto" and removing all - // DeviceAllow rules. - newProp("DevicePolicy", "auto"), - newProp("DeviceAllow", []deviceAllowEntry{}), - }, nil + return allowAllDevices(), nil } logrus.Warn("systemd doesn't support blacklist device rules -- applying temporary deny-all rule") return properties, nil @@ -203,8 +211,7 @@ func generateDeviceProperties(rules []*devices.Rule) ([]systemdDbus.Property, er // Now generate the set of rules we actually need to apply. Unlike the // normal devices cgroup, in "strict" mode systemd defaults to a deny-all // whitelist which is the default for devices.Emulator. - baseEmu := &cgroupdevices.Emulator{} - finalRules, err := baseEmu.Transition(configEmu) + finalRules, err := configEmu.Rules() if err != nil { return nil, errors.Wrap(err, "get simplified rules for systemd") } @@ -306,7 +313,7 @@ func getUnitName(c *configs.Cgroup) string { // isDbusError returns true if the error is a specific dbus error. func isDbusError(err error, name string) bool { if err != nil { - var derr *dbus.Error + var derr dbus.Error if errors.As(err, &derr) { return strings.Contains(derr.Name, name) } @@ -355,6 +362,9 @@ func stopUnit(cm *dbusConnManager, unitName string) error { return err }) if err == nil { + timeout := time.NewTimer(30 * time.Second) + defer timeout.Stop() + select { case s := <-statusChan: close(statusChan) @@ -362,8 +372,8 @@ func stopUnit(cm *dbusConnManager, unitName string) error { if s != "done" { logrus.Warnf("error removing unit `%s`: got `%s`. Continuing...", unitName, s) } - case <-time.After(time.Second): - logrus.Warnf("Timed out while waiting for StopUnit(%s) completion signal from dbus. Continuing...", unitName) + case <-timeout.C: + return errors.New("Timed out while waiting for systemd to remove " + unitName) } } return nil @@ -378,6 +388,15 @@ func resetFailedUnit(cm *dbusConnManager, name string) { } } +func getUnitProperty(cm *dbusConnManager, unitName string, propertyName string) (*systemdDbus.Property, error) { + var prop *systemdDbus.Property + err := cm.retryOnDisconnect(func(c *systemdDbus.Conn) (Err error) { + prop, Err = c.GetUnitPropertyContext(context.TODO(), unitName, propertyName) + return Err + }) + return prop, err +} + func setUnitProperties(cm *dbusConnManager, name string, properties ...systemdDbus.Property) error { return cm.retryOnDisconnect(func(c *systemdDbus.Conn) error { return c.SetUnitPropertiesContext(context.TODO(), name, true, properties...) @@ -476,7 +495,7 @@ func addCpuset(cm *dbusConnManager, props *[]systemdDbus.Property, cpus, mems st } if cpus != "" { - bits, err := rangeToBits(cpus) + bits, err := RangeToBits(cpus) if err != nil { return fmt.Errorf("resources.CPU.Cpus=%q conversion error: %w", cpus, err) @@ -485,7 +504,7 @@ func addCpuset(cm *dbusConnManager, props *[]systemdDbus.Property, cpus, mems st newProp("AllowedCPUs", bits)) } if mems != "" { - bits, err := rangeToBits(mems) + bits, err := RangeToBits(mems) if err != nil { return fmt.Errorf("resources.CPU.Mems=%q conversion error: %w", mems, err) diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/cpuset.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/cpuset.go index 070982188831..642a04e7dd94 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/cpuset.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/cpuset.go @@ -5,15 +5,15 @@ import ( "strconv" "strings" + "github.com/bits-and-blooms/bitset" "github.com/pkg/errors" - "github.com/willf/bitset" ) -// rangeToBits converts a text representation of a CPU mask (as written to +// RangeToBits converts a text representation of a CPU mask (as written to // or read from cgroups' cpuset.* files, e.g. "1,3-5") to a slice of bytes // with the corresponding bits set (as consumed by systemd over dbus as // AllowedCPUs/AllowedMemoryNodes unit property value). -func rangeToBits(str string) ([]byte, error) { +func RangeToBits(str string) ([]byte, error) { bits := &bitset.BitSet{} for _, r := range strings.Split(str, ",") { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/dbus.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/dbus.go index 0f7406cd9d60..a70a9df43e8d 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/dbus.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/dbus.go @@ -17,14 +17,16 @@ var ( dbusRootless bool ) -type dbusConnManager struct { -} +type dbusConnManager struct{} // newDbusConnManager initializes systemd dbus connection manager. func newDbusConnManager(rootless bool) *dbusConnManager { + dbusMu.Lock() + defer dbusMu.Unlock() if dbusInited && rootless != dbusRootless { panic("can't have both root and rootless dbus") } + dbusInited = true dbusRootless = rootless return &dbusConnManager{} } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go index 41de6e8b70f0..1a8e1e3c6c14 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go @@ -10,10 +10,12 @@ import ( "sync" systemdDbus "github.com/coreos/go-systemd/v22/dbus" + "github.com/godbus/dbus/v5" + "github.com/sirupsen/logrus" + "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups/fs" "github.com/opencontainers/runc/libcontainer/configs" - "github.com/sirupsen/logrus" ) type legacyManager struct { @@ -61,7 +63,7 @@ var legacySubsystems = []subsystem{ func genV1ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]systemdDbus.Property, error) { var properties []systemdDbus.Property - deviceProperties, err := generateDeviceProperties(r.Devices) + deviceProperties, err := generateDeviceProperties(r) if err != nil { return nil, err } @@ -207,9 +209,10 @@ func (m *legacyManager) Destroy() error { stopErr := stopUnit(m.dbus, getUnitName(m.cgroups)) - // Both on success and on error, cleanup all the cgroups we are aware of. - // Some of them were created directly by Apply() and are not managed by systemd. - if err := cgroups.RemovePaths(m.paths); err != nil { + // Both on success and on error, cleanup all the cgroups + // we are aware of, as some of them were created directly + // by Apply() and are not managed by systemd. + if err := cgroups.RemovePaths(m.paths); err != nil && stopErr == nil { return err } @@ -237,7 +240,7 @@ func (m *legacyManager) joinCgroups(pid int) error { } default: if path, ok := m.paths[name]; ok { - if err := os.MkdirAll(path, 0755); err != nil { + if err := os.MkdirAll(path, 0o755); err != nil { return err } if err := cgroups.WriteCgroupProc(path, pid); err != nil { @@ -277,18 +280,23 @@ func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) { } func (m *legacyManager) Freeze(state configs.FreezerState) error { + err := m.doFreeze(state) + if err == nil { + m.cgroups.Resources.Freezer = state + } + return err +} + +// doFreeze is the same as Freeze but without +// changing the m.cgroups.Resources.Frozen field. +func (m *legacyManager) doFreeze(state configs.FreezerState) error { path, ok := m.paths["freezer"] if !ok { return errSubsystemDoesNotExist } - prevState := m.cgroups.Resources.Freezer - m.cgroups.Resources.Freezer = state freezer := &fs.FreezerGroup{} - if err := freezer.Set(path, m.cgroups.Resources); err != nil { - m.cgroups.Resources.Freezer = prevState - return err - } - return nil + resources := &configs.Resources{Freezer: state} + return freezer.Set(path, resources) } func (m *legacyManager) GetPids() ([]int, error) { @@ -324,6 +332,61 @@ func (m *legacyManager) GetStats() (*cgroups.Stats, error) { return stats, nil } +// freezeBeforeSet answers whether there is a need to freeze the cgroup before +// applying its systemd unit properties, and thaw after, while avoiding +// unnecessary freezer state changes. +// +// The reason why we have to freeze is that systemd's application of device +// rules is done disruptively, resulting in spurious errors to common devices +// (unlike our fs driver, they will happily write deny-all rules to running +// containers). So we have to freeze the container to avoid the container get +// an occasional "permission denied" error. +func (m *legacyManager) freezeBeforeSet(unitName string, r *configs.Resources) (needsFreeze, needsThaw bool, err error) { + // Special case for SkipDevices, as used by Kubernetes to create pod + // cgroups with allow-all device policy). + if r.SkipDevices { + // No need to freeze if SkipDevices is set, and either + // (1) systemd unit does not (yet) exist, or + // (2) it has DevicePolicy=auto and empty DeviceAllow list. + // + // Interestingly, (1) and (2) are the same here because + // a non-existent unit returns default properties, + // and settings in (2) are the defaults. + // + // Do not return errors from getUnitProperty, as they alone + // should not prevent Set from working. + devPolicy, e := getUnitProperty(m.dbus, unitName, "DevicePolicy") + if e == nil && devPolicy.Value == dbus.MakeVariant("auto") { + devAllow, e := getUnitProperty(m.dbus, unitName, "DeviceAllow") + if e == nil && devAllow.Value == dbus.MakeVariant([]deviceAllowEntry{}) { + needsFreeze = false + needsThaw = false + return + } + } + } + + needsFreeze = true + needsThaw = true + + // Check the current freezer state. + freezerState, err := m.GetFreezerState() + if err != nil { + return + } + if freezerState == configs.Frozen { + // Already frozen, and should stay frozen. + needsFreeze = false + needsThaw = false + } + + if r.Freezer == configs.Frozen { + // Will be frozen anyway -- no need to thaw. + needsThaw = false + } + return +} + func (m *legacyManager) Set(r *configs.Resources) error { // If Paths are set, then we are just joining cgroups paths // and there is no need to set any values. @@ -338,37 +401,27 @@ func (m *legacyManager) Set(r *configs.Resources) error { return err } - // We have to freeze the container while systemd sets the cgroup settings. - // The reason for this is that systemd's application of DeviceAllow rules - // is done disruptively, resulting in spurrious errors to common devices - // (unlike our fs driver, they will happily write deny-all rules to running - // containers). So we freeze the container to avoid them hitting the cgroup - // error. But if the freezer cgroup isn't supported, we just warn about it. - targetFreezerState := configs.Undefined - if !m.cgroups.SkipDevices { - // Figure out the current freezer state, so we can revert to it after we - // temporarily freeze the container. - targetFreezerState, err = m.GetFreezerState() - if err != nil { - return err - } - if targetFreezerState == configs.Undefined { - targetFreezerState = configs.Thawed - } + unitName := getUnitName(m.cgroups) + needsFreeze, needsThaw, err := m.freezeBeforeSet(unitName, r) + if err != nil { + return err + } - if err := m.Freeze(configs.Frozen); err != nil { + if needsFreeze { + if err := m.doFreeze(configs.Frozen); err != nil { + // If freezer cgroup isn't supported, we just warn about it. logrus.Infof("freeze container before SetUnitProperties failed: %v", err) } } - - if err := setUnitProperties(m.dbus, getUnitName(m.cgroups), properties...); err != nil { - _ = m.Freeze(targetFreezerState) - return err + setErr := setUnitProperties(m.dbus, unitName, properties...) + if needsThaw { + if err := m.doFreeze(configs.Thawed); err != nil { + logrus.Infof("thaw container after SetUnitProperties failed: %v", err) + } + } + if setErr != nil { + return setErr } - - // Reset freezer state before we apply the configuration, to avoid clashing - // with the freezer setting in the configuration. - _ = m.Freeze(targetFreezerState) for _, sys := range legacySubsystems { // Get the subsystem path, but don't error out for not found cgroups. diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go index 8abb0feb7483..8176ce5b2ebf 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go @@ -96,7 +96,7 @@ func unifiedResToSystemdProps(cm *dbusConnManager, res map[string]string) (props newProp("CPUWeight", num)) case "cpuset.cpus", "cpuset.mems": - bits, err := rangeToBits(v) + bits, err := RangeToBits(v) if err != nil { return nil, fmt.Errorf("unified resource %q=%q conversion error: %w", k, v, err) } @@ -172,7 +172,7 @@ func genV2ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]syst // aren't the end of the world, but it is a bit concerning. However // it's unclear if systemd removes all eBPF programs attached when // doing SetUnitProperties... - deviceProperties, err := generateDeviceProperties(r.Devices) + deviceProperties, err := generateDeviceProperties(r) if err != nil { return nil, err } @@ -418,38 +418,10 @@ func (m *unifiedManager) Set(r *configs.Resources) error { return err } - // We have to freeze the container while systemd sets the cgroup settings. - // The reason for this is that systemd's application of DeviceAllow rules - // is done disruptively, resulting in spurrious errors to common devices - // (unlike our fs driver, they will happily write deny-all rules to running - // containers). So we freeze the container to avoid them hitting the cgroup - // error. But if the freezer cgroup isn't supported, we just warn about it. - targetFreezerState := configs.Undefined - if !m.cgroups.SkipDevices { - // Figure out the current freezer state, so we can revert to it after we - // temporarily freeze the container. - targetFreezerState, err = m.GetFreezerState() - if err != nil { - return err - } - if targetFreezerState == configs.Undefined { - targetFreezerState = configs.Thawed - } - - if err := m.Freeze(configs.Frozen); err != nil { - logrus.Infof("freeze container before SetUnitProperties failed: %v", err) - } - } - if err := setUnitProperties(m.dbus, getUnitName(m.cgroups), properties...); err != nil { - _ = m.Freeze(targetFreezerState) return errors.Wrap(err, "error while setting unit properties") } - // Reset freezer state before we apply the configuration, to avoid clashing - // with the freezer setting in the configuration. - _ = m.Freeze(targetFreezerState) - fsMgr, err := m.fsManager() if err != nil { return err diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go index 35ce2c1c2d47..92606525b4d7 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go @@ -15,7 +15,6 @@ import ( "sync" "time" - "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/userns" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" @@ -88,7 +87,7 @@ func GetAllSubsystems() ([]string, error) { // - freezer: implemented in kernel 5.2 // We assume these are always available, as it is hard to detect availability. pseudo := []string{"devices", "freezer"} - data, err := fscommon.ReadFile("/sys/fs/cgroup", "cgroup.controllers") + data, err := ReadFile("/sys/fs/cgroup", "cgroup.controllers") if err != nil { return nil, err } @@ -267,7 +266,6 @@ func RemovePaths(paths map[string]string) (err error) { case retries - 1: logrus.WithError(err).Error("Failed to remove cgroup") } - } _, err := os.Stat(p) // We need this strange way of checking cgroups existence because @@ -376,7 +374,7 @@ func WriteCgroupProc(dir string, pid int) error { return nil } - file, err := fscommon.OpenFile(dir, CgroupProcesses, os.O_WRONLY) + file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY) if err != nil { return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err) } 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 87d0da842881..a1e7f0afd44b 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go @@ -13,12 +13,12 @@ const ( Thawed FreezerState = "THAWED" ) +// Cgroup holds properties of a cgroup on Linux. type Cgroup struct { - // Deprecated, use Path instead + // Name specifies the name of the cgroup Name string `json:"name,omitempty"` - // name of parent of cgroup or slice - // Deprecated, use Path instead + // Parent specifies the name of parent of cgroup or slice Parent string `json:"parent,omitempty"` // Path specifies the path to cgroups that are created and/or joined by the container. @@ -127,8 +127,8 @@ type Resources struct { // SkipDevices allows to skip configuring device permissions. // Used by e.g. kubelet while creating a parent cgroup (kubepods) - // common for many containers. + // common for many containers, and by runc update. // // NOTE it is impossible to start a container which has this flag set. - SkipDevices bool `json:"skip_devices"` + SkipDevices bool `json:"-"` } 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 c0c23d70004a..2a519f582d2a 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go @@ -2,7 +2,7 @@ package configs +// Cgroup holds properties of a cgroup on Linux // TODO Windows: This can ultimately be entirely factored out on Windows as // cgroups are a Unix-specific construct. -type Cgroup struct { -} +type Cgroup struct{} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go index 14a0960389fb..4281593f0b75 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go @@ -208,9 +208,11 @@ type Config struct { RootlessCgroups bool `json:"rootless_cgroups,omitempty"` } -type HookName string -type HookList []Hook -type Hooks map[HookName]HookList +type ( + HookName string + HookList []Hook + Hooks map[HookName]HookList +) const ( // Prestart commands are executed after the container namespaces are created, @@ -387,7 +389,7 @@ func (c Command) Run(s *specs.State) error { case err := <-errC: return err case <-timerCh: - cmd.Process.Kill() + _ = cmd.Process.Kill() <-errC return fmt.Errorf("hook ran past specified timeout of %.1fs", c.Timeout.Seconds()) } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/devices.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/devices.go deleted file mode 100644 index b9e3664ceaa5..000000000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/devices.go +++ /dev/null @@ -1,17 +0,0 @@ -package configs - -import "github.com/opencontainers/runc/libcontainer/devices" - -type ( - // Deprecated: use libcontainer/devices.Device - Device = devices.Device - - // Deprecated: use libcontainer/devices.Rule - DeviceRule = devices.Rule - - // Deprecated: use libcontainer/devices.Type - DeviceType = devices.Type - - // Deprecated: use libcontainer/devices.Permissions - DevicePermissions = devices.Permissions -) diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go index 670757ddb5f4..a75ff10ec9dd 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go @@ -3,7 +3,7 @@ package configs const ( // EXT_COPYUP is a directive to copy up the contents of a directory when // a tmpfs is mounted over it. - EXT_COPYUP = 1 << iota + EXT_COPYUP = 1 << iota //nolint:golint // ignore "don't use ALL_CAPS" warning ) type Mount struct { 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 19bf713de3a3..cc76e2f586ad 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go @@ -4,5 +4,4 @@ package configs // Namespace defines configuration for each namespace. It specifies an // alternate path that is able to be joined via setns. -type Namespace struct { -} +type Namespace struct{} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/network.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/network.go index ccdb228e14c8..c44c3ea71b8f 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/network.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/network.go @@ -50,7 +50,10 @@ type Network struct { HairpinMode bool `json:"hairpin_mode"` } -// Routes can be specified to create entries in the route table as the container is started +// Route defines a routing table entry. +// +// Routes can be specified to create entries in the routing table as the container +// is started. // // All of destination, source, and gateway should be either IPv4 or IPv6. // One of the three options must be present, and omitted entries will use their @@ -58,15 +61,15 @@ type Network struct { // gateway to 1.2.3.4 and the interface to eth0 will set up a standard // destination of 0.0.0.0(or *) when viewed in the route table. type Route struct { - // Sets the destination and mask, should be a CIDR. Accepts IPv4 and IPv6 + // Destination specifies the destination IP address and mask in the CIDR form. Destination string `json:"destination"` - // Sets the source and mask, should be a CIDR. Accepts IPv4 and IPv6 + // Source specifies the source IP address and mask in the CIDR form. Source string `json:"source"` - // Sets the gateway. Accepts IPv4 and IPv6 + // Gateway specifies the gateway IP address. Gateway string `json:"gateway"` - // The device to set this route up for, for example: eth0 + // InterfaceName specifies the device to set this route up for, for example eth0. InterfaceName string `json:"interface_name"` } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go index 02de2abc81c0..b0254600244b 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go @@ -12,6 +12,7 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/intelrdt" selinux "github.com/opencontainers/selinux/go-selinux" + "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -23,13 +24,13 @@ func New() Validator { return &ConfigValidator{} } -type ConfigValidator struct { -} +type ConfigValidator struct{} type check func(config *configs.Config) error func (v *ConfigValidator) Validate(config *configs.Config) error { checks := []check{ + v.cgroups, v.rootfs, v.network, v.hostname, @@ -39,17 +40,21 @@ func (v *ConfigValidator) Validate(config *configs.Config) error { v.sysctl, v.intelrdt, v.rootlessEUID, - v.mounts, } for _, c := range checks { if err := c(config); err != nil { return err } } - if err := v.cgroups(config); err != nil { - return err + // Relaxed validation rules for backward compatibility + warns := []check{ + v.mounts, // TODO (runc v1.x.x): make this an error instead of a warning + } + for _, c := range warns { + if err := c(config); err != nil { + logrus.WithError(err).Warnf("invalid configuration") + } } - return nil } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/console_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/console_linux.go index 9997e93ed4f3..7bfff026ac8e 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/console_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/console_linux.go @@ -9,7 +9,7 @@ import ( // mount initializes the console inside the rootfs mounting with the specified mount label // and applying the correct ownership of the console. func mountConsole(slavePath string) error { - oldMask := unix.Umask(0000) + oldMask := unix.Umask(0o000) defer unix.Umask(oldMask) f, err := os.Create("/dev/console") if err != nil && !os.IsExist(err) { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go index 849bf4a613ce..6ce1854f6878 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go @@ -437,8 +437,8 @@ func (c *linuxContainer) createExecFifo() error { if _, err := os.Stat(fifoName); err == nil { return fmt.Errorf("exec fifo %s already exists", fifoName) } - oldMask := unix.Umask(0000) - if err := unix.Mkfifo(fifoName, 0622); err != nil { + oldMask := unix.Umask(0o000) + if err := unix.Mkfifo(fifoName, 0o622); err != nil { unix.Umask(oldMask) return err } @@ -699,7 +699,6 @@ func (c *linuxContainer) NotifyMemoryPressure(level PressureLevel) (<-chan struc var criuFeatures *criurpc.CriuFeatures func (c *linuxContainer) checkCriuFeatures(criuOpts *CriuOpts, rpcOpts *criurpc.CriuOpts, criuFeat *criurpc.CriuFeatures) error { - t := criurpc.CriuReqType_FEATURE_CHECK // make sure the features we are looking for are really not from @@ -761,7 +760,6 @@ func compareCriuVersion(criuVersion int, minVersion int) error { // checkCriuVersion checks Criu version greater than or equal to minVersion func (c *linuxContainer) checkCriuVersion(minVersion int) error { - // If the version of criu has already been determined there is no need // to ask criu for the version again. Use the value from c.criuVersion. if c.criuVersion != 0 { @@ -970,7 +968,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { // Since a container can be C/R'ed multiple times, // the checkpoint directory may already exist. - if err := os.Mkdir(criuOpts.ImagesDirectory, 0700); err != nil && !os.IsExist(err) { + if err := os.Mkdir(criuOpts.ImagesDirectory, 0o700); err != nil && !os.IsExist(err) { return err } @@ -978,7 +976,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { criuOpts.WorkDirectory = filepath.Join(c.root, "criu.work") } - if err := os.Mkdir(criuOpts.WorkDirectory, 0700); err != nil && !os.IsExist(err) { + if err := os.Mkdir(criuOpts.WorkDirectory, 0o700); err != nil && !os.IsExist(err) { return err } @@ -1048,7 +1046,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { } } - //pre-dump may need parentImage param to complete iterative migration + // pre-dump may need parentImage param to complete iterative migration if criuOpts.ParentImage != "" { rpcOpts.ParentImg = proto.String(criuOpts.ParentImage) rpcOpts.TrackMem = proto.Bool(true) @@ -1146,7 +1144,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { return err } - err = ioutil.WriteFile(filepath.Join(criuOpts.ImagesDirectory, descriptorsFilename), fdsJSON, 0600) + err = ioutil.WriteFile(filepath.Join(criuOpts.ImagesDirectory, descriptorsFilename), fdsJSON, 0o600) if err != nil { return err } @@ -1217,7 +1215,7 @@ func (c *linuxContainer) makeCriuRestoreMountpoints(m *configs.Mount) error { if err := checkProcMount(c.config.Rootfs, dest, ""); err != nil { return err } - if err := os.MkdirAll(dest, 0755); err != nil { + if err := os.MkdirAll(dest, 0o755); err != nil { return err } } @@ -1318,7 +1316,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { } // Since a container can be C/R'ed multiple times, // the work directory may already exist. - if err := os.Mkdir(criuOpts.WorkDirectory, 0700); err != nil && !os.IsExist(err) { + if err := os.Mkdir(criuOpts.WorkDirectory, 0o700); err != nil && !os.IsExist(err) { return err } workDir, err := os.Open(criuOpts.WorkDirectory) @@ -1340,7 +1338,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { // c.config.Rootfs is bind-mounted to a temporary directory // to satisfy these requirements. root := filepath.Join(c.root, "criu-root") - if err := os.Mkdir(root, 0755); err != nil { + if err := os.Mkdir(root, 0o755); err != nil { return err } defer os.Remove(root) @@ -1352,7 +1350,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { if err != nil { return err } - defer unix.Unmount(root, unix.MNT_DETACH) + defer unix.Unmount(root, unix.MNT_DETACH) //nolint: errcheck t := criurpc.CriuReqType_RESTORE req := &criurpc.CriuReq{ Type: &t, @@ -1377,6 +1375,15 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { }, } + if criuOpts.LsmProfile != "" { + // CRIU older than 3.16 has a bug which breaks the possibility + // to set a different LSM profile. + if err := c.checkCriuVersion(31600); err != nil { + return errors.New("--lsm-profile requires at least CRIU 3.16") + } + req.Opts.LsmProfile = proto.String(criuOpts.LsmProfile) + } + c.handleCriuConfigurationFile(req.Opts) if err := c.handleRestoringNamespaces(req.Opts, &extraFiles); err != nil { @@ -1665,7 +1672,7 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts * break } - criuClientCon.CloseWrite() + _ = criuClientCon.CloseWrite() // cmd.Wait() waits cmd.goroutines which are used for proxying file descriptors. // Here we want to wait only the CRIU process. criuProcessState, err = criuProcess.Wait() diff --git a/vendor/github.com/opencontainers/runc/libcontainer/criu_opts_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/criu_opts_linux.go index 001c5399c721..0db43e74e8aa 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/criu_opts_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/criu_opts_linux.go @@ -29,4 +29,5 @@ type CriuOpts struct { AutoDedup bool // auto deduplication for incremental dumps LazyPages bool // restore memory pages lazily using userfaultfd StatusFd int // fd for feedback when lazy server is ready + LsmProfile string // LSM profile used to restore the container } 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 acb816998c35..6d5b3d09df3b 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go @@ -11,10 +11,8 @@ import ( "golang.org/x/sys/unix" ) -var ( - // ErrNotADevice denotes that a file is not a valid linux device. - ErrNotADevice = errors.New("not a device node") -) +// ErrNotADevice denotes that a file is not a valid linux device. +var ErrNotADevice = errors.New("not a device node") // Testing dependencies var ( @@ -29,8 +27,9 @@ func mkDev(d *Rule) (uint64, error) { return unix.Mkdev(uint32(d.Major), uint32(d.Minor)), nil } -// Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the -// information about a linux device and return that information as a Device struct. +// DeviceFromPath takes the path to a device and its cgroup_permissions (which +// cannot be easily queried) to look up the information about a linux device +// and returns that information as a Device struct. func DeviceFromPath(path, permissions string) (*Device, error) { var stat unix.Stat_t err := unixLstat(path, &stat) diff --git a/vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go index 972b0f2b5d96..dbd410b88f98 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go @@ -196,7 +196,11 @@ func New(root string, options ...func(*LinuxFactory) error) (Factory, error) { Validator: validate.New(), CriuPath: "criu", } - Cgroupfs(l) + + if err := Cgroupfs(l); err != nil { + return nil, err + } + for _, opt := range options { if opt == nil { continue @@ -287,7 +291,7 @@ func (l *LinuxFactory) Load(id string) (Container, error) { if l.Root == "" { return nil, newGenericError(fmt.Errorf("invalid root"), ConfigInvalid) } - //when load, we need to check id is valid or not. + // when load, we need to check id is valid or not. if err := l.validateID(id); err != nil { return nil, err } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go index 798e7a84d35e..c456cbe7a150 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go @@ -112,9 +112,19 @@ func populateProcessEnvironment(env []string) error { for _, pair := range env { p := strings.SplitN(pair, "=", 2) if len(p) < 2 { - return fmt.Errorf("invalid environment '%v'", pair) + return fmt.Errorf("invalid environment variable: %q", pair) } - if err := os.Setenv(p[0], p[1]); err != nil { + name, val := p[0], p[1] + if name == "" { + return fmt.Errorf("environment variable name can't be empty: %q", pair) + } + if strings.IndexByte(name, 0) >= 0 { + return fmt.Errorf("environment variable name can't contain null(\\x00): %q", pair) + } + if strings.IndexByte(val, 0) >= 0 { + return fmt.Errorf("environment variable value can't contain null(\\x00): %q", pair) + } + if err := os.Setenv(name, val); err != nil { return err } } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/cmt.go b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/cmt.go index ed950973f080..6480a1306970 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/cmt.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/cmt.go @@ -1,8 +1,6 @@ package intelrdt -var ( - cmtEnabled bool -) +var cmtEnabled bool // Check if Intel RDT/CMT is enabled. func IsCMTEnabled() bool { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/mbm.go b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/mbm.go index 93063ee01905..0fbecdeb2281 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/mbm.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/mbm.go @@ -2,10 +2,8 @@ package intelrdt -var ( - // The flag to indicate if Intel RDT/MBM is enabled - mbmEnabled bool -) +// The flag to indicate if Intel RDT/MBM is enabled +var mbmEnabled bool // Check if Intel RDT/MBM is enabled. func IsMBMEnabled() bool { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/monitoring.go b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/monitoring.go index 78c2f624c960..547c15470f25 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/monitoring.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/monitoring.go @@ -10,9 +10,7 @@ import ( "github.com/sirupsen/logrus" ) -var ( - enabledMonFeatures monFeatures -) +var enabledMonFeatures monFeatures type monFeatures struct { mbmTotalBytes bool diff --git a/vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go b/vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go index e73af7ae2dca..4a60c34b8421 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go @@ -14,18 +14,18 @@ import ( type KeySerial uint32 func JoinSessionKeyring(name string) (KeySerial, error) { - sessKeyId, err := unix.KeyctlJoinSessionKeyring(name) + sessKeyID, err := unix.KeyctlJoinSessionKeyring(name) if err != nil { return 0, errors.Wrap(err, "create session key") } - return KeySerial(sessKeyId), nil + return KeySerial(sessKeyID), nil } // ModKeyringPerm modifies permissions on a keyring by reading the current permissions, // anding the bits with the given mask (clearing permissions) and setting // additional permission bits -func ModKeyringPerm(ringId KeySerial, mask, setbits uint32) error { - dest, err := unix.KeyctlString(unix.KEYCTL_DESCRIBE, int(ringId)) +func ModKeyringPerm(ringID KeySerial, mask, setbits uint32) error { + dest, err := unix.KeyctlString(unix.KEYCTL_DESCRIBE, int(ringID)) if err != nil { return err } @@ -43,5 +43,5 @@ func ModKeyringPerm(ringId KeySerial, mask, setbits uint32) error { perm := (uint32(perm64) & mask) | setbits - return unix.KeyctlSetperm(int(ringId), perm) + return unix.KeyctlSetperm(int(ringID), perm) } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/logs/logs.go b/vendor/github.com/opencontainers/runc/libcontainer/logs/logs.go index 27b96846632f..6610a1aaeeac 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/logs/logs.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/logs/logs.go @@ -85,7 +85,7 @@ func ConfigureLogging(config Config) error { if config.LogPipeFd > 0 { logrus.SetOutput(os.NewFile(uintptr(config.LogPipeFd), "logpipe")) } else if config.LogFilePath != "" { - f, err := os.OpenFile(config.LogFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0644) + f, err := os.OpenFile(config.LogFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0o644) if err != nil { return err } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/network_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/network_linux.go index a0a87b9842af..12e5800fc0e6 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/network_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/network_linux.go @@ -83,8 +83,7 @@ func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) { } // loopback is a network strategy that provides a basic loopback device -type loopback struct { -} +type loopback struct{} func (l *loopback) create(n *network, nspid int) error { return nil diff --git a/vendor/github.com/opencontainers/runc/libcontainer/notify_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/notify_linux.go index d7d1de1ba512..73a6f5946558 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/notify_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/notify_linux.go @@ -35,7 +35,7 @@ func registerMemoryEvent(cgDir string, evName string, arg string) (<-chan struct eventControlPath := filepath.Join(cgDir, "cgroup.event_control") data := fmt.Sprintf("%d %d %s", eventfd.Fd(), evFile.Fd(), arg) - if err := ioutil.WriteFile(eventControlPath, []byte(data), 0700); err != nil { + if err := ioutil.WriteFile(eventControlPath, []byte(data), 0o700); err != nil { eventfd.Close() evFile.Close() return nil, err diff --git a/vendor/github.com/opencontainers/runc/libcontainer/process_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/process_linux.go index 053971b911bd..80f25e334f71 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/process_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/process_linux.go @@ -188,7 +188,7 @@ func (p *setnsProcess) start() (retErr error) { } // Must be done after Shutdown so the child will exit and we can wait for it. if ierr != nil { - p.wait() + _, _ = p.wait() return ierr } return nil @@ -201,16 +201,16 @@ func (p *setnsProcess) start() (retErr error) { func (p *setnsProcess) execSetns() error { status, err := p.cmd.Process.Wait() if err != nil { - p.cmd.Wait() + _ = p.cmd.Wait() return newSystemErrorWithCause(err, "waiting on setns process to finish") } if !status.Success() { - p.cmd.Wait() + _ = p.cmd.Wait() return newSystemError(&exec.ExitError{ProcessState: status}) } var pid *pid if err := json.NewDecoder(p.messageSockPair.parent).Decode(&pid); err != nil { - p.cmd.Wait() + _ = p.cmd.Wait() return newSystemErrorWithCause(err, "reading pid from init pipe") } @@ -292,7 +292,7 @@ func (p *initProcess) externalDescriptors() []string { func (p *initProcess) getChildPid() (int, error) { var pid pid if err := json.NewDecoder(p.messageSockPair.parent).Decode(&pid); err != nil { - p.cmd.Wait() + _ = p.cmd.Wait() return -1, err } @@ -309,11 +309,11 @@ func (p *initProcess) getChildPid() (int, error) { func (p *initProcess) waitForChildExit(childPid int) error { status, err := p.cmd.Process.Wait() if err != nil { - p.cmd.Wait() + _ = p.cmd.Wait() return err } if !status.Success() { - p.cmd.Wait() + _ = p.cmd.Wait() return &exec.ExitError{ProcessState: status} } @@ -327,12 +327,12 @@ func (p *initProcess) waitForChildExit(childPid int) error { } func (p *initProcess) start() (retErr error) { - defer p.messageSockPair.parent.Close() + defer p.messageSockPair.parent.Close() //nolint: errcheck err := p.cmd.Start() p.process.ops = p // close the write-side of the pipes (controlled by child) - p.messageSockPair.child.Close() - p.logFilePair.child.Close() + _ = p.messageSockPair.child.Close() + _ = p.logFilePair.child.Close() if err != nil { p.process.ops = nil return newSystemErrorWithCause(err, "starting init process command") @@ -371,9 +371,9 @@ func (p *initProcess) start() (retErr error) { logrus.WithError(err).Warn("unable to terminate initProcess") } - p.manager.Destroy() + _ = p.manager.Destroy() if p.intelRdtManager != nil { - p.intelRdtManager.Destroy() + _ = p.intelRdtManager.Destroy() } } }() @@ -553,7 +553,7 @@ func (p *initProcess) start() (retErr error) { // Must be done after Shutdown so the child will exit and we can wait for it. if ierr != nil { - p.wait() + _, _ = p.wait() return ierr } return nil @@ -563,7 +563,7 @@ func (p *initProcess) wait() (*os.ProcessState, error) { err := p.cmd.Wait() // we should kill all processes in cgroup when init is died if we use host PID namespace if p.sharePidns { - signalAllProcesses(p.manager, unix.SIGKILL) + _ = signalAllProcesses(p.manager, unix.SIGKILL) } return p.cmd.ProcessState, err } @@ -668,7 +668,7 @@ func (p *Process) InitializeIO(rootuid, rootgid int) (i *IO, err error) { defer func() { if err != nil { for _, fd := range fds { - unix.Close(int(fd)) + _ = unix.Close(int(fd)) } } }() diff --git a/vendor/github.com/opencontainers/runc/libcontainer/restored_process.go b/vendor/github.com/opencontainers/runc/libcontainer/restored_process.go index 97565d7fa4b2..34270e64ed47 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/restored_process.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/restored_process.go @@ -11,9 +11,7 @@ import ( ) func newRestoredProcess(cmd *exec.Cmd, fds []string) (*restoredProcess, error) { - var ( - err error - ) + var err error pid := cmd.Process.Pid stat, err := system.Stat(pid) if err != nil { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go index d9c5146dddd1..430f490dec91 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go @@ -143,7 +143,7 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) { if cwd := iConfig.Cwd; cwd != "" { // Note that spec.Process.Cwd can contain unclean value like "../../../../foo/bar...". // However, we are safe to call MkDirAll directly because we are in the jail here. - if err := os.MkdirAll(cwd, 0755); err != nil { + if err := os.MkdirAll(cwd, 0o755); err != nil { return err } } @@ -176,7 +176,7 @@ func finalizeRootfs(config *configs.Config) (err error) { if config.Umask != nil { unix.Umask(int(*config.Umask)) } else { - unix.Umask(0022) + unix.Umask(0o022) } return nil } @@ -196,9 +196,9 @@ func prepareTmp(topTmpDir string) (string, error) { return tmpdir, nil } -func cleanupTmp(tmpdir string) error { - unix.Unmount(tmpdir, 0) - return os.RemoveAll(tmpdir) +func cleanupTmp(tmpdir string) { + _ = unix.Unmount(tmpdir, 0) + _ = os.RemoveAll(tmpdir) } func mountCmd(cmd configs.Command) error { @@ -262,7 +262,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error { for _, b := range binds { if c.cgroupns { subsystemPath := filepath.Join(c.root, b.Destination) - if err := os.MkdirAll(subsystemPath, 0755); err != nil { + if err := os.MkdirAll(subsystemPath, 0o755); err != nil { return err } if err := utils.WithProcfd(c.root, b.Destination, func(procfd string) error { @@ -306,7 +306,7 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error { if err != nil { return err } - if err := os.MkdirAll(dest, 0755); err != nil { + if err := os.MkdirAll(dest, 0o755); err != nil { return err } return utils.WithProcfd(c.root, m.Destination, func(procfd string) error { @@ -398,13 +398,13 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { } else if fi.Mode()&os.ModeDir == 0 { return fmt.Errorf("filesystem %q must be mounted on ordinary directory", m.Device) } - if err := os.MkdirAll(dest, 0755); err != nil { + if err := os.MkdirAll(dest, 0o755); err != nil { return err } // Selinux kernels do not support labeling of /proc or /sys return mountPropagate(m, rootfs, "") case "mqueue": - if err := os.MkdirAll(dest, 0755); err != nil { + if err := os.MkdirAll(dest, 0o755); err != nil { return err } if err := mountPropagate(m, rootfs, ""); err != nil { @@ -414,7 +414,7 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { case "tmpfs": stat, err := os.Stat(dest) if err != nil { - if err := os.MkdirAll(dest, 0755); err != nil { + if err := os.MkdirAll(dest, 0o755); err != nil { return err } } @@ -473,7 +473,7 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { if err := checkProcMount(rootfs, dest, m.Source); err != nil { return err } - if err := os.MkdirAll(dest, 0755); err != nil { + if err := os.MkdirAll(dest, 0o755); err != nil { return err } return mountPropagate(m, rootfs, mountLabel) @@ -582,7 +582,7 @@ func isProc(path string) (bool, error) { } func setupDevSymlinks(rootfs string) error { - var links = [][2]string{ + links := [][2]string{ {"/proc/self/fd", "/dev/fd"}, {"/proc/self/fd/0", "/dev/stdin"}, {"/proc/self/fd/1", "/dev/stdout"}, @@ -615,7 +615,7 @@ func reOpenDevNull() error { if err != nil { return fmt.Errorf("Failed to open /dev/null - %s", err) } - defer file.Close() + defer file.Close() //nolint: errcheck if err := unix.Fstat(int(file.Fd()), &devNullStat); err != nil { return err } @@ -636,7 +636,7 @@ func reOpenDevNull() error { // Create the device nodes in the container. func createDevices(config *configs.Config) error { useBindMount := userns.RunningInUserNS() || config.Namespaces.Contains(configs.NEWUSER) - oldMask := unix.Umask(0000) + oldMask := unix.Umask(0o000) for _, node := range config.Devices { // The /dev/ptmx device is setup by setupPtmx() @@ -661,7 +661,7 @@ func bindMountDeviceNode(rootfs, dest string, node *devices.Device) error { return err } if f != nil { - f.Close() + _ = f.Close() } return utils.WithProcfd(rootfs, dest, func(procfd string) error { return unix.Mount(node.Path, procfd, "bind", unix.MS_BIND, "") @@ -678,7 +678,7 @@ func createDeviceNode(rootfs string, node *devices.Device, bind bool) error { if err != nil { return err } - if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { return err } if bind { @@ -799,7 +799,6 @@ func setReadonly() error { } flags |= uintptr(s.Flags) return unix.Mount("", "/", "", flags, "") - } func setupPtmx(config *configs.Config) error { @@ -826,13 +825,13 @@ func pivotRoot(rootfs string) error { if err != nil { return err } - defer unix.Close(oldroot) + defer unix.Close(oldroot) //nolint: errcheck newroot, err := unix.Open(rootfs, unix.O_DIRECTORY|unix.O_RDONLY, 0) if err != nil { return err } - defer unix.Close(newroot) + defer unix.Close(newroot) //nolint: errcheck // Change to the new root so that the pivot_root actually acts on it. if err := unix.Fchdir(newroot); err != nil { @@ -947,16 +946,16 @@ func createIfNotExists(path string, isDir bool) error { if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { if isDir { - return os.MkdirAll(path, 0755) + return os.MkdirAll(path, 0o755) } - if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return err } - f, err := os.OpenFile(path, os.O_CREATE, 0755) + f, err := os.OpenFile(path, os.O_CREATE, 0o755) if err != nil { return err } - f.Close() + _ = f.Close() } } return nil @@ -1031,7 +1030,7 @@ func maskPath(path string, mountLabel string) error { // For e.g. net.ipv4.ip_forward translated to /proc/sys/net/ipv4/ip_forward. func writeSystemProperty(key, value string) error { keyPath := strings.Replace(key, ".", "/", -1) - return ioutil.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0644) + return ioutil.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0o644) } func remount(m *configs.Mount, rootfs string) error { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/seccomp/patchbpf/enosys_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/seccomp/patchbpf/enosys_linux.go index a8432bfd46a7..3c6ef7a4c6a5 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/seccomp/patchbpf/enosys_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/seccomp/patchbpf/enosys_linux.go @@ -324,7 +324,8 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error) bpf.JumpIf{ Cond: bpf.JumpGreaterThan, Val: uint32(sysno), - SkipTrue: uint8(baseJumpEnosys + 1)}, + SkipTrue: uint8(baseJumpEnosys + 1), + }, // ja [baseJumpFilter] bpf.Jump{Skip: baseJumpFilter}, } @@ -353,16 +354,20 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error) case libseccomp.ArchAMD64: sectionTail = append([]bpf.Instruction{ // jset (1<<30),[len(tail)-1] - bpf.JumpIf{Cond: bpf.JumpBitsSet, + bpf.JumpIf{ + Cond: bpf.JumpBitsSet, Val: 1 << 30, - SkipTrue: uint8(len(sectionTail) - 1)}, + SkipTrue: uint8(len(sectionTail) - 1), + }, }, sectionTail...) case libseccomp.ArchX32: sectionTail = append([]bpf.Instruction{ // jset (1<<30),0,[len(tail)-1] - bpf.JumpIf{Cond: bpf.JumpBitsNotSet, + bpf.JumpIf{ + Cond: bpf.JumpBitsNotSet, Val: 1 << 30, - SkipTrue: uint8(len(sectionTail) - 1)}, + SkipTrue: uint8(len(sectionTail) - 1), + }, }, sectionTail...) default: return nil, errors.Errorf("unknown amd64 native architecture %#x", scmpArch) @@ -402,12 +407,14 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error) bpf.JumpIf{ Cond: bpf.JumpGreaterThan, Val: uint32(x86sysno), - SkipTrue: uint8(baseJumpEnosys + 2), SkipFalse: 1}, + SkipTrue: uint8(baseJumpEnosys + 2), SkipFalse: 1, + }, // jgt [x32 syscall],[baseJumpEnosys] bpf.JumpIf{ Cond: bpf.JumpGreaterThan, Val: uint32(x32sysno), - SkipTrue: uint8(baseJumpEnosys + 1)}, + SkipTrue: uint8(baseJumpEnosys + 1), + }, // ja [baseJumpFilter] bpf.Jump{Skip: baseJumpFilter}, }...) @@ -426,12 +433,14 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error) bpf.JumpIf{ Cond: bpf.JumpGreaterThan, Val: uint32(x86sysno), - SkipTrue: 1, SkipFalse: 2}, + SkipTrue: 1, SkipFalse: 2, + }, // jle [x32 syscall],[baseJumpEnosys] bpf.JumpIf{ Cond: bpf.JumpLessOrEqual, Val: uint32(x32sysno), - SkipTrue: 1}, + SkipTrue: 1, + }, // ja [baseJumpEnosys+1] bpf.Jump{Skip: baseJumpEnosys + 1}, // ja [baseJumpFilter] @@ -478,7 +487,8 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error) bpf.JumpIf{ Cond: bpf.JumpEqual, Val: uint32(nativeArch), - SkipTrue: uint8(jump)}, + SkipTrue: uint8(jump), + }, }, programTail...) } else { programTail = append([]bpf.Instruction{ @@ -486,7 +496,8 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error) bpf.JumpIf{ Cond: bpf.JumpNotEqual, Val: uint32(nativeArch), - SkipTrue: 1}, + SkipTrue: 1, + }, // ja [jump] bpf.Jump{Skip: jump}, }, programTail...) diff --git a/vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go index 97987f1d038c..2d7e5814e8af 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go @@ -37,7 +37,7 @@ func (l *linuxSetnsInit) Init() error { if err := selinux.SetKeyLabel(l.config.ProcessLabel); err != nil { return err } - defer selinux.SetKeyLabel("") + defer selinux.SetKeyLabel("") //nolint: errcheck // Do not inherit the parent's session keyring. if _, err := keys.JoinSessionKeyring(l.getSessionRingName()); err != nil { // Same justification as in standart_init_linux.go as to why we @@ -65,7 +65,7 @@ func (l *linuxSetnsInit) Init() error { if err := selinux.SetExecLabel(l.config.ProcessLabel); err != nil { return err } - defer selinux.SetExecLabel("") + defer selinux.SetExecLabel("") //nolint: errcheck // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible. diff --git a/vendor/github.com/opencontainers/runc/libcontainer/stacktrace/capture.go b/vendor/github.com/opencontainers/runc/libcontainer/stacktrace/capture.go index 0bbe14950409..bfb89157b46f 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/stacktrace/capture.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/stacktrace/capture.go @@ -13,8 +13,8 @@ func Capture(userSkip int) Stacktrace { ) for i := skip; ; i++ { pc, file, line, ok := runtime.Caller(i) - //detect if caller is repeated to avoid loop, gccgo - //currently runs into a loop without this check + // detect if caller is repeated to avoid loop, gccgo + // currently runs into a loop without this check if !ok || pc == prevPc { break } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go index d77022ad4d63..98c4860541e9 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go @@ -52,7 +52,7 @@ func (l *linuxStandardInit) Init() error { if err := selinux.SetKeyLabel(l.config.ProcessLabel); err != nil { return err } - defer selinux.SetKeyLabel("") + defer selinux.SetKeyLabel("") //nolint: errcheck ringname, keepperms, newperms := l.getSessionRingParams() // Do not inherit the parent's session keyring. @@ -151,7 +151,7 @@ func (l *linuxStandardInit) Init() error { if err := selinux.SetExecLabel(l.config.ProcessLabel); err != nil { return errors.Wrap(err, "set process label") } - defer selinux.SetExecLabel("") + defer selinux.SetExecLabel("") //nolint: errcheck // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible. @@ -183,7 +183,7 @@ func (l *linuxStandardInit) Init() error { } // Close the pipe to signal that we have completed our init. logrus.Debugf("init: closing the pipe to signal completion") - l.pipe.Close() + _ = l.pipe.Close() // Close the log pipe fd so the parent's ForwardLogs can exit. if err := unix.Close(l.logFd); err != nil { @@ -207,7 +207,7 @@ func (l *linuxStandardInit) Init() error { // N.B. the core issue itself (passing dirfds to the host filesystem) has // since been resolved. // https://github.com/torvalds/linux/blob/v4.9/fs/exec.c#L1290-L1318 - unix.Close(l.fifoFd) + _ = unix.Close(l.fifoFd) // Set seccomp as close to execve as possible, so as few syscalls take // place afterward (reducing the amount of syscalls that users need to // enable in their seccomp profiles). @@ -224,7 +224,7 @@ func (l *linuxStandardInit) Init() error { return err } - if err := unix.Exec(name, l.config.Args[0:], os.Environ()); err != nil { + if err := system.Exec(name, l.config.Args[0:], os.Environ()); err != nil { return newSystemErrorWithCause(err, "exec user process") } return nil diff --git a/vendor/github.com/opencontainers/runc/libcontainer/state_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/state_linux.go index 02ff06ea9cc2..43c040c8573e 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/state_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/state_linux.go @@ -157,7 +157,7 @@ func (i *createdState) transition(s containerState) error { } func (i *createdState) destroy() error { - i.c.initProcess.signal(unix.SIGKILL) + _ = i.c.initProcess.signal(unix.SIGKILL) return destroy(i.c) } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/system/linux.go b/vendor/github.com/opencontainers/runc/libcontainer/system/linux.go index 4379a2070884..b9fd0832d569 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/system/linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/system/linux.go @@ -35,7 +35,16 @@ func Execv(cmd string, args []string, env []string) error { return err } - return unix.Exec(name, args, env) + return Exec(name, args, env) +} + +func Exec(cmd string, args []string, env []string) error { + for { + err := unix.Exec(cmd, args, env) + if err != unix.EINTR { //nolint:errorlint // unix errors are bare + return err + } + } } func Prlimit(pid, resource int, limit unix.Rlimit) error { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/system/proc.go b/vendor/github.com/opencontainers/runc/libcontainer/system/proc.go index b73cf70b4344..d0407cfe42a6 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/system/proc.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/system/proc.go @@ -96,7 +96,7 @@ func parseStat(data string) (stat Stat_t, err error) { // one (PID) and two (Name) in the paren-split. parts = strings.Split(data[i+2:], " ") var state int - fmt.Sscanf(parts[3-3], "%c", &state) + fmt.Sscanf(parts[3-3], "%c", &state) //nolint:staticcheck // "3-3" is more readable in this context. stat.State = State(state) fmt.Sscanf(parts[22-3], "%d", &stat.StartTime) return stat, nil diff --git a/vendor/github.com/opencontainers/runc/libcontainer/system/userns_deprecated.go b/vendor/github.com/opencontainers/runc/libcontainer/system/userns_deprecated.go deleted file mode 100644 index 2de3462a5068..000000000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/system/userns_deprecated.go +++ /dev/null @@ -1,5 +0,0 @@ -package system - -import "github.com/opencontainers/runc/libcontainer/userns" - -var RunningInUserNS = userns.RunningInUserNS diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go index 68da4400d463..cc7a106be5db 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go @@ -2,6 +2,7 @@ package user import ( "bufio" + "bytes" "errors" "fmt" "io" @@ -11,19 +12,17 @@ import ( ) const ( - minId = 0 - maxId = 1<<31 - 1 //for 32-bit systems compatibility + minID = 0 + maxID = 1<<31 - 1 // for 32-bit systems compatibility ) var ( - // The current operating system does not provide the required data for user lookups. - ErrUnsupported = errors.New("user lookup: operating system does not provide passwd-formatted data") - - // No matching entries found in file. + // ErrNoPasswdEntries is returned if no matching entries were found in /etc/group. ErrNoPasswdEntries = errors.New("no matching entries in passwd file") - ErrNoGroupEntries = errors.New("no matching entries in group file") - - ErrRange = fmt.Errorf("uids and gids must be in range %d-%d", minId, maxId) + // ErrNoGroupEntries is returned if no matching entries were found in /etc/passwd. + ErrNoGroupEntries = errors.New("no matching entries in group file") + // ErrRange is returned if a UID or GID is outside of the valid range. + ErrRange = fmt.Errorf("uids and gids must be in range %d-%d", minID, maxID) ) type User struct { @@ -57,11 +56,11 @@ type IDMap struct { Count int64 } -func parseLine(line string, v ...interface{}) { - parseParts(strings.Split(line, ":"), v...) +func parseLine(line []byte, v ...interface{}) { + parseParts(bytes.Split(line, []byte(":")), v...) } -func parseParts(parts []string, v ...interface{}) { +func parseParts(parts [][]byte, v ...interface{}) { if len(parts) == 0 { return } @@ -77,16 +76,16 @@ func parseParts(parts []string, v ...interface{}) { // This is legit. switch e := v[i].(type) { case *string: - *e = p + *e = string(p) case *int: // "numbers", with conversion errors ignored because of some misbehaving configuration files. - *e, _ = strconv.Atoi(p) + *e, _ = strconv.Atoi(string(p)) case *int64: - *e, _ = strconv.ParseInt(p, 10, 64) + *e, _ = strconv.ParseInt(string(p), 10, 64) case *[]string: // Comma-separated lists. - if p != "" { - *e = strings.Split(p, ",") + if len(p) != 0 { + *e = strings.Split(string(p), ",") } else { *e = []string{} } @@ -130,8 +129,8 @@ func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) { ) for s.Scan() { - line := strings.TrimSpace(s.Text()) - if line == "" { + line := bytes.TrimSpace(s.Bytes()) + if len(line) == 0 { continue } @@ -181,15 +180,53 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) { if r == nil { return nil, fmt.Errorf("nil source for group-formatted data") } + rd := bufio.NewReader(r) + out := []Group{} - var ( - s = bufio.NewScanner(r) - out = []Group{} - ) + // Read the file line-by-line. + for { + var ( + isPrefix bool + wholeLine []byte + err error + ) - for s.Scan() { - text := s.Text() - if text == "" { + // Read the next line. We do so in chunks (as much as reader's + // buffer is able to keep), check if we read enough columns + // already on each step and store final result in wholeLine. + for { + var line []byte + line, isPrefix, err = rd.ReadLine() + + if err != nil { + // We should return no error if EOF is reached + // without a match. + if err == io.EOF { //nolint:errorlint // comparison with io.EOF is legit, https://github.com/polyfloyd/go-errorlint/pull/12 + err = nil + } + return out, err + } + + // Simple common case: line is short enough to fit in a + // single reader's buffer. + if !isPrefix && len(wholeLine) == 0 { + wholeLine = line + break + } + + wholeLine = append(wholeLine, line...) + + // Check if we read the whole line already. + if !isPrefix { + break + } + } + + // There's no spec for /etc/passwd or /etc/group, but we try to follow + // the same rules as the glibc parser, which allows comments and blank + // space at the beginning of a line. + wholeLine = bytes.TrimSpace(wholeLine) + if len(wholeLine) == 0 || wholeLine[0] == '#' { continue } @@ -199,17 +236,12 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) { // root:x:0:root // adm:x:4:root,adm,daemon p := Group{} - parseLine(text, &p.Name, &p.Pass, &p.Gid, &p.List) + parseLine(wholeLine, &p.Name, &p.Pass, &p.Gid, &p.List) if filter == nil || filter(p) { out = append(out, p) } } - if err := s.Err(); err != nil { - return nil, err - } - - return out, nil } type ExecUser struct { @@ -280,7 +312,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( // Allow for userArg to have either "user" syntax, or optionally "user:group" syntax var userArg, groupArg string - parseLine(userSpec, &userArg, &groupArg) + parseLine([]byte(userSpec), &userArg, &groupArg) // Convert userArg and groupArg to be numeric, so we don't have to execute // Atoi *twice* for each iteration over lines. @@ -328,7 +360,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( user.Uid = uidArg // Must be inside valid uid range. - if user.Uid < minId || user.Uid > maxId { + if user.Uid < minID || user.Uid > maxID { return nil, ErrRange } @@ -377,7 +409,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( user.Gid = gidArg // Must be inside valid gid range. - if user.Gid < minId || user.Gid > maxId { + if user.Gid < minID || user.Gid > maxID { return nil, ErrRange } @@ -401,7 +433,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( // or the given group data is nil, the id will be returned as-is // provided it is in the legal range. func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, error) { - var groups = []Group{} + groups := []Group{} if group != nil { var err error groups, err = ParseGroupFilter(group, func(g Group) bool { @@ -439,7 +471,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err return nil, fmt.Errorf("Unable to find group %s", ag) } // Ensure gid is inside gid range. - if gid < minId || gid > maxId { + if gid < minID || gid > maxID { return nil, ErrRange } gidMap[int(gid)] = struct{}{} @@ -498,8 +530,8 @@ func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) { ) for s.Scan() { - line := strings.TrimSpace(s.Text()) - if line == "" { + line := bytes.TrimSpace(s.Bytes()) + if len(line) == 0 { continue } @@ -551,14 +583,14 @@ func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) { ) for s.Scan() { - line := strings.TrimSpace(s.Text()) - if line == "" { + line := bytes.TrimSpace(s.Bytes()) + if len(line) == 0 { continue } // see: man 7 user_namespaces p := IDMap{} - parseParts(strings.Fields(line), &p.ID, &p.ParentID, &p.Count) + parseParts(bytes.Fields(line), &p.ID, &p.ParentID, &p.Count) if filter == nil || filter(p) { out = append(out, p) diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/doc.go b/vendor/github.com/opencontainers/selinux/go-selinux/doc.go index 9c9cbd120aa1..0ac7d819e6d3 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/doc.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/doc.go @@ -1,10 +1,6 @@ /* Package selinux provides a high-level interface for interacting with selinux. -This package uses a selinux build tag to enable the selinux functionality. This -allows non-linux and linux users who do not have selinux support to still use -tools that rely on this library. - Usage: import "github.com/opencontainers/selinux/go-selinux" diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go index 43945551172b..b3d142d8c5bf 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go @@ -25,6 +25,8 @@ var ErrIncompatibleLabel = errors.New("Bad SELinux option z and Z can not be use // the container. A list of options can be passed into this function to alter // the labels. The labels returned will include a random MCS String, that is // guaranteed to be unique. +// If the disabled flag is passed in, the process label will not be set, but the mount label will be set +// to the container_file label with the maximum category. This label is not usable by any confined label. func InitLabels(options []string) (plabel string, mlabel string, retErr error) { if !selinux.GetEnabled() { return "", "", nil @@ -47,7 +49,8 @@ func InitLabels(options []string) (plabel string, mlabel string, retErr error) { } for _, opt := range options { if opt == "disable" { - return "", mountLabel, nil + selinux.ReleaseLabel(mountLabel) + return "", selinux.PrivContainerMountLabel(), nil } if i := strings.Index(opt, ":"); i == -1 { return "", "", errors.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt) diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go index d9119908b782..b336ebad3abb 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go @@ -11,9 +11,10 @@ const ( Permissive = 0 // Disabled constant to indicate SELinux is disabled Disabled = -1 - + // maxCategory is the maximum number of categories used within containers + maxCategory = 1024 // DefaultCategoryRange is the upper bound on the category range - DefaultCategoryRange = uint32(1024) + DefaultCategoryRange = uint32(maxCategory) ) var ( @@ -276,3 +277,8 @@ func DisableSecOpt() []string { func GetDefaultContextWithLevel(user, level, scon string) (string, error) { return getDefaultContextWithLevel(user, level, scon) } + +// PrivContainerMountLabel returns mount label for privileged containers +func PrivContainerMountLabel() string { + return privContainerMountLabel +} diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go index 5bfcc0490269..a91a116f8481 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go @@ -16,9 +16,9 @@ import ( "strings" "sync" + "github.com/bits-and-blooms/bitset" "github.com/opencontainers/selinux/pkg/pwalk" "github.com/pkg/errors" - "github.com/willf/bitset" "golang.org/x/sys/unix" ) @@ -892,13 +892,13 @@ func openContextFile() (*os.File, error) { return os.Open(lxcPath) } -var labels = loadLabels() +var labels, privContainerMountLabel = loadLabels() -func loadLabels() map[string]string { +func loadLabels() (map[string]string, string) { labels := make(map[string]string) in, err := openContextFile() if err != nil { - return labels + return labels, "" } defer in.Close() @@ -920,7 +920,10 @@ func loadLabels() map[string]string { } } - return labels + con, _ := NewContext(labels["file"]) + con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1) + reserveLabel(con.get()) + return labels, con.get() } // kvmContainerLabels returns the default processLabel and mountLabel to be used diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go index 70b7b7c8519d..b7218a0b6a85 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go @@ -2,6 +2,8 @@ package selinux +const privContainerMountLabel = "" + func setDisabled() { } diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml index 5e20aa4140c3..c1dbd5a3a3e2 100644 --- a/vendor/github.com/sirupsen/logrus/.travis.yml +++ b/vendor/github.com/sirupsen/logrus/.travis.yml @@ -4,14 +4,12 @@ git: depth: 1 env: - GO111MODULE=on -go: [1.13.x, 1.14.x] -os: [linux, osx] +go: 1.15.x +os: linux install: - ./travis/install.sh script: - - ./travis/cross_build.sh - - ./travis/lint.sh - - export GOMAXPROCS=4 - - export GORACE=halt_on_error=1 - - go test -race -v ./... - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi + - cd ci + - go run mage.go -v -w ../ crossBuild + - go run mage.go -v -w ../ lint + - go run mage.go -v -w ../ test diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md index 584026d67caa..7567f612898c 100644 --- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -1,3 +1,39 @@ +# 1.8.1 +Code quality: + * move magefile in its own subdir/submodule to remove magefile dependency on logrus consumer + * improve timestamp format documentation + +Fixes: + * fix race condition on logger hooks + + +# 1.8.0 + +Correct versioning number replacing v1.7.1. + +# 1.7.1 + +Beware this release has introduced a new public API and its semver is therefore incorrect. + +Code quality: + * use go 1.15 in travis + * use magefile as task runner + +Fixes: + * small fixes about new go 1.13 error formatting system + * Fix for long time race condiction with mutating data hooks + +Features: + * build support for zos + +# 1.7.0 +Fixes: + * the dependency toward a windows terminal library has been removed + +Features: + * a new buffer pool management API has been added + * a set of `Fn()` functions have been added + # 1.6.0 Fixes: * end of line cleanup diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md index 5796706dbfa2..5152b6aa406f 100644 --- a/vendor/github.com/sirupsen/logrus/README.md +++ b/vendor/github.com/sirupsen/logrus/README.md @@ -402,7 +402,7 @@ func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { // source of the official loggers. serialized, err := json.Marshal(entry.Data) if err != nil { - return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + return nil, fmt.Errorf("Failed to marshal fields to JSON, %w", err) } return append(serialized, '\n'), nil } diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go index 5a5cbfe7c897..07a1e5fa7249 100644 --- a/vendor/github.com/sirupsen/logrus/entry.go +++ b/vendor/github.com/sirupsen/logrus/entry.go @@ -78,6 +78,14 @@ func NewEntry(logger *Logger) *Entry { } } +func (entry *Entry) Dup() *Entry { + data := make(Fields, len(entry.Data)) + for k, v := range entry.Data { + data[k] = v + } + return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, Context: entry.Context, err: entry.err} +} + // Returns the bytes representation of this entry from the formatter. func (entry *Entry) Bytes() ([]byte, error) { return entry.Logger.Formatter.Format(entry) @@ -123,11 +131,9 @@ func (entry *Entry) WithFields(fields Fields) *Entry { for k, v := range fields { isErrField := false if t := reflect.TypeOf(v); t != nil { - switch t.Kind() { - case reflect.Func: + switch { + case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func: isErrField = true - case reflect.Ptr: - isErrField = t.Elem().Kind() == reflect.Func } } if isErrField { @@ -212,68 +218,72 @@ func (entry Entry) HasCaller() (has bool) { entry.Caller != nil } -// This function is not declared with a pointer value because otherwise -// race conditions will occur when using multiple goroutines -func (entry Entry) log(level Level, msg string) { +func (entry *Entry) log(level Level, msg string) { var buffer *bytes.Buffer - // Default to now, but allow users to override if they want. - // - // We don't have to worry about polluting future calls to Entry#log() - // with this assignment because this function is declared with a - // non-pointer receiver. - if entry.Time.IsZero() { - entry.Time = time.Now() + newEntry := entry.Dup() + + if newEntry.Time.IsZero() { + newEntry.Time = time.Now() } - entry.Level = level - entry.Message = msg - entry.Logger.mu.Lock() - if entry.Logger.ReportCaller { - entry.Caller = getCaller() + newEntry.Level = level + newEntry.Message = msg + + newEntry.Logger.mu.Lock() + reportCaller := newEntry.Logger.ReportCaller + newEntry.Logger.mu.Unlock() + + if reportCaller { + newEntry.Caller = getCaller() } - entry.Logger.mu.Unlock() - entry.fireHooks() + newEntry.fireHooks() buffer = getBuffer() defer func() { - entry.Buffer = nil + newEntry.Buffer = nil putBuffer(buffer) }() buffer.Reset() - entry.Buffer = buffer + newEntry.Buffer = buffer - entry.write() + newEntry.write() - entry.Buffer = nil + newEntry.Buffer = nil // To avoid Entry#log() returning a value that only would make sense for // panic() to use in Entry#Panic(), we avoid the allocation by checking // directly here. if level <= PanicLevel { - panic(&entry) + panic(newEntry) } } func (entry *Entry) fireHooks() { + var tmpHooks LevelHooks entry.Logger.mu.Lock() - defer entry.Logger.mu.Unlock() - err := entry.Logger.Hooks.Fire(entry.Level, entry) + tmpHooks = make(LevelHooks, len(entry.Logger.Hooks)) + for k, v := range entry.Logger.Hooks { + tmpHooks[k] = v + } + entry.Logger.mu.Unlock() + + err := tmpHooks.Fire(entry.Level, entry) if err != nil { fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) } } func (entry *Entry) write() { - entry.Logger.mu.Lock() - defer entry.Logger.mu.Unlock() serialized, err := entry.Logger.Formatter.Format(entry) if err != nil { fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) return } - if _, err = entry.Logger.Out.Write(serialized); err != nil { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + if _, err := entry.Logger.Out.Write(serialized); err != nil { fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) } } @@ -319,7 +329,6 @@ func (entry *Entry) Fatal(args ...interface{}) { func (entry *Entry) Panic(args ...interface{}) { entry.Log(PanicLevel, args...) - panic(fmt.Sprint(args...)) } // Entry Printf family functions diff --git a/vendor/github.com/sirupsen/logrus/go.sum b/vendor/github.com/sirupsen/logrus/go.sum index 1edc143bed02..694c18b84546 100644 --- a/vendor/github.com/sirupsen/logrus/go.sum +++ b/vendor/github.com/sirupsen/logrus/go.sum @@ -4,7 +4,5 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go index ba7f237112bd..c96dc5636bf0 100644 --- a/vendor/github.com/sirupsen/logrus/json_formatter.go +++ b/vendor/github.com/sirupsen/logrus/json_formatter.go @@ -23,6 +23,9 @@ func (f FieldMap) resolve(key fieldKey) string { // JSONFormatter formats logs into parsable json type JSONFormatter struct { // TimestampFormat sets the format used for marshaling timestamps. + // The format to use is the same than for time.Format or time.Parse from the standard + // library. + // The standard Library already provides a set of predefined format. TimestampFormat string // DisableTimestamp allows disabling automatic timestamps in output @@ -118,7 +121,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { encoder.SetIndent("", " ") } if err := encoder.Encode(data); err != nil { - return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err) + return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err) } return b.Bytes(), nil diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go index dbf627c97541..337704457a28 100644 --- a/vendor/github.com/sirupsen/logrus/logger.go +++ b/vendor/github.com/sirupsen/logrus/logger.go @@ -12,7 +12,7 @@ import ( // LogFunction For big messages, it can be more efficient to pass a function // and only call it if the log level is actually enables rather than // generating the log message and then checking if the level is enabled -type LogFunction func()[]interface{} +type LogFunction func() []interface{} type Logger struct { // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go index cc4fe6e31776..04748b8515f1 100644 --- a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go +++ b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go @@ -1,4 +1,4 @@ -// +build linux aix +// +build linux aix zos // +build !js package logrus diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go index 3c28b54cabae..be2c6efe5ed0 100644 --- a/vendor/github.com/sirupsen/logrus/text_formatter.go +++ b/vendor/github.com/sirupsen/logrus/text_formatter.go @@ -53,7 +53,10 @@ type TextFormatter struct { // the time passed since beginning of execution. FullTimestamp bool - // TimestampFormat to use for display when a full timestamp is printed + // TimestampFormat to use for display when a full timestamp is printed. + // The format to use is the same than for time.Format or time.Parse from the standard + // library. + // The standard Library already provides a set of predefined format. TimestampFormat string // The fields are sorted by default for a consistent output. For applications @@ -235,6 +238,8 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin levelColor = yellow case ErrorLevel, FatalLevel, PanicLevel: levelColor = red + case InfoLevel: + levelColor = blue default: levelColor = blue } diff --git a/vendor/github.com/willf/bitset/go.mod b/vendor/github.com/willf/bitset/go.mod deleted file mode 100644 index 583ecab78f74..000000000000 --- a/vendor/github.com/willf/bitset/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/willf/bitset - -go 1.14 diff --git a/vendor/modules.txt b/vendor/modules.txt index ad8d5b4699fc..9b084d1d6eb4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -143,6 +143,8 @@ github.com/aws/aws-sdk-go/service/sts github.com/aws/aws-sdk-go/service/sts/stsiface # github.com/beorn7/perks v1.0.1 => github.com/beorn7/perks v1.0.1 github.com/beorn7/perks/quantile +# github.com/bits-and-blooms/bitset v1.2.0 => github.com/bits-and-blooms/bitset v1.2.0 +github.com/bits-and-blooms/bitset # github.com/blang/semver v3.5.1+incompatible => github.com/blang/semver v3.5.1+incompatible ## explicit github.com/blang/semver @@ -158,7 +160,7 @@ github.com/chai2010/gettext-go/gettext/po # github.com/checkpoint-restore/go-criu/v5 v5.0.0 => github.com/checkpoint-restore/go-criu/v5 v5.0.0 github.com/checkpoint-restore/go-criu/v5 github.com/checkpoint-restore/go-criu/v5/rpc -# github.com/cilium/ebpf v0.5.0 => github.com/cilium/ebpf v0.5.0 +# github.com/cilium/ebpf v0.6.2 => github.com/cilium/ebpf v0.6.2 github.com/cilium/ebpf github.com/cilium/ebpf/asm github.com/cilium/ebpf/internal @@ -615,7 +617,7 @@ github.com/opencontainers/go-digest # github.com/opencontainers/image-spec v1.0.1 => github.com/opencontainers/image-spec v1.0.1 github.com/opencontainers/image-spec/specs-go github.com/opencontainers/image-spec/specs-go/v1 -# github.com/opencontainers/runc v1.0.0-rc95 => github.com/opencontainers/runc v1.0.0-rc95 +# github.com/opencontainers/runc v1.0.1 => github.com/opencontainers/runc v1.0.1 ## explicit github.com/opencontainers/runc/libcontainer github.com/opencontainers/runc/libcontainer/apparmor @@ -644,7 +646,7 @@ github.com/opencontainers/runc/libcontainer/utils github.com/opencontainers/runc/types # github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 github.com/opencontainers/runtime-spec/specs-go -# github.com/opencontainers/selinux v1.8.0 => github.com/opencontainers/selinux v1.8.0 +# github.com/opencontainers/selinux v1.8.2 => github.com/opencontainers/selinux v1.8.2 ## explicit github.com/opencontainers/selinux/go-selinux github.com/opencontainers/selinux/go-selinux/label @@ -695,7 +697,7 @@ github.com/russross/blackfriday/v2 github.com/seccomp/libseccomp-golang # github.com/shurcooL/sanitized_anchor_name v1.0.0 => github.com/shurcooL/sanitized_anchor_name v1.0.0 github.com/shurcooL/sanitized_anchor_name -# github.com/sirupsen/logrus v1.7.0 => github.com/sirupsen/logrus v1.7.0 +# github.com/sirupsen/logrus v1.8.1 => github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus # github.com/soheilhy/cmux v0.1.5 => github.com/soheilhy/cmux v0.1.5 github.com/soheilhy/cmux @@ -764,8 +766,6 @@ github.com/vmware/govmomi/vim25/progress github.com/vmware/govmomi/vim25/soap github.com/vmware/govmomi/vim25/types github.com/vmware/govmomi/vim25/xml -# github.com/willf/bitset v1.1.11 => github.com/willf/bitset v1.1.11 -github.com/willf/bitset # github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 => github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 github.com/xiang90/probing # github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca => github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca @@ -2420,6 +2420,7 @@ sigs.k8s.io/yaml # github.com/benbjohnson/clock => github.com/benbjohnson/clock v1.0.3 # github.com/beorn7/perks => github.com/beorn7/perks v1.0.1 # github.com/bgentry/speakeasy => github.com/bgentry/speakeasy v0.1.0 +# github.com/bits-and-blooms/bitset => github.com/bits-and-blooms/bitset v1.2.0 # github.com/bketelsen/crypt => github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c # github.com/blang/semver => github.com/blang/semver v3.5.1+incompatible # github.com/boltdb/bolt => github.com/boltdb/bolt v1.3.1 @@ -2431,7 +2432,7 @@ sigs.k8s.io/yaml # github.com/chzyer/logex => github.com/chzyer/logex v1.1.10 # github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e # github.com/chzyer/test => github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 -# github.com/cilium/ebpf => github.com/cilium/ebpf v0.5.0 +# github.com/cilium/ebpf => github.com/cilium/ebpf v0.6.2 # github.com/clusterhq/flocker-go => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 # github.com/cncf/udpa/go => github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 # github.com/cockroachdb/datadriven => github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 @@ -2607,9 +2608,9 @@ sigs.k8s.io/yaml # github.com/onsi/gomega => github.com/onsi/gomega v1.10.1 # github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0 # github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.1 -# github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc95 +# github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.1 # github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 -# github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.8.0 +# github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.8.2 # github.com/opentracing/opentracing-go => github.com/opentracing/opentracing-go v1.1.0 # github.com/pascaldekloe/goe => github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c # github.com/pelletier/go-toml => github.com/pelletier/go-toml v1.2.0 @@ -2635,7 +2636,7 @@ sigs.k8s.io/yaml # github.com/seccomp/libseccomp-golang => github.com/seccomp/libseccomp-golang v0.9.1 # github.com/sergi/go-diff => github.com/sergi/go-diff v1.1.0 # github.com/shurcooL/sanitized_anchor_name => github.com/shurcooL/sanitized_anchor_name v1.0.0 -# github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.7.0 +# github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.8.1 # github.com/smartystreets/assertions => github.com/smartystreets/assertions v1.1.0 # github.com/smartystreets/goconvey => github.com/smartystreets/goconvey v1.6.4 # github.com/soheilhy/cmux => github.com/soheilhy/cmux v0.1.5 @@ -2657,7 +2658,6 @@ sigs.k8s.io/yaml # github.com/vishvananda/netlink => github.com/vishvananda/netlink v1.1.0 # github.com/vishvananda/netns => github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae # github.com/vmware/govmomi => github.com/vmware/govmomi v0.20.3 -# github.com/willf/bitset => github.com/willf/bitset v1.1.11 # github.com/xiang90/probing => github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 # github.com/xlab/treeprint => github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca # github.com/yuin/goldmark => github.com/yuin/goldmark v1.3.5 From 83de5b10ec8c60713c2738715c78745f81e58ffd Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 21 May 2021 13:53:23 -0700 Subject: [PATCH 2/2] kubelet/cm: don't set Devices Since runc 1.0.0 it is now sufficient to have SkipDevices: true. Signed-off-by: Kir Kolyshkin --- pkg/kubelet/cm/cgroup_manager_linux.go | 10 ---------- pkg/kubelet/cm/container_manager_linux.go | 10 ---------- pkg/kubelet/dockershim/cm/container_manager_linux.go | 10 ---------- 3 files changed, 30 deletions(-) diff --git a/pkg/kubelet/cm/cgroup_manager_linux.go b/pkg/kubelet/cm/cgroup_manager_linux.go index 90393298138a..7d2644026fdf 100644 --- a/pkg/kubelet/cm/cgroup_manager_linux.go +++ b/pkg/kubelet/cm/cgroup_manager_linux.go @@ -33,7 +33,6 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" cgroupsystemd "github.com/opencontainers/runc/libcontainer/cgroups/systemd" libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs" - libcontainerdevices "github.com/opencontainers/runc/libcontainer/devices" "k8s.io/klog/v2" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" @@ -380,15 +379,6 @@ func getSupportedUnifiedControllers() sets.String { func (m *cgroupManagerImpl) toResources(resourceConfig *ResourceConfig) *libcontainerconfigs.Resources { resources := &libcontainerconfigs.Resources{ - Devices: []*libcontainerdevices.Rule{ - { - Type: 'a', - Permissions: "rwm", - Allow: true, - Minor: libcontainerdevices.Wildcard, - Major: libcontainerdevices.Wildcard, - }, - }, SkipDevices: true, } if resourceConfig == nil { diff --git a/pkg/kubelet/cm/container_manager_linux.go b/pkg/kubelet/cm/container_manager_linux.go index 31a728b72919..d7aa6270f2b9 100644 --- a/pkg/kubelet/cm/container_manager_linux.go +++ b/pkg/kubelet/cm/container_manager_linux.go @@ -38,7 +38,6 @@ import ( utilio "k8s.io/utils/io" utilpath "k8s.io/utils/path" - libcontainerdevices "github.com/opencontainers/runc/libcontainer/devices" libcontaineruserns "github.com/opencontainers/runc/libcontainer/userns" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -396,15 +395,6 @@ func createManager(containerName string) (cgroups.Manager, error) { Parent: "/", Name: containerName, Resources: &configs.Resources{ - Devices: []*libcontainerdevices.Rule{ - { - Type: 'a', - Permissions: "rwm", - Allow: true, - Minor: libcontainerdevices.Wildcard, - Major: libcontainerdevices.Wildcard, - }, - }, SkipDevices: true, }, } diff --git a/pkg/kubelet/dockershim/cm/container_manager_linux.go b/pkg/kubelet/dockershim/cm/container_manager_linux.go index f515a5bfb25e..aa32936e7261 100644 --- a/pkg/kubelet/dockershim/cm/container_manager_linux.go +++ b/pkg/kubelet/dockershim/cm/container_manager_linux.go @@ -28,7 +28,6 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups" cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" "github.com/opencontainers/runc/libcontainer/configs" - libcontainerdevices "github.com/opencontainers/runc/libcontainer/devices" utilversion "k8s.io/apimachinery/pkg/util/version" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/klog/v2" @@ -127,15 +126,6 @@ func createCgroupManager(name string) (cgroups.Manager, error) { Memory: int64(memoryLimit), MemorySwap: -1, SkipDevices: true, - Devices: []*libcontainerdevices.Rule{ - { - Minor: libcontainerdevices.Wildcard, - Major: libcontainerdevices.Wildcard, - Type: 'a', - Permissions: "rwm", - Allow: true, - }, - }, }, } return cgroupfs.NewManager(cg, nil, false), nil