Переглянути джерело

Merge pull request #43083 from AkihiroSuda/runc-1.1.0

update runc to v1.1.0
Sebastiaan van Stijn 3 роки тому
батько
коміт
af4babd657
100 змінених файлів з 2481 додано та 1117 видалено
  1. 1 1
      hack/dockerfile/install/runc.installer
  2. 7 7
      vendor.mod
  3. 18 9
      vendor.sum
  4. 1 0
      vendor/github.com/cilium/ebpf/.gitignore
  5. 0 1
      vendor/github.com/cilium/ebpf/.golangci.yaml
  6. 2 2
      vendor/github.com/cilium/ebpf/ARCHITECTURE.md
  7. 2 2
      vendor/github.com/cilium/ebpf/CONTRIBUTING.md
  8. 4 1
      vendor/github.com/cilium/ebpf/Makefile
  9. 35 27
      vendor/github.com/cilium/ebpf/README.md
  10. 6 0
      vendor/github.com/cilium/ebpf/asm/func.go
  11. 6 0
      vendor/github.com/cilium/ebpf/asm/func_string.go
  12. 5 0
      vendor/github.com/cilium/ebpf/asm/instruction.go
  13. 65 0
      vendor/github.com/cilium/ebpf/attachtype_string.go
  14. 280 228
      vendor/github.com/cilium/ebpf/collection.go
  15. 152 28
      vendor/github.com/cilium/ebpf/elf_reader.go
  16. 1 0
      vendor/github.com/cilium/ebpf/elf_reader_fuzz.go
  17. 35 1
      vendor/github.com/cilium/ebpf/info.go
  18. 6 0
      vendor/github.com/cilium/ebpf/internal/align.go
  19. 146 147
      vendor/github.com/cilium/ebpf/internal/btf/btf.go
  20. 8 3
      vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
  21. 17 16
      vendor/github.com/cilium/ebpf/internal/btf/core.go
  22. 12 3
      vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
  23. 1 0
      vendor/github.com/cilium/ebpf/internal/btf/fuzz.go
  24. 48 0
      vendor/github.com/cilium/ebpf/internal/btf/info.go
  25. 1 7
      vendor/github.com/cilium/ebpf/internal/btf/strings.go
  26. 31 0
      vendor/github.com/cilium/ebpf/internal/btf/syscalls.go
  27. 126 62
      vendor/github.com/cilium/ebpf/internal/btf/types.go
  28. 2 2
      vendor/github.com/cilium/ebpf/internal/cpu.go
  29. 1 0
      vendor/github.com/cilium/ebpf/internal/ptr_32_be.go
  30. 1 0
      vendor/github.com/cilium/ebpf/internal/ptr_32_le.go
  31. 2 2
      vendor/github.com/cilium/ebpf/internal/ptr_64.go
  32. 59 0
      vendor/github.com/cilium/ebpf/internal/syscall.go
  33. 10 6
      vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
  34. 9 5
      vendor/github.com/cilium/ebpf/internal/unix/types_other.go
  35. 2 2
      vendor/github.com/cilium/ebpf/internal/version.go
  36. 88 0
      vendor/github.com/cilium/ebpf/link/freplace.go
  37. 22 16
      vendor/github.com/cilium/ebpf/link/kprobe.go
  38. 9 5
      vendor/github.com/cilium/ebpf/link/link.go
  39. 3 4
      vendor/github.com/cilium/ebpf/link/perf_event.go
  40. 5 4
      vendor/github.com/cilium/ebpf/link/syscalls.go
  41. 6 2
      vendor/github.com/cilium/ebpf/link/tracepoint.go
  42. 92 41
      vendor/github.com/cilium/ebpf/link/uprobe.go
  43. 21 2
      vendor/github.com/cilium/ebpf/linker.go
  44. 65 30
      vendor/github.com/cilium/ebpf/map.go
  45. 49 14
      vendor/github.com/cilium/ebpf/marshalers.go
  46. 78 45
      vendor/github.com/cilium/ebpf/prog.go
  47. 12 10
      vendor/github.com/cilium/ebpf/run-tests.sh
  48. 39 55
      vendor/github.com/cilium/ebpf/syscalls.go
  49. 33 3
      vendor/github.com/cilium/ebpf/types.go
  50. 8 61
      vendor/github.com/cilium/ebpf/types_string.go
  51. 5 5
      vendor/github.com/containerd/console/console_windows.go
  52. 163 0
      vendor/github.com/containerd/console/console_zos.go
  53. 1 1
      vendor/github.com/containerd/console/tc_unix.go
  54. 26 0
      vendor/github.com/containerd/console/tc_zos.go
  55. 5 3
      vendor/github.com/cyphar/filepath-securejoin/.travis.yml
  56. 17 3
      vendor/github.com/cyphar/filepath-securejoin/README.md
  57. 1 1
      vendor/github.com/cyphar/filepath-securejoin/VERSION
  58. 3 22
      vendor/github.com/cyphar/filepath-securejoin/join.go
  59. 0 1
      vendor/github.com/cyphar/filepath-securejoin/vendor.conf
  60. 6 6
      vendor/github.com/godbus/dbus/v5/README.md
  61. 9 6
      vendor/github.com/godbus/dbus/v5/auth.go
  62. 30 6
      vendor/github.com/godbus/dbus/v5/conn.go
  63. 11 5
      vendor/github.com/godbus/dbus/v5/decoder.go
  64. 43 18
      vendor/github.com/godbus/dbus/v5/encoder.go
  65. 30 7
      vendor/github.com/godbus/dbus/v5/export.go
  66. 52 21
      vendor/github.com/godbus/dbus/v5/message.go
  67. 50 16
      vendor/github.com/godbus/dbus/v5/sig.go
  68. 6 4
      vendor/github.com/godbus/dbus/v5/transport_generic.go
  69. 12 12
      vendor/github.com/godbus/dbus/v5/transport_unix.go
  70. 14 0
      vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go
  71. 0 2
      vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
  72. 0 3
      vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go
  73. 42 18
      vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
  74. 27 0
      vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go
  75. 13 3
      vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
  76. 66 49
      vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
  77. 13 6
      vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
  78. 16 4
      vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
  79. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
  80. 26 8
      vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
  81. 12 5
      vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
  82. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
  83. 3 0
      vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
  84. 9 0
      vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
  85. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
  86. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
  87. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
  88. 9 0
      vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go
  89. 6 6
      vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
  90. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
  91. 11 10
      vendor/github.com/opencontainers/runc/libcontainer/user/user.go
  92. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
  93. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
  94. 1 0
      vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
  95. 16 2
      vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
  96. 42 3
      vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
  97. 8 0
      vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
  98. 33 0
      vendor/github.com/opencontainers/selinux/go-selinux/xattrs_linux.go
  99. 0 4
      vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
  100. 4 3
      vendor/golang.org/x/sys/cpu/cpu_x86.go

+ 1 - 1
hack/dockerfile/install/runc.installer

@@ -9,7 +9,7 @@ set -e
 # the containerd project first, and update both after that is merged.
 # the containerd project first, and update both after that is merged.
 #
 #
 # When updating RUNC_VERSION, consider updating runc in vendor.mod accordingly
 # When updating RUNC_VERSION, consider updating runc in vendor.mod accordingly
-: "${RUNC_VERSION:=v1.0.3}"
+: "${RUNC_VERSION:=v1.1.0}"
 
 
 install_runc() {
 install_runc() {
 	RUNC_BUILDTAGS="${RUNC_BUILDTAGS:-"seccomp"}"
 	RUNC_BUILDTAGS="${RUNC_BUILDTAGS:-"seccomp"}"

+ 7 - 7
vendor.mod

@@ -36,7 +36,7 @@ require (
 	github.com/docker/swarmkit v1.12.1-0.20210726173615-3629f50980f6
 	github.com/docker/swarmkit v1.12.1-0.20210726173615-3629f50980f6
 	github.com/fluent/fluent-logger-golang v1.9.0
 	github.com/fluent/fluent-logger-golang v1.9.0
 	github.com/fsnotify/fsnotify v1.4.9
 	github.com/fsnotify/fsnotify v1.4.9
-	github.com/godbus/dbus/v5 v5.0.4
+	github.com/godbus/dbus/v5 v5.0.6
 	github.com/gogo/protobuf v1.3.2
 	github.com/gogo/protobuf v1.3.2
 	github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2
 	github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2
 	github.com/google/go-cmp v0.5.5
 	github.com/google/go-cmp v0.5.5
@@ -62,9 +62,9 @@ require (
 	github.com/morikuni/aec v1.0.0
 	github.com/morikuni/aec v1.0.0
 	github.com/opencontainers/go-digest v1.0.0
 	github.com/opencontainers/go-digest v1.0.0
 	github.com/opencontainers/image-spec v1.0.2
 	github.com/opencontainers/image-spec v1.0.2
-	github.com/opencontainers/runc v1.0.3
+	github.com/opencontainers/runc v1.1.0
 	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/selinux v1.9.1
+	github.com/opencontainers/selinux v1.10.0
 	github.com/pelletier/go-toml v1.9.1
 	github.com/pelletier/go-toml v1.9.1
 	github.com/pkg/errors v0.9.1
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.11.0
 	github.com/prometheus/client_golang v1.11.0
@@ -79,7 +79,7 @@ require (
 	go.etcd.io/bbolt v1.3.6
 	go.etcd.io/bbolt v1.3.6
 	golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
 	golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
-	golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359
+	golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
 	golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
 	golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
 	google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
 	google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
 	google.golang.org/grpc v1.40.0
 	google.golang.org/grpc v1.40.0
@@ -93,14 +93,14 @@ require (
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
 	github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
 	github.com/cespare/xxhash/v2 v2.1.1 // indirect
 	github.com/cespare/xxhash/v2 v2.1.1 // indirect
-	github.com/cilium/ebpf v0.6.2 // indirect
-	github.com/containerd/console v1.0.2 // indirect
+	github.com/cilium/ebpf v0.7.0 // indirect
+	github.com/containerd/console v1.0.3 // indirect
 	github.com/containerd/go-runc v1.0.0 // indirect
 	github.com/containerd/go-runc v1.0.0 // indirect
 	github.com/containerd/ttrpc v1.1.0 // indirect
 	github.com/containerd/ttrpc v1.1.0 // indirect
 	github.com/coreos/etcd v3.3.27+incompatible // indirect
 	github.com/coreos/etcd v3.3.27+incompatible // indirect
 	github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
 	github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
 	github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
 	github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
-	github.com/cyphar/filepath-securejoin v0.2.2 // indirect
+	github.com/cyphar/filepath-securejoin v0.2.3 // indirect
 	github.com/fernet/fernet-go v0.0.0-20180830025343-9eac43b88a5e // indirect
 	github.com/fernet/fernet-go v0.0.0-20180830025343-9eac43b88a5e // indirect
 	github.com/gofrs/flock v0.7.3 // indirect
 	github.com/gofrs/flock v0.7.3 // indirect
 	github.com/gogo/googleapis v1.4.0 // indirect
 	github.com/gogo/googleapis v1.4.0 // indirect

+ 18 - 9
vendor.sum

@@ -75,13 +75,15 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
 github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
 github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
 github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
+github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/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/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/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
 github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
 github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
 github.com/cilium/ebpf v0.4.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/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k=
+github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
 github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 h1:PqZ3bA4yzwywivzk7PBQWngJp2/PAS0bWRZerKteicY=
 github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 h1:PqZ3bA4yzwywivzk7PBQWngJp2/PAS0bWRZerKteicY=
 github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
 github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
@@ -92,8 +94,9 @@ github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTF
 github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
 github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
 github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
 github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
 github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
 github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
-github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE=
 github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
 github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
+github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
+github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
 github.com/containerd/containerd v1.5.8 h1:NmkCC1/QxyZFBny8JogwLpOy2f+VEbO/f6bV2Mqtwuw=
 github.com/containerd/containerd v1.5.8 h1:NmkCC1/QxyZFBny8JogwLpOy2f+VEbO/f6bV2Mqtwuw=
 github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
 github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
 github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
 github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
@@ -142,8 +145,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
 github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
 github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
 github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
+github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
+github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
 github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
 github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
 github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
 github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
 github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
 github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
@@ -215,8 +219,9 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
 github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
 github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
+github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gofrs/flock v0.7.3 h1:I0EKY9l8HZCXTMYC4F80vwT6KNypV9uYKP3Alm/hjmQ=
 github.com/gofrs/flock v0.7.3 h1:I0EKY9l8HZCXTMYC4F80vwT6KNypV9uYKP3Alm/hjmQ=
 github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 github.com/gogo/googleapis v1.3.2 h1:kX1es4djPJrsDhY7aZKJy7aZasdcB5oSOEphMjSB53c=
 github.com/gogo/googleapis v1.3.2 h1:kX1es4djPJrsDhY7aZKJy7aZasdcB5oSOEphMjSB53c=
@@ -415,16 +420,16 @@ github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrB
 github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
 github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
 github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
 github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
-github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
-github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
+github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8=
+github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
 github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 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 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 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/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
 github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
 github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
 github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
-github.com/opencontainers/selinux v1.9.1 h1:b4VPEF3O5JLZgdTDBmGepaaIbAo0GqoF6EBRq5f/g3Y=
-github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
+github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
+github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
 github.com/opentracing-contrib/go-stdlib v1.0.0 h1:TBS7YuVotp8myLon4Pv7BtCBzOTo1DeZCld0Z63mW2w=
 github.com/opentracing-contrib/go-stdlib v1.0.0 h1:TBS7YuVotp8myLon4Pv7BtCBzOTo1DeZCld0Z63mW2w=
 github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU=
 github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@@ -464,6 +469,7 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
 github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
+github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
 github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
 github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
 github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
@@ -631,8 +637,11 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
+golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
 golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=

+ 1 - 0
vendor/github.com/cilium/ebpf/.gitignore

@@ -5,6 +5,7 @@
 *.so
 *.so
 *.dylib
 *.dylib
 *.o
 *.o
+!*_bpf*.o
 
 
 # Test binary, build with `go test -c`
 # Test binary, build with `go test -c`
 *.test
 *.test

+ 0 - 1
vendor/github.com/cilium/ebpf/.golangci.yaml

@@ -24,6 +24,5 @@ linters:
 
 
     # Could be enabled later:
     # Could be enabled later:
     # - gocyclo
     # - gocyclo
-    # - prealloc
     # - maligned
     # - maligned
     # - gosec
     # - gosec

+ 2 - 2
vendor/github.com/cilium/ebpf/ARCHITECTURE.md

@@ -57,7 +57,7 @@ Objects
 loading a spec will fail because the kernel is too old, or a feature is not
 loading a spec will fail because the kernel is too old, or a feature is not
 enabled. There are multiple ways the library deals with that:
 enabled. There are multiple ways the library deals with that:
 
 
-* Fallback: older kernels don't allowing naming programs and maps. The library
+* Fallback: older kernels don't allow naming programs and maps. The library
   automatically detects support for names, and omits them during load if
   automatically detects support for names, and omits them during load if
   necessary. This works since name is primarily a debug aid.
   necessary. This works since name is primarily a debug aid.
 
 
@@ -68,7 +68,7 @@ enabled. There are multiple ways the library deals with that:
 Once program and map objects are loaded they expose the kernel's low-level API,
 Once program and map objects are loaded they expose the kernel's low-level API,
 e.g. `NextKey`. Often this API is awkward to use in Go, so there are safer
 e.g. `NextKey`. Often this API is awkward to use in Go, so there are safer
 wrappers on top of the low-level API, like `MapIterator`. The low-level API is
 wrappers on top of the low-level API, like `MapIterator`. The low-level API is
-useful as an out when our higher-level API doesn't support a particular use case.
+useful when our higher-level API doesn't support a particular use case.
 
 
 Links
 Links
 ---
 ---

+ 2 - 2
vendor/github.com/cilium/ebpf/CONTRIBUTING.md

@@ -6,8 +6,8 @@ are welcome. Please take a look at [the architecture](ARCHITECTURE.md) to get
 a better understanding for the high-level goals.
 a better understanding for the high-level goals.
 
 
 New features must be accompanied by tests. Before starting work on any large
 New features must be accompanied by tests. Before starting work on any large
-feature, please [join](https://cilium.herokuapp.com/) the
-[#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack to
+feature, please [join](https://ebpf.io/slack) the
+[#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack to
 discuss the design first.
 discuss the design first.
 
 
 When submitting pull requests, consider writing details about what problem you
 When submitting pull requests, consider writing details about what problem you

+ 4 - 1
vendor/github.com/cilium/ebpf/Makefile

@@ -18,11 +18,14 @@ TARGETS := \
 	testdata/loader-clang-7 \
 	testdata/loader-clang-7 \
 	testdata/loader-clang-9 \
 	testdata/loader-clang-9 \
 	testdata/loader-$(CLANG) \
 	testdata/loader-$(CLANG) \
+	testdata/btf_map_init \
 	testdata/invalid_map \
 	testdata/invalid_map \
 	testdata/raw_tracepoint \
 	testdata/raw_tracepoint \
 	testdata/invalid_map_static \
 	testdata/invalid_map_static \
-	testdata/initialized_btf_map \
+	testdata/invalid_btf_map_init \
 	testdata/strings \
 	testdata/strings \
+	testdata/freplace \
+	testdata/iproute2_map_compat \
 	internal/btf/testdata/relocs
 	internal/btf/testdata/relocs
 
 
 .PHONY: all clean docker-all docker-shell
 .PHONY: all clean docker-all docker-shell

+ 35 - 27
vendor/github.com/cilium/ebpf/README.md

@@ -2,28 +2,16 @@
 
 
 [![PkgGoDev](https://pkg.go.dev/badge/github.com/cilium/ebpf)](https://pkg.go.dev/github.com/cilium/ebpf)
 [![PkgGoDev](https://pkg.go.dev/badge/github.com/cilium/ebpf)](https://pkg.go.dev/github.com/cilium/ebpf)
 
 
+![HoneyGopher](.github/images/cilium-ebpf.png)
+
 eBPF is a pure Go library that provides utilities for loading, compiling, and
 eBPF is a pure Go library that provides utilities for loading, compiling, and
 debugging eBPF programs. It has minimal external dependencies and is intended to
 debugging eBPF programs. It has minimal external dependencies and is intended to
 be used in long running processes.
 be used in long running processes.
 
 
-* [asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic
-  assembler
-* [link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF
-  to various hooks
-* [perf](https://pkg.go.dev/github.com/cilium/ebpf/perf) allows reading from a
-  `PERF_EVENT_ARRAY`
-* [cmd/bpf2go](https://pkg.go.dev/github.com/cilium/ebpf/cmd/bpf2go) allows
-  compiling and embedding eBPF programs in Go code
-
 The library is maintained by [Cloudflare](https://www.cloudflare.com) and
 The library is maintained by [Cloudflare](https://www.cloudflare.com) and
-[Cilium](https://www.cilium.io). Feel free to
-[join](https://cilium.herokuapp.com/) the
-[#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack.
-
-## Current status
+[Cilium](https://www.cilium.io).
 
 
-The package is production ready, but **the API is explicitly unstable right
-now**. Expect to update your code if you want to follow along.
+See [ebpf.io](https://ebpf.io) for other projects from the eBPF ecosystem.
 
 
 ## Getting Started
 ## Getting Started
 
 
@@ -33,21 +21,37 @@ your own tools can be found under [examples/](examples/).
 Contributions are highly encouraged, as they highlight certain use cases of
 Contributions are highly encouraged, as they highlight certain use cases of
 eBPF and the library, and help shape the future of the project.
 eBPF and the library, and help shape the future of the project.
 
 
+## Getting Help
+
+Please
+[join](https://ebpf.io/slack) the
+[#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack if you
+have questions regarding the library.
+
+## Packages
+
+This library includes the following packages: 
+
+* [asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic
+  assembler, allowing you to write eBPF assembly instructions directly
+  within your Go code. (You don't need to use this if you prefer to write your eBPF program in C.)
+* [cmd/bpf2go](https://pkg.go.dev/github.com/cilium/ebpf/cmd/bpf2go) allows
+  compiling and embedding eBPF programs written in C within Go code. As well as
+  compiling the C code, it auto-generates Go code for loading and manipulating
+  the eBPF program and map objects. 
+* [link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF
+  to various hooks
+* [perf](https://pkg.go.dev/github.com/cilium/ebpf/perf) allows reading from a
+  `PERF_EVENT_ARRAY`
+* [ringbuf](https://pkg.go.dev/github.com/cilium/ebpf/ringbuf) allows reading from a
+  `BPF_MAP_TYPE_RINGBUF` map
+
+
 ## Requirements
 ## Requirements
 
 
 * A version of Go that is [supported by
 * A version of Go that is [supported by
   upstream](https://golang.org/doc/devel/release.html#policy)
   upstream](https://golang.org/doc/devel/release.html#policy)
-* Linux 4.9, 4.19 or 5.4 (versions in-between should work, but are not tested)
-
-## Useful resources
-
-* [eBPF.io](https://ebpf.io) (recommended)
-* [Cilium eBPF documentation](https://docs.cilium.io/en/latest/bpf/#bpf-guide)
-  (recommended)
-* [Linux documentation on
-  BPF](https://www.kernel.org/doc/html/latest/networking/filter.html)
-* [eBPF features by Linux
-  version](https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md)
+* Linux >= 4.9. CI is run against LTS releases.
 
 
 ## Regenerating Testdata
 ## Regenerating Testdata
 
 
@@ -60,3 +64,7 @@ The toolchain image build files are kept in [testdata/docker/](testdata/docker/)
 ## License
 ## License
 
 
 MIT
 MIT
+
+### eBPF Gopher
+
+The eBPF honeygopher is based on the Go gopher designed by Renee French.

+ 6 - 0
vendor/github.com/cilium/ebpf/asm/func.go

@@ -184,6 +184,12 @@ const (
 	FnKtimeGetCoarseNs
 	FnKtimeGetCoarseNs
 	FnImaInodeHash
 	FnImaInodeHash
 	FnSockFromFile
 	FnSockFromFile
+	FnCheckMtu
+	FnForEachMapElem
+	FnSnprintf
+	FnSysBpf
+	FnBtfFindByNameKind
+	FnSysClose
 )
 )
 
 
 // Call emits a function call.
 // Call emits a function call.

Різницю між файлами не показано, бо вона завелика
+ 6 - 0
vendor/github.com/cilium/ebpf/asm/func_string.go


+ 5 - 0
vendor/github.com/cilium/ebpf/asm/instruction.go

@@ -181,6 +181,11 @@ func (ins *Instruction) IsFunctionCall() bool {
 	return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall
 	return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall
 }
 }
 
 
+// IsBuiltinCall returns true if the instruction is a built-in call, i.e. BPF helper call.
+func (ins *Instruction) IsBuiltinCall() bool {
+	return ins.OpCode.JumpOp() == Call && ins.Src == R0 && ins.Dst == R0
+}
+
 // IsConstantLoad returns true if the instruction loads a constant of the
 // IsConstantLoad returns true if the instruction loads a constant of the
 // given size.
 // given size.
 func (ins *Instruction) IsConstantLoad(size Size) bool {
 func (ins *Instruction) IsConstantLoad(size Size) bool {

+ 65 - 0
vendor/github.com/cilium/ebpf/attachtype_string.go

@@ -0,0 +1,65 @@
+// Code generated by "stringer -type AttachType -trimprefix Attach"; DO NOT EDIT.
+
+package ebpf
+
+import "strconv"
+
+func _() {
+	// An "invalid array index" compiler error signifies that the constant values have changed.
+	// Re-run the stringer command to generate them again.
+	var x [1]struct{}
+	_ = x[AttachNone-0]
+	_ = x[AttachCGroupInetIngress-0]
+	_ = x[AttachCGroupInetEgress-1]
+	_ = x[AttachCGroupInetSockCreate-2]
+	_ = x[AttachCGroupSockOps-3]
+	_ = x[AttachSkSKBStreamParser-4]
+	_ = x[AttachSkSKBStreamVerdict-5]
+	_ = x[AttachCGroupDevice-6]
+	_ = x[AttachSkMsgVerdict-7]
+	_ = x[AttachCGroupInet4Bind-8]
+	_ = x[AttachCGroupInet6Bind-9]
+	_ = x[AttachCGroupInet4Connect-10]
+	_ = x[AttachCGroupInet6Connect-11]
+	_ = x[AttachCGroupInet4PostBind-12]
+	_ = x[AttachCGroupInet6PostBind-13]
+	_ = x[AttachCGroupUDP4Sendmsg-14]
+	_ = x[AttachCGroupUDP6Sendmsg-15]
+	_ = x[AttachLircMode2-16]
+	_ = x[AttachFlowDissector-17]
+	_ = x[AttachCGroupSysctl-18]
+	_ = x[AttachCGroupUDP4Recvmsg-19]
+	_ = x[AttachCGroupUDP6Recvmsg-20]
+	_ = x[AttachCGroupGetsockopt-21]
+	_ = x[AttachCGroupSetsockopt-22]
+	_ = x[AttachTraceRawTp-23]
+	_ = x[AttachTraceFEntry-24]
+	_ = x[AttachTraceFExit-25]
+	_ = x[AttachModifyReturn-26]
+	_ = x[AttachLSMMac-27]
+	_ = x[AttachTraceIter-28]
+	_ = x[AttachCgroupInet4GetPeername-29]
+	_ = x[AttachCgroupInet6GetPeername-30]
+	_ = x[AttachCgroupInet4GetSockname-31]
+	_ = x[AttachCgroupInet6GetSockname-32]
+	_ = x[AttachXDPDevMap-33]
+	_ = x[AttachCgroupInetSockRelease-34]
+	_ = x[AttachXDPCPUMap-35]
+	_ = x[AttachSkLookup-36]
+	_ = x[AttachXDP-37]
+	_ = x[AttachSkSKBVerdict-38]
+	_ = x[AttachSkReuseportSelect-39]
+	_ = x[AttachSkReuseportSelectOrMigrate-40]
+	_ = x[AttachPerfEvent-41]
+}
+
+const _AttachType_name = "NoneCGroupInetEgressCGroupInetSockCreateCGroupSockOpsSkSKBStreamParserSkSKBStreamVerdictCGroupDeviceSkMsgVerdictCGroupInet4BindCGroupInet6BindCGroupInet4ConnectCGroupInet6ConnectCGroupInet4PostBindCGroupInet6PostBindCGroupUDP4SendmsgCGroupUDP6SendmsgLircMode2FlowDissectorCGroupSysctlCGroupUDP4RecvmsgCGroupUDP6RecvmsgCGroupGetsockoptCGroupSetsockoptTraceRawTpTraceFEntryTraceFExitModifyReturnLSMMacTraceIterCgroupInet4GetPeernameCgroupInet6GetPeernameCgroupInet4GetSocknameCgroupInet6GetSocknameXDPDevMapCgroupInetSockReleaseXDPCPUMapSkLookupXDPSkSKBVerdictSkReuseportSelectSkReuseportSelectOrMigratePerfEvent"
+
+var _AttachType_index = [...]uint16{0, 4, 20, 40, 53, 70, 88, 100, 112, 127, 142, 160, 178, 197, 216, 233, 250, 259, 272, 284, 301, 318, 334, 350, 360, 371, 381, 393, 399, 408, 430, 452, 474, 496, 505, 526, 535, 543, 546, 558, 575, 601, 610}
+
+func (i AttachType) String() string {
+	if i >= AttachType(len(_AttachType_index)-1) {
+		return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")"
+	}
+	return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]]
+}

+ 280 - 228
vendor/github.com/cilium/ebpf/collection.go

@@ -1,6 +1,7 @@
 package ebpf
 package ebpf
 
 
 import (
 import (
+	"encoding/binary"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
@@ -25,6 +26,10 @@ type CollectionOptions struct {
 type CollectionSpec struct {
 type CollectionSpec struct {
 	Maps     map[string]*MapSpec
 	Maps     map[string]*MapSpec
 	Programs map[string]*ProgramSpec
 	Programs map[string]*ProgramSpec
+
+	// ByteOrder specifies whether the ELF was compiled for
+	// big-endian or little-endian architectures.
+	ByteOrder binary.ByteOrder
 }
 }
 
 
 // Copy returns a recursive copy of the spec.
 // Copy returns a recursive copy of the spec.
@@ -34,8 +39,9 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
 	}
 	}
 
 
 	cpy := CollectionSpec{
 	cpy := CollectionSpec{
-		Maps:     make(map[string]*MapSpec, len(cs.Maps)),
-		Programs: make(map[string]*ProgramSpec, len(cs.Programs)),
+		Maps:      make(map[string]*MapSpec, len(cs.Maps)),
+		Programs:  make(map[string]*ProgramSpec, len(cs.Programs)),
+		ByteOrder: cs.ByteOrder,
 	}
 	}
 
 
 	for name, spec := range cs.Maps {
 	for name, spec := range cs.Maps {
@@ -123,7 +129,7 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
 	buf := make([]byte, len(value))
 	buf := make([]byte, len(value))
 	copy(buf, value)
 	copy(buf, value)
 
 
-	err := patchValue(buf, btf.MapValue(rodata.BTF), consts)
+	err := patchValue(buf, rodata.BTF.Value, consts)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -134,15 +140,15 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
 
 
 // Assign the contents of a CollectionSpec to a struct.
 // Assign the contents of a CollectionSpec to a struct.
 //
 //
-// This function is a short-cut to manually checking the presence
-// of maps and programs in a collection spec. Consider using bpf2go if this
-// sounds useful.
+// This function is a shortcut to manually checking the presence
+// of maps and programs in a CollectionSpec. Consider using bpf2go
+// if this sounds useful.
 //
 //
-// The argument to must be a pointer to a struct. A field of the
+// 'to' must be a pointer to a struct. A field of the
 // struct is updated with values from Programs or Maps if it
 // struct is updated with values from Programs or Maps if it
 // has an `ebpf` tag and its type is *ProgramSpec or *MapSpec.
 // has an `ebpf` tag and its type is *ProgramSpec or *MapSpec.
-// The tag gives the name of the program or map as found in
-// the CollectionSpec.
+// The tag's value specifies the name of the program or map as
+// found in the CollectionSpec.
 //
 //
 //    struct {
 //    struct {
 //        Foo     *ebpf.ProgramSpec `ebpf:"xdp_foo"`
 //        Foo     *ebpf.ProgramSpec `ebpf:"xdp_foo"`
@@ -150,42 +156,47 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
 //        Ignored int
 //        Ignored int
 //    }
 //    }
 //
 //
-// Returns an error if any of the fields can't be found, or
-// if the same map or program is assigned multiple times.
+// Returns an error if any of the eBPF objects can't be found, or
+// if the same MapSpec or ProgramSpec is assigned multiple times.
 func (cs *CollectionSpec) Assign(to interface{}) error {
 func (cs *CollectionSpec) Assign(to interface{}) error {
-	valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
+	// Assign() only supports assigning ProgramSpecs and MapSpecs,
+	// so doesn't load any resources into the kernel.
+	getValue := func(typ reflect.Type, name string) (interface{}, error) {
 		switch typ {
 		switch typ {
+
 		case reflect.TypeOf((*ProgramSpec)(nil)):
 		case reflect.TypeOf((*ProgramSpec)(nil)):
-			p := cs.Programs[name]
-			if p == nil {
-				return reflect.Value{}, fmt.Errorf("missing program %q", name)
+			if p := cs.Programs[name]; p != nil {
+				return p, nil
 			}
 			}
-			return reflect.ValueOf(p), nil
+			return nil, fmt.Errorf("missing program %q", name)
+
 		case reflect.TypeOf((*MapSpec)(nil)):
 		case reflect.TypeOf((*MapSpec)(nil)):
-			m := cs.Maps[name]
-			if m == nil {
-				return reflect.Value{}, fmt.Errorf("missing map %q", name)
+			if m := cs.Maps[name]; m != nil {
+				return m, nil
 			}
 			}
-			return reflect.ValueOf(m), nil
+			return nil, fmt.Errorf("missing map %q", name)
+
 		default:
 		default:
-			return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
+			return nil, fmt.Errorf("unsupported type %s", typ)
 		}
 		}
 	}
 	}
 
 
-	return assignValues(to, valueOf)
+	return assignValues(to, getValue)
 }
 }
 
 
-// LoadAndAssign maps and programs into the kernel and assign them to a struct.
+// LoadAndAssign loads Maps and Programs into the kernel and assigns them
+// to a struct.
 //
 //
-// This function is a short-cut to manually checking the presence
-// of maps and programs in a collection spec. Consider using bpf2go if this
-// sounds useful.
+// This function is a shortcut to manually checking the presence
+// of maps and programs in a CollectionSpec. Consider using bpf2go
+// if this sounds useful.
 //
 //
-// The argument to must be a pointer to a struct. A field of the
-// struct is updated with values from Programs or Maps if it
-// has an `ebpf` tag and its type is *Program or *Map.
-// The tag gives the name of the program or map as found in
-// the CollectionSpec.
+// 'to' must be a pointer to a struct. A field of the struct is updated with
+// a Program or Map if it has an `ebpf` tag and its type is *Program or *Map.
+// The tag's value specifies the name of the program or map as found in the
+// CollectionSpec. Before updating the struct, the requested objects and their
+// dependent resources are loaded into the kernel and populated with values if
+// specified.
 //
 //
 //    struct {
 //    struct {
 //        Foo     *ebpf.Program `ebpf:"xdp_foo"`
 //        Foo     *ebpf.Program `ebpf:"xdp_foo"`
@@ -196,39 +207,53 @@ func (cs *CollectionSpec) Assign(to interface{}) error {
 // opts may be nil.
 // opts may be nil.
 //
 //
 // Returns an error if any of the fields can't be found, or
 // Returns an error if any of the fields can't be found, or
-// if the same map or program is assigned multiple times.
+// if the same Map or Program is assigned multiple times.
 func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) error {
 func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) error {
-	if opts == nil {
-		opts = &CollectionOptions{}
-	}
-
-	loadMap, loadProgram, done, cleanup := lazyLoadCollection(cs, opts)
-	defer cleanup()
+	loader := newCollectionLoader(cs, opts)
+	defer loader.cleanup()
 
 
-	valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
+	// Support assigning Programs and Maps, lazy-loading the required objects.
+	assignedMaps := make(map[string]bool)
+	getValue := func(typ reflect.Type, name string) (interface{}, error) {
 		switch typ {
 		switch typ {
+
 		case reflect.TypeOf((*Program)(nil)):
 		case reflect.TypeOf((*Program)(nil)):
-			p, err := loadProgram(name)
-			if err != nil {
-				return reflect.Value{}, err
-			}
-			return reflect.ValueOf(p), nil
+			return loader.loadProgram(name)
+
 		case reflect.TypeOf((*Map)(nil)):
 		case reflect.TypeOf((*Map)(nil)):
-			m, err := loadMap(name)
-			if err != nil {
-				return reflect.Value{}, err
-			}
-			return reflect.ValueOf(m), nil
+			assignedMaps[name] = true
+			return loader.loadMap(name)
+
 		default:
 		default:
-			return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
+			return nil, fmt.Errorf("unsupported type %s", typ)
 		}
 		}
 	}
 	}
 
 
-	if err := assignValues(to, valueOf); err != nil {
+	// Load the Maps and Programs requested by the annotated struct.
+	if err := assignValues(to, getValue); err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	done()
+	// Populate the requested maps. Has a chance of lazy-loading other dependent maps.
+	if err := loader.populateMaps(); err != nil {
+		return err
+	}
+
+	// Evaluate the loader's objects after all (lazy)loading has taken place.
+	for n, m := range loader.maps {
+		switch m.typ {
+		case ProgramArray:
+			// Require all lazy-loaded ProgramArrays to be assigned to the given object.
+			// Without any references, they will be closed on the first GC and all tail
+			// calls into them will miss.
+			if !assignedMaps[n] {
+				return fmt.Errorf("ProgramArray %s must be assigned to prevent missed tail calls", n)
+			}
+		}
+	}
+
+	loader.finalize()
+
 	return nil
 	return nil
 }
 }
 
 
@@ -246,24 +271,32 @@ func NewCollection(spec *CollectionSpec) (*Collection, error) {
 
 
 // NewCollectionWithOptions creates a Collection from a specification.
 // NewCollectionWithOptions creates a Collection from a specification.
 func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) {
 func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) {
-	loadMap, loadProgram, done, cleanup := lazyLoadCollection(spec, &opts)
-	defer cleanup()
+	loader := newCollectionLoader(spec, &opts)
+	defer loader.cleanup()
 
 
+	// Create maps first, as their fds need to be linked into programs.
 	for mapName := range spec.Maps {
 	for mapName := range spec.Maps {
-		_, err := loadMap(mapName)
-		if err != nil {
+		if _, err := loader.loadMap(mapName); err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
 	}
 	}
 
 
 	for progName := range spec.Programs {
 	for progName := range spec.Programs {
-		_, err := loadProgram(progName)
-		if err != nil {
+		if _, err := loader.loadProgram(progName); err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
 	}
 	}
 
 
-	maps, progs := done()
+	// Maps can contain Program and Map stubs, so populate them after
+	// all Maps and Programs have been successfully loaded.
+	if err := loader.populateMaps(); err != nil {
+		return nil, err
+	}
+
+	maps, progs := loader.maps, loader.programs
+
+	loader.finalize()
+
 	return &Collection{
 	return &Collection{
 		progs,
 		progs,
 		maps,
 		maps,
@@ -314,113 +347,154 @@ func (hc handleCache) close() {
 	for _, handle := range hc.btfHandles {
 	for _, handle := range hc.btfHandles {
 		handle.Close()
 		handle.Close()
 	}
 	}
-	hc.btfHandles = nil
-	hc.btfSpecs = nil
 }
 }
 
 
-func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
-	loadMap func(string) (*Map, error),
-	loadProgram func(string) (*Program, error),
-	done func() (map[string]*Map, map[string]*Program),
-	cleanup func(),
-) {
-	var (
-		maps             = make(map[string]*Map)
-		progs            = make(map[string]*Program)
-		handles          = newHandleCache()
-		skipMapsAndProgs = false
-	)
-
-	cleanup = func() {
-		handles.close()
-
-		if skipMapsAndProgs {
-			return
-		}
+type collectionLoader struct {
+	coll     *CollectionSpec
+	opts     *CollectionOptions
+	maps     map[string]*Map
+	programs map[string]*Program
+	handles  *handleCache
+}
 
 
-		for _, m := range maps {
-			m.Close()
-		}
+func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) *collectionLoader {
+	if opts == nil {
+		opts = &CollectionOptions{}
+	}
 
 
-		for _, p := range progs {
-			p.Close()
-		}
+	return &collectionLoader{
+		coll,
+		opts,
+		make(map[string]*Map),
+		make(map[string]*Program),
+		newHandleCache(),
+	}
+}
+
+// finalize should be called when all the collectionLoader's resources
+// have been successfully loaded into the kernel and populated with values.
+func (cl *collectionLoader) finalize() {
+	cl.maps, cl.programs = nil, nil
+}
+
+// cleanup cleans up all resources left over in the collectionLoader.
+// Call finalize() when Map and Program creation/population is successful
+// to prevent them from getting closed.
+func (cl *collectionLoader) cleanup() {
+	cl.handles.close()
+	for _, m := range cl.maps {
+		m.Close()
+	}
+	for _, p := range cl.programs {
+		p.Close()
+	}
+}
+
+func (cl *collectionLoader) loadMap(mapName string) (*Map, error) {
+	if m := cl.maps[mapName]; m != nil {
+		return m, nil
+	}
+
+	mapSpec := cl.coll.Maps[mapName]
+	if mapSpec == nil {
+		return nil, fmt.Errorf("missing map %s", mapName)
 	}
 	}
 
 
-	done = func() (map[string]*Map, map[string]*Program) {
-		skipMapsAndProgs = true
-		return maps, progs
+	m, err := newMapWithOptions(mapSpec, cl.opts.Maps, cl.handles)
+	if err != nil {
+		return nil, fmt.Errorf("map %s: %w", mapName, err)
 	}
 	}
 
 
-	loadMap = func(mapName string) (*Map, error) {
-		if m := maps[mapName]; m != nil {
-			return m, nil
+	cl.maps[mapName] = m
+	return m, nil
+}
+
+func (cl *collectionLoader) loadProgram(progName string) (*Program, error) {
+	if prog := cl.programs[progName]; prog != nil {
+		return prog, nil
+	}
+
+	progSpec := cl.coll.Programs[progName]
+	if progSpec == nil {
+		return nil, fmt.Errorf("unknown program %s", progName)
+	}
+
+	progSpec = progSpec.Copy()
+
+	// Rewrite any reference to a valid map.
+	for i := range progSpec.Instructions {
+		ins := &progSpec.Instructions[i]
+
+		if !ins.IsLoadFromMap() || ins.Reference == "" {
+			continue
 		}
 		}
 
 
-		mapSpec := coll.Maps[mapName]
-		if mapSpec == nil {
-			return nil, fmt.Errorf("missing map %s", mapName)
+		if uint32(ins.Constant) != math.MaxUint32 {
+			// Don't overwrite maps already rewritten, users can
+			// rewrite programs in the spec themselves
+			continue
 		}
 		}
 
 
-		m, err := newMapWithOptions(mapSpec, opts.Maps, handles)
+		m, err := cl.loadMap(ins.Reference)
 		if err != nil {
 		if err != nil {
-			return nil, fmt.Errorf("map %s: %w", mapName, err)
+			return nil, fmt.Errorf("program %s: %w", progName, err)
 		}
 		}
 
 
-		maps[mapName] = m
-		return m, nil
-	}
-
-	loadProgram = func(progName string) (*Program, error) {
-		if prog := progs[progName]; prog != nil {
-			return prog, nil
+		fd := m.FD()
+		if fd < 0 {
+			return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
 		}
 		}
-
-		progSpec := coll.Programs[progName]
-		if progSpec == nil {
-			return nil, fmt.Errorf("unknown program %s", progName)
+		if err := ins.RewriteMapPtr(m.FD()); err != nil {
+			return nil, fmt.Errorf("program %s: map %s: %w", progName, ins.Reference, err)
 		}
 		}
+	}
 
 
-		progSpec = progSpec.Copy()
+	prog, err := newProgramWithOptions(progSpec, cl.opts.Programs, cl.handles)
+	if err != nil {
+		return nil, fmt.Errorf("program %s: %w", progName, err)
+	}
 
 
-		// Rewrite any reference to a valid map.
-		for i := range progSpec.Instructions {
-			ins := &progSpec.Instructions[i]
+	cl.programs[progName] = prog
+	return prog, nil
+}
 
 
-			if !ins.IsLoadFromMap() || ins.Reference == "" {
-				continue
-			}
+func (cl *collectionLoader) populateMaps() error {
+	for mapName, m := range cl.maps {
+		mapSpec, ok := cl.coll.Maps[mapName]
+		if !ok {
+			return fmt.Errorf("missing map spec %s", mapName)
+		}
 
 
-			if uint32(ins.Constant) != math.MaxUint32 {
-				// Don't overwrite maps already rewritten, users can
-				// rewrite programs in the spec themselves
-				continue
-			}
+		mapSpec = mapSpec.Copy()
 
 
-			m, err := loadMap(ins.Reference)
-			if err != nil {
-				return nil, fmt.Errorf("program %s: %w", progName, err)
-			}
+		// Replace any object stubs with loaded objects.
+		for i, kv := range mapSpec.Contents {
+			switch v := kv.Value.(type) {
+			case programStub:
+				// loadProgram is idempotent and could return an existing Program.
+				prog, err := cl.loadProgram(string(v))
+				if err != nil {
+					return fmt.Errorf("loading program %s, for map %s: %w", v, mapName, err)
+				}
+				mapSpec.Contents[i] = MapKV{kv.Key, prog}
 
 
-			fd := m.FD()
-			if fd < 0 {
-				return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
-			}
-			if err := ins.RewriteMapPtr(m.FD()); err != nil {
-				return nil, fmt.Errorf("progam %s: map %s: %w", progName, ins.Reference, err)
+			case mapStub:
+				// loadMap is idempotent and could return an existing Map.
+				innerMap, err := cl.loadMap(string(v))
+				if err != nil {
+					return fmt.Errorf("loading inner map %s, for map %s: %w", v, mapName, err)
+				}
+				mapSpec.Contents[i] = MapKV{kv.Key, innerMap}
 			}
 			}
 		}
 		}
 
 
-		prog, err := newProgramWithOptions(progSpec, opts.Programs, handles)
-		if err != nil {
-			return nil, fmt.Errorf("program %s: %w", progName, err)
+		// Populate and freeze the map if specified.
+		if err := m.finalize(mapSpec); err != nil {
+			return fmt.Errorf("populating map %s: %w", mapName, err)
 		}
 		}
-
-		progs[progName] = prog
-		return prog, nil
 	}
 	}
 
 
-	return
+	return nil
 }
 }
 
 
 // LoadCollection parses an object file and converts it to a collection.
 // LoadCollection parses an object file and converts it to a collection.
@@ -466,108 +540,81 @@ func (coll *Collection) DetachProgram(name string) *Program {
 	return p
 	return p
 }
 }
 
 
-// Assign the contents of a collection to a struct.
-//
-// Deprecated: use CollectionSpec.Assign instead. It provides the same
-// functionality but creates only the maps and programs requested.
-func (coll *Collection) Assign(to interface{}) error {
-	assignedMaps := make(map[string]struct{})
-	assignedPrograms := make(map[string]struct{})
-	valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
-		switch typ {
-		case reflect.TypeOf((*Program)(nil)):
-			p := coll.Programs[name]
-			if p == nil {
-				return reflect.Value{}, fmt.Errorf("missing program %q", name)
-			}
-			assignedPrograms[name] = struct{}{}
-			return reflect.ValueOf(p), nil
-		case reflect.TypeOf((*Map)(nil)):
-			m := coll.Maps[name]
-			if m == nil {
-				return reflect.Value{}, fmt.Errorf("missing map %q", name)
-			}
-			assignedMaps[name] = struct{}{}
-			return reflect.ValueOf(m), nil
-		default:
-			return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
-		}
-	}
-
-	if err := assignValues(to, valueOf); err != nil {
-		return err
-	}
+// structField represents a struct field containing the ebpf struct tag.
+type structField struct {
+	reflect.StructField
+	value reflect.Value
+}
 
 
-	for name := range assignedPrograms {
-		coll.DetachProgram(name)
+// ebpfFields extracts field names tagged with 'ebpf' from a struct type.
+// Keep track of visited types to avoid infinite recursion.
+func ebpfFields(structVal reflect.Value, visited map[reflect.Type]bool) ([]structField, error) {
+	if visited == nil {
+		visited = make(map[reflect.Type]bool)
 	}
 	}
 
 
-	for name := range assignedMaps {
-		coll.DetachMap(name)
+	structType := structVal.Type()
+	if structType.Kind() != reflect.Struct {
+		return nil, fmt.Errorf("%s is not a struct", structType)
 	}
 	}
 
 
-	return nil
-}
-
-func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Value, error)) error {
-	type structField struct {
-		reflect.StructField
-		value reflect.Value
+	if visited[structType] {
+		return nil, fmt.Errorf("recursion on type %s", structType)
 	}
 	}
 
 
-	var (
-		fields        []structField
-		visitedTypes  = make(map[reflect.Type]bool)
-		flattenStruct func(reflect.Value) error
-	)
+	fields := make([]structField, 0, structType.NumField())
+	for i := 0; i < structType.NumField(); i++ {
+		field := structField{structType.Field(i), structVal.Field(i)}
 
 
-	flattenStruct = func(structVal reflect.Value) error {
-		structType := structVal.Type()
-		if structType.Kind() != reflect.Struct {
-			return fmt.Errorf("%s is not a struct", structType)
-		}
-
-		if visitedTypes[structType] {
-			return fmt.Errorf("recursion on type %s", structType)
+		// If the field is tagged, gather it and move on.
+		name := field.Tag.Get("ebpf")
+		if name != "" {
+			fields = append(fields, field)
+			continue
 		}
 		}
 
 
-		for i := 0; i < structType.NumField(); i++ {
-			field := structField{structType.Field(i), structVal.Field(i)}
-
-			name := field.Tag.Get("ebpf")
-			if name != "" {
-				fields = append(fields, field)
+		// If the field does not have an ebpf tag, but is a struct or a pointer
+		// to a struct, attempt to gather its fields as well.
+		var v reflect.Value
+		switch field.Type.Kind() {
+		case reflect.Ptr:
+			if field.Type.Elem().Kind() != reflect.Struct {
 				continue
 				continue
 			}
 			}
 
 
-			var err error
-			switch field.Type.Kind() {
-			case reflect.Ptr:
-				if field.Type.Elem().Kind() != reflect.Struct {
-					continue
-				}
-
-				if field.value.IsNil() {
-					return fmt.Errorf("nil pointer to %s", structType)
-				}
+			if field.value.IsNil() {
+				return nil, fmt.Errorf("nil pointer to %s", structType)
+			}
 
 
-				err = flattenStruct(field.value.Elem())
+			// Obtain the destination type of the pointer.
+			v = field.value.Elem()
 
 
-			case reflect.Struct:
-				err = flattenStruct(field.value)
+		case reflect.Struct:
+			// Reference the value's type directly.
+			v = field.value
 
 
-			default:
-				continue
-			}
+		default:
+			continue
+		}
 
 
-			if err != nil {
-				return fmt.Errorf("field %s: %w", field.Name, err)
-			}
+		inner, err := ebpfFields(v, visited)
+		if err != nil {
+			return nil, fmt.Errorf("field %s: %w", field.Name, err)
 		}
 		}
 
 
-		return nil
+		fields = append(fields, inner...)
 	}
 	}
 
 
+	return fields, nil
+}
+
+// assignValues attempts to populate all fields of 'to' tagged with 'ebpf'.
+//
+// getValue is called for every tagged field of 'to' and must return the value
+// to be assigned to the field with the given typ and name.
+func assignValues(to interface{},
+	getValue func(typ reflect.Type, name string) (interface{}, error)) error {
+
 	toValue := reflect.ValueOf(to)
 	toValue := reflect.ValueOf(to)
 	if toValue.Type().Kind() != reflect.Ptr {
 	if toValue.Type().Kind() != reflect.Ptr {
 		return fmt.Errorf("%T is not a pointer to struct", to)
 		return fmt.Errorf("%T is not a pointer to struct", to)
@@ -577,7 +624,8 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
 		return fmt.Errorf("nil pointer to %T", to)
 		return fmt.Errorf("nil pointer to %T", to)
 	}
 	}
 
 
-	if err := flattenStruct(toValue.Elem()); err != nil {
+	fields, err := ebpfFields(toValue.Elem(), nil)
+	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -587,19 +635,23 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
 		name string
 		name string
 	}
 	}
 
 
-	assignedTo := make(map[elem]string)
+	assigned := make(map[elem]string)
 	for _, field := range fields {
 	for _, field := range fields {
-		name := field.Tag.Get("ebpf")
-		if strings.Contains(name, ",") {
+		// Get string value the field is tagged with.
+		tag := field.Tag.Get("ebpf")
+		if strings.Contains(tag, ",") {
 			return fmt.Errorf("field %s: ebpf tag contains a comma", field.Name)
 			return fmt.Errorf("field %s: ebpf tag contains a comma", field.Name)
 		}
 		}
 
 
-		e := elem{field.Type, name}
-		if assignedField := assignedTo[e]; assignedField != "" {
-			return fmt.Errorf("field %s: %q was already assigned to %s", field.Name, name, assignedField)
+		// Check if the eBPF object with the requested
+		// type and tag was already assigned elsewhere.
+		e := elem{field.Type, tag}
+		if af := assigned[e]; af != "" {
+			return fmt.Errorf("field %s: object %q was already assigned to %s", field.Name, tag, af)
 		}
 		}
 
 
-		value, err := valueOf(field.Type, name)
+		// Get the eBPF object referred to by the tag.
+		value, err := getValue(field.Type, tag)
 		if err != nil {
 		if err != nil {
 			return fmt.Errorf("field %s: %w", field.Name, err)
 			return fmt.Errorf("field %s: %w", field.Name, err)
 		}
 		}
@@ -607,9 +659,9 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
 		if !field.value.CanSet() {
 		if !field.value.CanSet() {
 			return fmt.Errorf("field %s: can't set value", field.Name)
 			return fmt.Errorf("field %s: can't set value", field.Name)
 		}
 		}
+		field.value.Set(reflect.ValueOf(value))
 
 
-		field.value.Set(value)
-		assignedTo[e] = field.Name
+		assigned[e] = field.Name
 	}
 	}
 
 
 	return nil
 	return nil

+ 152 - 28
vendor/github.com/cilium/ebpf/elf_reader.go

@@ -19,7 +19,7 @@ import (
 )
 )
 
 
 // elfCode is a convenience to reduce the amount of arguments that have to
 // elfCode is a convenience to reduce the amount of arguments that have to
-// be passed around explicitly. You should treat it's contents as immutable.
+// be passed around explicitly. You should treat its contents as immutable.
 type elfCode struct {
 type elfCode struct {
 	*internal.SafeELFFile
 	*internal.SafeELFFile
 	sections map[elf.SectionIndex]*elfSection
 	sections map[elf.SectionIndex]*elfSection
@@ -188,7 +188,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
 		return nil, fmt.Errorf("load programs: %w", err)
 		return nil, fmt.Errorf("load programs: %w", err)
 	}
 	}
 
 
-	return &CollectionSpec{maps, progs}, nil
+	return &CollectionSpec{maps, progs, ec.ByteOrder}, nil
 }
 }
 
 
 func loadLicense(sec *elf.Section) (string, error) {
 func loadLicense(sec *elf.Section) (string, error) {
@@ -520,8 +520,12 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error {
 				return fmt.Errorf("map %s: missing flags", mapName)
 				return fmt.Errorf("map %s: missing flags", mapName)
 			}
 			}
 
 
-			if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
-				return fmt.Errorf("map %s: unknown and non-zero fields in definition", mapName)
+			extra, err := io.ReadAll(lr)
+			if err != nil {
+				return fmt.Errorf("map %s: reading map tail: %w", mapName, err)
+			}
+			if len(extra) > 0 {
+				spec.Extra = *bytes.NewReader(extra)
 			}
 			}
 
 
 			if err := spec.clampPerfEventArraySize(); err != nil {
 			if err := spec.clampPerfEventArraySize(); err != nil {
@@ -535,6 +539,9 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error {
 	return nil
 	return nil
 }
 }
 
 
+// loadBTFMaps iterates over all ELF sections marked as BTF map sections
+// (like .maps) and parses them into MapSpecs. Dump the .maps section and
+// any relocations with `readelf -x .maps -r <elf_file>`.
 func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
 func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
 	for _, sec := range ec.sections {
 	for _, sec := range ec.sections {
 		if sec.kind != btfMapSection {
 		if sec.kind != btfMapSection {
@@ -545,33 +552,46 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
 			return fmt.Errorf("missing BTF")
 			return fmt.Errorf("missing BTF")
 		}
 		}
 
 
-		_, err := io.Copy(internal.DiscardZeroes{}, bufio.NewReader(sec.Open()))
-		if err != nil {
-			return fmt.Errorf("section %v: initializing BTF map definitions: %w", sec.Name, internal.ErrNotSupported)
-		}
-
-		var ds btf.Datasec
+		// Each section must appear as a DataSec in the ELF's BTF blob.
+		var ds *btf.Datasec
 		if err := ec.btf.FindType(sec.Name, &ds); err != nil {
 		if err := ec.btf.FindType(sec.Name, &ds); err != nil {
 			return fmt.Errorf("cannot find section '%s' in BTF: %w", sec.Name, err)
 			return fmt.Errorf("cannot find section '%s' in BTF: %w", sec.Name, err)
 		}
 		}
 
 
+		// Open a Reader to the ELF's raw section bytes so we can assert that all
+		// of them are zero on a per-map (per-Var) basis. For now, the section's
+		// sole purpose is to receive relocations, so all must be zero.
+		rs := sec.Open()
+
 		for _, vs := range ds.Vars {
 		for _, vs := range ds.Vars {
+			// BPF maps are declared as and assigned to global variables,
+			// so iterate over each Var in the DataSec and validate their types.
 			v, ok := vs.Type.(*btf.Var)
 			v, ok := vs.Type.(*btf.Var)
 			if !ok {
 			if !ok {
 				return fmt.Errorf("section %v: unexpected type %s", sec.Name, vs.Type)
 				return fmt.Errorf("section %v: unexpected type %s", sec.Name, vs.Type)
 			}
 			}
 			name := string(v.Name)
 			name := string(v.Name)
 
 
+			// The BTF metadata for each Var contains the full length of the map
+			// declaration, so read the corresponding amount of bytes from the ELF.
+			// This way, we can pinpoint which map declaration contains unexpected
+			// (and therefore unsupported) data.
+			_, err := io.Copy(internal.DiscardZeroes{}, io.LimitReader(rs, int64(vs.Size)))
+			if err != nil {
+				return fmt.Errorf("section %v: map %s: initializing BTF map definitions: %w", sec.Name, name, internal.ErrNotSupported)
+			}
+
 			if maps[name] != nil {
 			if maps[name] != nil {
 				return fmt.Errorf("section %v: map %s already exists", sec.Name, name)
 				return fmt.Errorf("section %v: map %s already exists", sec.Name, name)
 			}
 			}
 
 
+			// Each Var representing a BTF map definition contains a Struct.
 			mapStruct, ok := v.Type.(*btf.Struct)
 			mapStruct, ok := v.Type.(*btf.Struct)
 			if !ok {
 			if !ok {
 				return fmt.Errorf("expected struct, got %s", v.Type)
 				return fmt.Errorf("expected struct, got %s", v.Type)
 			}
 			}
 
 
-			mapSpec, err := mapSpecFromBTF(name, mapStruct, false, ec.btf)
+			mapSpec, err := mapSpecFromBTF(sec, &vs, mapStruct, ec.btf, name, false)
 			if err != nil {
 			if err != nil {
 				return fmt.Errorf("map %v: %w", name, err)
 				return fmt.Errorf("map %v: %w", name, err)
 			}
 			}
@@ -582,32 +602,52 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
 
 
 			maps[name] = mapSpec
 			maps[name] = mapSpec
 		}
 		}
+
+		// Drain the ELF section reader to make sure all bytes are accounted for
+		// with BTF metadata.
+		i, err := io.Copy(io.Discard, rs)
+		if err != nil {
+			return fmt.Errorf("section %v: unexpected error reading remainder of ELF section: %w", sec.Name, err)
+		}
+		if i > 0 {
+			return fmt.Errorf("section %v: %d unexpected remaining bytes in ELF section, invalid BTF?", sec.Name, i)
+		}
 	}
 	}
 
 
 	return nil
 	return nil
 }
 }
 
 
+// A programStub is a placeholder for a Program to be inserted at a certain map key.
+// It needs to be resolved into a Program later on in the loader process.
+type programStub string
+
+// A mapStub is a placeholder for a Map to be inserted at a certain map key.
+// It needs to be resolved into a Map later on in the loader process.
+type mapStub string
+
 // mapSpecFromBTF produces a MapSpec based on a btf.Struct def representing
 // mapSpecFromBTF produces a MapSpec based on a btf.Struct def representing
 // a BTF map definition. The name and spec arguments will be copied to the
 // a BTF map definition. The name and spec arguments will be copied to the
 // resulting MapSpec, and inner must be true on any resursive invocations.
 // resulting MapSpec, and inner must be true on any resursive invocations.
-func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*MapSpec, error) {
-
+func mapSpecFromBTF(es *elfSection, vs *btf.VarSecinfo, def *btf.Struct, spec *btf.Spec, name string, inner bool) (*MapSpec, error) {
 	var (
 	var (
-		key, value                 btf.Type
-		keySize, valueSize         uint32
-		mapType, flags, maxEntries uint32
-		pinType                    PinType
-		innerMapSpec               *MapSpec
-		err                        error
+		key, value         btf.Type
+		keySize, valueSize uint32
+		mapType            MapType
+		flags, maxEntries  uint32
+		pinType            PinType
+		innerMapSpec       *MapSpec
+		contents           []MapKV
+		err                error
 	)
 	)
 
 
 	for i, member := range def.Members {
 	for i, member := range def.Members {
 		switch member.Name {
 		switch member.Name {
 		case "type":
 		case "type":
-			mapType, err = uintFromBTF(member.Type)
+			mt, err := uintFromBTF(member.Type)
 			if err != nil {
 			if err != nil {
 				return nil, fmt.Errorf("can't get type: %w", err)
 				return nil, fmt.Errorf("can't get type: %w", err)
 			}
 			}
+			mapType = MapType(mt)
 
 
 		case "map_flags":
 		case "map_flags":
 			flags, err = uintFromBTF(member.Type)
 			flags, err = uintFromBTF(member.Type)
@@ -717,7 +757,7 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
 			case *btf.Struct:
 			case *btf.Struct:
 				// The values member pointing to an array of structs means we're expecting
 				// The values member pointing to an array of structs means we're expecting
 				// a map-in-map declaration.
 				// a map-in-map declaration.
-				if MapType(mapType) != ArrayOfMaps && MapType(mapType) != HashOfMaps {
+				if mapType != ArrayOfMaps && mapType != HashOfMaps {
 					return nil, errors.New("outer map needs to be an array or a hash of maps")
 					return nil, errors.New("outer map needs to be an array or a hash of maps")
 				}
 				}
 				if inner {
 				if inner {
@@ -731,21 +771,38 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
 				// on kernels 5.2 and up)
 				// on kernels 5.2 and up)
 				// Pass the BTF spec from the parent object, since both parent and
 				// Pass the BTF spec from the parent object, since both parent and
 				// child must be created from the same BTF blob (on kernels that support BTF).
 				// child must be created from the same BTF blob (on kernels that support BTF).
-				innerMapSpec, err = mapSpecFromBTF(name+"_inner", t, true, spec)
+				innerMapSpec, err = mapSpecFromBTF(es, vs, t, spec, name+"_inner", true)
 				if err != nil {
 				if err != nil {
 					return nil, fmt.Errorf("can't parse BTF map definition of inner map: %w", err)
 					return nil, fmt.Errorf("can't parse BTF map definition of inner map: %w", err)
 				}
 				}
 
 
+			case *btf.FuncProto:
+				// The values member contains an array of function pointers, meaning an
+				// autopopulated PROG_ARRAY.
+				if mapType != ProgramArray {
+					return nil, errors.New("map needs to be a program array")
+				}
+
 			default:
 			default:
 				return nil, fmt.Errorf("unsupported value type %q in 'values' field", t)
 				return nil, fmt.Errorf("unsupported value type %q in 'values' field", t)
 			}
 			}
 
 
+			contents, err = resolveBTFValuesContents(es, vs, member)
+			if err != nil {
+				return nil, fmt.Errorf("resolving values contents: %w", err)
+			}
+
 		default:
 		default:
 			return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name)
 			return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name)
 		}
 		}
 	}
 	}
 
 
-	bm := btf.NewMap(spec, key, value)
+	if key == nil {
+		key = &btf.Void{}
+	}
+	if value == nil {
+		value = &btf.Void{}
+	}
 
 
 	return &MapSpec{
 	return &MapSpec{
 		Name:       SanitizeName(name, -1),
 		Name:       SanitizeName(name, -1),
@@ -754,9 +811,10 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
 		ValueSize:  valueSize,
 		ValueSize:  valueSize,
 		MaxEntries: maxEntries,
 		MaxEntries: maxEntries,
 		Flags:      flags,
 		Flags:      flags,
-		BTF:        &bm,
+		BTF:        &btf.Map{Spec: spec, Key: key, Value: value},
 		Pinning:    pinType,
 		Pinning:    pinType,
 		InnerMap:   innerMapSpec,
 		InnerMap:   innerMapSpec,
+		Contents:   contents,
 	}, nil
 	}, nil
 }
 }
 
 
@@ -793,6 +851,64 @@ func resolveBTFArrayMacro(typ btf.Type) (btf.Type, error) {
 	return ptr.Target, nil
 	return ptr.Target, nil
 }
 }
 
 
+// resolveBTFValuesContents resolves relocations into ELF sections belonging
+// to btf.VarSecinfo's. This can be used on the 'values' member in BTF map
+// definitions to extract static declarations of map contents.
+func resolveBTFValuesContents(es *elfSection, vs *btf.VarSecinfo, member btf.Member) ([]MapKV, error) {
+	// The elements of a .values pointer array are not encoded in BTF.
+	// Instead, relocations are generated into each array index.
+	// However, it's possible to leave certain array indices empty, so all
+	// indices' offsets need to be checked for emitted relocations.
+
+	// The offset of the 'values' member within the _struct_ (in bits)
+	// is the starting point of the array. Convert to bytes. Add VarSecinfo
+	// offset to get the absolute position in the ELF blob.
+	start := (member.OffsetBits / 8) + vs.Offset
+	// 'values' is encoded in BTF as a zero (variable) length struct
+	// member, and its contents run until the end of the VarSecinfo.
+	// Add VarSecinfo offset to get the absolute position in the ELF blob.
+	end := vs.Size + vs.Offset
+	// The size of an address in this section. This determines the width of
+	// an index in the array.
+	align := uint32(es.SectionHeader.Addralign)
+
+	// Check if variable-length section is aligned.
+	if (end-start)%align != 0 {
+		return nil, errors.New("unaligned static values section")
+	}
+	elems := (end - start) / align
+
+	if elems == 0 {
+		return nil, nil
+	}
+
+	contents := make([]MapKV, 0, elems)
+
+	// k is the array index, off is its corresponding ELF section offset.
+	for k, off := uint32(0), start; k < elems; k, off = k+1, off+align {
+		r, ok := es.relocations[uint64(off)]
+		if !ok {
+			continue
+		}
+
+		// Relocation exists for the current offset in the ELF section.
+		// Emit a value stub based on the type of relocation to be replaced by
+		// a real fd later in the pipeline before populating the map.
+		// Map keys are encoded in MapKV entries, so empty array indices are
+		// skipped here.
+		switch t := elf.ST_TYPE(r.Info); t {
+		case elf.STT_FUNC:
+			contents = append(contents, MapKV{uint32(k), programStub(r.Name)})
+		case elf.STT_OBJECT:
+			contents = append(contents, MapKV{uint32(k), mapStub(r.Name)})
+		default:
+			return nil, fmt.Errorf("unknown relocation type %v", t)
+		}
+	}
+
+	return contents, nil
+}
+
 func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
 func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
 	for _, sec := range ec.sections {
 	for _, sec := range ec.sections {
 		if sec.kind != dataSection {
 		if sec.kind != dataSection {
@@ -809,9 +925,9 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
 			return errors.New("data sections require BTF, make sure all consts are marked as static")
 			return errors.New("data sections require BTF, make sure all consts are marked as static")
 		}
 		}
 
 
-		btfMap, err := ec.btf.Datasec(sec.Name)
-		if err != nil {
-			return err
+		var datasec *btf.Datasec
+		if err := ec.btf.FindType(sec.Name, &datasec); err != nil {
+			return fmt.Errorf("data section %s: can't get BTF: %w", sec.Name, err)
 		}
 		}
 
 
 		data, err := sec.Data()
 		data, err := sec.Data()
@@ -830,7 +946,7 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
 			ValueSize:  uint32(len(data)),
 			ValueSize:  uint32(len(data)),
 			MaxEntries: 1,
 			MaxEntries: 1,
 			Contents:   []MapKV{{uint32(0), data}},
 			Contents:   []MapKV{{uint32(0), data}},
-			BTF:        btfMap,
+			BTF:        &btf.Map{Spec: ec.btf, Key: &btf.Void{}, Value: datasec},
 		}
 		}
 
 
 		switch sec.Name {
 		switch sec.Name {
@@ -855,6 +971,8 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
 	}{
 	}{
 		// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c
 		// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c
 		"socket":                {SocketFilter, AttachNone, 0},
 		"socket":                {SocketFilter, AttachNone, 0},
+		"sk_reuseport/migrate":  {SkReuseport, AttachSkReuseportSelectOrMigrate, 0},
+		"sk_reuseport":          {SkReuseport, AttachSkReuseportSelect, 0},
 		"seccomp":               {SocketFilter, AttachNone, 0},
 		"seccomp":               {SocketFilter, AttachNone, 0},
 		"kprobe/":               {Kprobe, AttachNone, 0},
 		"kprobe/":               {Kprobe, AttachNone, 0},
 		"uprobe/":               {Kprobe, AttachNone, 0},
 		"uprobe/":               {Kprobe, AttachNone, 0},
@@ -884,6 +1002,7 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
 		"fmod_ret.s/":           {Tracing, AttachModifyReturn, unix.BPF_F_SLEEPABLE},
 		"fmod_ret.s/":           {Tracing, AttachModifyReturn, unix.BPF_F_SLEEPABLE},
 		"fexit.s/":              {Tracing, AttachTraceFExit, unix.BPF_F_SLEEPABLE},
 		"fexit.s/":              {Tracing, AttachTraceFExit, unix.BPF_F_SLEEPABLE},
 		"sk_lookup/":            {SkLookup, AttachSkLookup, 0},
 		"sk_lookup/":            {SkLookup, AttachSkLookup, 0},
+		"freplace/":             {Extension, AttachNone, 0},
 		"lsm/":                  {LSM, AttachLSMMac, 0},
 		"lsm/":                  {LSM, AttachLSMMac, 0},
 		"lsm.s/":                {LSM, AttachLSMMac, unix.BPF_F_SLEEPABLE},
 		"lsm.s/":                {LSM, AttachLSMMac, unix.BPF_F_SLEEPABLE},
 
 
@@ -907,6 +1026,11 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
 		"cgroup/setsockopt":  {CGroupSockopt, AttachCGroupSetsockopt, 0},
 		"cgroup/setsockopt":  {CGroupSockopt, AttachCGroupSetsockopt, 0},
 		"classifier":         {SchedCLS, AttachNone, 0},
 		"classifier":         {SchedCLS, AttachNone, 0},
 		"action":             {SchedACT, AttachNone, 0},
 		"action":             {SchedACT, AttachNone, 0},
+
+		"cgroup/getsockname4": {CGroupSockAddr, AttachCgroupInet4GetSockname, 0},
+		"cgroup/getsockname6": {CGroupSockAddr, AttachCgroupInet6GetSockname, 0},
+		"cgroup/getpeername4": {CGroupSockAddr, AttachCgroupInet4GetPeername, 0},
+		"cgroup/getpeername6": {CGroupSockAddr, AttachCgroupInet6GetPeername, 0},
 	}
 	}
 
 
 	for prefix, t := range types {
 	for prefix, t := range types {

+ 1 - 0
vendor/github.com/cilium/ebpf/elf_reader_fuzz.go

@@ -1,3 +1,4 @@
+//go:build gofuzz
 // +build gofuzz
 // +build gofuzz
 
 
 // Use with https://github.com/dvyukov/go-fuzz
 // Use with https://github.com/dvyukov/go-fuzz

+ 35 - 1
vendor/github.com/cilium/ebpf/info.go

@@ -12,6 +12,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/cilium/ebpf/internal"
 	"github.com/cilium/ebpf/internal"
+	"github.com/cilium/ebpf/internal/btf"
 )
 )
 
 
 // MapInfo describes a map.
 // MapInfo describes a map.
@@ -87,12 +88,16 @@ type ProgramInfo struct {
 	Tag string
 	Tag string
 	// Name as supplied by user space at load time.
 	// Name as supplied by user space at load time.
 	Name string
 	Name string
+	// BTF for the program.
+	btf btf.ID
+	// IDS map ids related to program.
+	ids []MapID
 
 
 	stats *programStats
 	stats *programStats
 }
 }
 
 
 func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
 func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
-	info, err := bpfGetProgInfoByFD(fd)
+	info, err := bpfGetProgInfoByFD(fd, nil)
 	if errors.Is(err, syscall.EINVAL) {
 	if errors.Is(err, syscall.EINVAL) {
 		return newProgramInfoFromProc(fd)
 		return newProgramInfoFromProc(fd)
 	}
 	}
@@ -100,6 +105,15 @@ func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
+	var mapIDs []MapID
+	if info.nr_map_ids > 0 {
+		mapIDs = make([]MapID, info.nr_map_ids)
+		info, err = bpfGetProgInfoByFD(fd, mapIDs)
+		if err != nil {
+			return nil, err
+		}
+	}
+
 	return &ProgramInfo{
 	return &ProgramInfo{
 		Type: ProgramType(info.prog_type),
 		Type: ProgramType(info.prog_type),
 		id:   ProgramID(info.id),
 		id:   ProgramID(info.id),
@@ -107,6 +121,8 @@ func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
 		Tag: hex.EncodeToString(info.tag[:]),
 		Tag: hex.EncodeToString(info.tag[:]),
 		// name is available from 4.15.
 		// name is available from 4.15.
 		Name: internal.CString(info.name[:]),
 		Name: internal.CString(info.name[:]),
+		btf:  btf.ID(info.btf_id),
+		ids:  mapIDs,
 		stats: &programStats{
 		stats: &programStats{
 			runtime:  time.Duration(info.run_time_ns),
 			runtime:  time.Duration(info.run_time_ns),
 			runCount: info.run_cnt,
 			runCount: info.run_cnt,
@@ -142,6 +158,17 @@ func (pi *ProgramInfo) ID() (ProgramID, bool) {
 	return pi.id, pi.id > 0
 	return pi.id, pi.id > 0
 }
 }
 
 
+// BTFID returns the BTF ID associated with the program.
+//
+// Available from 5.0.
+//
+// The bool return value indicates whether this optional field is available and
+// populated. (The field may be available but not populated if the kernel
+// supports the field but the program was loaded without BTF information.)
+func (pi *ProgramInfo) BTFID() (btf.ID, bool) {
+	return pi.btf, pi.btf > 0
+}
+
 // RunCount returns the total number of times the program was called.
 // RunCount returns the total number of times the program was called.
 //
 //
 // Can return 0 if the collection of statistics is not enabled. See EnableStats().
 // Can return 0 if the collection of statistics is not enabled. See EnableStats().
@@ -164,6 +191,13 @@ func (pi *ProgramInfo) Runtime() (time.Duration, bool) {
 	return time.Duration(0), false
 	return time.Duration(0), false
 }
 }
 
 
+// MapIDs returns the maps related to the program.
+//
+// The bool return value indicates whether this optional field is available.
+func (pi *ProgramInfo) MapIDs() ([]MapID, bool) {
+	return pi.ids, pi.ids != nil
+}
+
 func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
 func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
 	raw, err := fd.Value()
 	raw, err := fd.Value()
 	if err != nil {
 	if err != nil {

+ 6 - 0
vendor/github.com/cilium/ebpf/internal/align.go

@@ -0,0 +1,6 @@
+package internal
+
+// Align returns 'n' updated to 'alignment' boundary.
+func Align(n, alignment int) int {
+	return (int(n) + alignment - 1) / alignment * alignment
+}

+ 146 - 147
vendor/github.com/cilium/ebpf/internal/btf/btf.go

@@ -7,7 +7,6 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
-	"io/ioutil"
 	"math"
 	"math"
 	"os"
 	"os"
 	"reflect"
 	"reflect"
@@ -27,12 +26,15 @@ var (
 	ErrNoExtendedInfo = errors.New("no extended info")
 	ErrNoExtendedInfo = errors.New("no extended info")
 )
 )
 
 
+// ID represents the unique ID of a BTF object.
+type ID uint32
+
 // Spec represents decoded BTF.
 // Spec represents decoded BTF.
 type Spec struct {
 type Spec struct {
 	rawTypes   []rawType
 	rawTypes   []rawType
 	strings    stringTable
 	strings    stringTable
 	types      []Type
 	types      []Type
-	namedTypes map[string][]namedType
+	namedTypes map[string][]NamedType
 	funcInfos  map[string]extInfo
 	funcInfos  map[string]extInfo
 	lineInfos  map[string]extInfo
 	lineInfos  map[string]extInfo
 	coreRelos  map[string]coreRelos
 	coreRelos  map[string]coreRelos
@@ -61,15 +63,6 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
 	}
 	}
 	defer file.Close()
 	defer file.Close()
 
 
-	btfSection, btfExtSection, sectionSizes, err := findBtfSections(file)
-	if err != nil {
-		return nil, err
-	}
-
-	if btfSection == nil {
-		return nil, fmt.Errorf("btf: %w", ErrNotFound)
-	}
-
 	symbols, err := file.Symbols()
 	symbols, err := file.Symbols()
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("can't read symbols: %v", err)
 		return nil, fmt.Errorf("can't read symbols: %v", err)
@@ -87,10 +80,6 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
 		}
 		}
 
 
 		secName := file.Sections[symbol.Section].Name
 		secName := file.Sections[symbol.Section].Name
-		if _, ok := sectionSizes[secName]; !ok {
-			continue
-		}
-
 		if symbol.Value > math.MaxUint32 {
 		if symbol.Value > math.MaxUint32 {
 			return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name)
 			return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name)
 		}
 		}
@@ -98,24 +87,10 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
 		variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value)
 		variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value)
 	}
 	}
 
 
-	spec, err := loadNakedSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets)
-	if err != nil {
-		return nil, err
-	}
-
-	if btfExtSection == nil {
-		return spec, nil
-	}
-
-	spec.funcInfos, spec.lineInfos, spec.coreRelos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
-	if err != nil {
-		return nil, fmt.Errorf("can't read ext info: %w", err)
-	}
-
-	return spec, nil
+	return loadSpecFromELF(file, variableOffsets)
 }
 }
 
 
-func findBtfSections(file *internal.SafeELFFile) (*elf.Section, *elf.Section, map[string]uint32, error) {
+func loadSpecFromELF(file *internal.SafeELFFile, variableOffsets map[variable]uint32) (*Spec, error) {
 	var (
 	var (
 		btfSection    *elf.Section
 		btfSection    *elf.Section
 		btfExtSection *elf.Section
 		btfExtSection *elf.Section
@@ -134,33 +109,45 @@ func findBtfSections(file *internal.SafeELFFile) (*elf.Section, *elf.Section, ma
 			}
 			}
 
 
 			if sec.Size > math.MaxUint32 {
 			if sec.Size > math.MaxUint32 {
-				return nil, nil, nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
+				return nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
 			}
 			}
 
 
 			sectionSizes[sec.Name] = uint32(sec.Size)
 			sectionSizes[sec.Name] = uint32(sec.Size)
 		}
 		}
 	}
 	}
-	return btfSection, btfExtSection, sectionSizes, nil
-}
 
 
-func loadSpecFromVmlinux(rd io.ReaderAt) (*Spec, error) {
-	file, err := internal.NewSafeELFFile(rd)
+	if btfSection == nil {
+		return nil, fmt.Errorf("btf: %w", ErrNotFound)
+	}
+
+	spec, err := loadRawSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	defer file.Close()
 
 
-	btfSection, _, _, err := findBtfSections(file)
-	if err != nil {
-		return nil, fmt.Errorf(".BTF ELF section: %s", err)
+	if btfExtSection == nil {
+		return spec, nil
 	}
 	}
-	if btfSection == nil {
-		return nil, fmt.Errorf("unable to find .BTF ELF section")
+
+	spec.funcInfos, spec.lineInfos, spec.coreRelos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
+	if err != nil {
+		return nil, fmt.Errorf("can't read ext info: %w", err)
 	}
 	}
-	return loadNakedSpec(btfSection.Open(), file.ByteOrder, nil, nil)
+
+	return spec, nil
+}
+
+// LoadRawSpec reads a blob of BTF data that isn't wrapped in an ELF file.
+//
+// Prefer using LoadSpecFromReader, since this function only supports a subset
+// of BTF.
+func LoadRawSpec(btf io.Reader, bo binary.ByteOrder) (*Spec, error) {
+	// This will return an error if we encounter a Datasec, since we can't fix
+	// it up.
+	return loadRawSpec(btf, bo, nil, nil)
 }
 }
 
 
-func loadNakedSpec(btf io.ReadSeeker, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) {
+func loadRawSpec(btf io.Reader, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) {
 	rawTypes, rawStrings, err := parseBTF(btf, bo)
 	rawTypes, rawStrings, err := parseBTF(btf, bo)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -217,7 +204,7 @@ func loadKernelSpec() (*Spec, error) {
 	if err == nil {
 	if err == nil {
 		defer fh.Close()
 		defer fh.Close()
 
 
-		return loadNakedSpec(fh, internal.NativeEndian, nil, nil)
+		return LoadRawSpec(fh, internal.NativeEndian)
 	}
 	}
 
 
 	// use same list of locations as libbpf
 	// use same list of locations as libbpf
@@ -241,14 +228,20 @@ func loadKernelSpec() (*Spec, error) {
 		}
 		}
 		defer fh.Close()
 		defer fh.Close()
 
 
-		return loadSpecFromVmlinux(fh)
+		file, err := internal.NewSafeELFFile(fh)
+		if err != nil {
+			return nil, err
+		}
+		defer file.Close()
+
+		return loadSpecFromELF(file, nil)
 	}
 	}
 
 
 	return nil, fmt.Errorf("no BTF for kernel version %s: %w", release, internal.ErrNotSupported)
 	return nil, fmt.Errorf("no BTF for kernel version %s: %w", release, internal.ErrNotSupported)
 }
 }
 
 
-func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) ([]rawType, stringTable, error) {
-	rawBTF, err := ioutil.ReadAll(btf)
+func parseBTF(btf io.Reader, bo binary.ByteOrder) ([]rawType, stringTable, error) {
+	rawBTF, err := io.ReadAll(btf)
 	if err != nil {
 	if err != nil {
 		return nil, nil, fmt.Errorf("can't read BTF: %v", err)
 		return nil, nil, fmt.Errorf("can't read BTF: %v", err)
 	}
 	}
@@ -357,6 +350,30 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s
 	return nil
 	return nil
 }
 }
 
 
+// Copy creates a copy of Spec.
+func (s *Spec) Copy() *Spec {
+	types, _ := copyTypes(s.types, nil)
+	namedTypes := make(map[string][]NamedType)
+	for _, typ := range types {
+		if named, ok := typ.(NamedType); ok {
+			name := essentialName(named.TypeName())
+			namedTypes[name] = append(namedTypes[name], named)
+		}
+	}
+
+	// NB: Other parts of spec are not copied since they are immutable.
+	return &Spec{
+		s.rawTypes,
+		s.strings,
+		types,
+		namedTypes,
+		s.funcInfos,
+		s.lineInfos,
+		s.coreRelos,
+		s.byteOrder,
+	}
+}
+
 type marshalOpts struct {
 type marshalOpts struct {
 	ByteOrder        binary.ByteOrder
 	ByteOrder        binary.ByteOrder
 	StripFuncLinkage bool
 	StripFuncLinkage bool
@@ -447,36 +464,37 @@ func (s *Spec) Program(name string, length uint64) (*Program, error) {
 	return &Program{s, length, funcInfos, lineInfos, relos}, nil
 	return &Program{s, length, funcInfos, lineInfos, relos}, nil
 }
 }
 
 
-// Datasec returns the BTF required to create maps which represent data sections.
-func (s *Spec) Datasec(name string) (*Map, error) {
-	var datasec Datasec
-	if err := s.FindType(name, &datasec); err != nil {
-		return nil, fmt.Errorf("data section %s: can't get BTF: %w", name, err)
-	}
-
-	m := NewMap(s, &Void{}, &datasec)
-	return &m, nil
-}
-
 // FindType searches for a type with a specific name.
 // FindType searches for a type with a specific name.
 //
 //
-// hint determines the type of the returned Type.
+// Called T a type that satisfies Type, typ must be a non-nil **T.
+// On success, the address of the found type will be copied in typ.
 //
 //
 // Returns an error wrapping ErrNotFound if no matching
 // Returns an error wrapping ErrNotFound if no matching
 // type exists in spec.
 // type exists in spec.
-func (s *Spec) FindType(name string, typ Type) error {
-	var (
-		wanted    = reflect.TypeOf(typ)
-		candidate Type
-	)
+func (s *Spec) FindType(name string, typ interface{}) error {
+	typValue := reflect.ValueOf(typ)
+	if typValue.Kind() != reflect.Ptr {
+		return fmt.Errorf("%T is not a pointer", typ)
+	}
+
+	typPtr := typValue.Elem()
+	if !typPtr.CanSet() {
+		return fmt.Errorf("%T cannot be set", typ)
+	}
 
 
+	wanted := typPtr.Type()
+	if !wanted.AssignableTo(reflect.TypeOf((*Type)(nil)).Elem()) {
+		return fmt.Errorf("%T does not satisfy Type interface", typ)
+	}
+
+	var candidate Type
 	for _, typ := range s.namedTypes[essentialName(name)] {
 	for _, typ := range s.namedTypes[essentialName(name)] {
 		if reflect.TypeOf(typ) != wanted {
 		if reflect.TypeOf(typ) != wanted {
 			continue
 			continue
 		}
 		}
 
 
 		// Match against the full name, not just the essential one.
 		// Match against the full name, not just the essential one.
-		if typ.name() != name {
+		if typ.TypeName() != name {
 			continue
 			continue
 		}
 		}
 
 
@@ -491,15 +509,15 @@ func (s *Spec) FindType(name string, typ Type) error {
 		return fmt.Errorf("type %s: %w", name, ErrNotFound)
 		return fmt.Errorf("type %s: %w", name, ErrNotFound)
 	}
 	}
 
 
-	cpy, _ := copyType(candidate, nil)
-	value := reflect.Indirect(reflect.ValueOf(cpy))
-	reflect.Indirect(reflect.ValueOf(typ)).Set(value)
+	typPtr.Set(reflect.ValueOf(candidate))
+
 	return nil
 	return nil
 }
 }
 
 
 // Handle is a reference to BTF loaded into the kernel.
 // Handle is a reference to BTF loaded into the kernel.
 type Handle struct {
 type Handle struct {
-	fd *internal.FD
+	spec *Spec
+	fd   *internal.FD
 }
 }
 
 
 // NewHandle loads BTF into the kernel.
 // NewHandle loads BTF into the kernel.
@@ -541,7 +559,32 @@ func NewHandle(spec *Spec) (*Handle, error) {
 		return nil, internal.ErrorWithLog(err, logBuf, logErr)
 		return nil, internal.ErrorWithLog(err, logBuf, logErr)
 	}
 	}
 
 
-	return &Handle{fd}, nil
+	return &Handle{spec.Copy(), fd}, nil
+}
+
+// NewHandleFromID returns the BTF handle for a given id.
+//
+// Returns ErrNotExist, if there is no BTF with the given id.
+//
+// Requires CAP_SYS_ADMIN.
+func NewHandleFromID(id ID) (*Handle, error) {
+	fd, err := internal.BPFObjGetFDByID(internal.BPF_BTF_GET_FD_BY_ID, uint32(id))
+	if err != nil {
+		return nil, fmt.Errorf("get BTF by id: %w", err)
+	}
+
+	info, err := newInfoFromFd(fd)
+	if err != nil {
+		_ = fd.Close()
+		return nil, fmt.Errorf("get BTF spec for handle: %w", err)
+	}
+
+	return &Handle{info.BTF, fd}, nil
+}
+
+// Spec returns the Spec that defined the BTF loaded into the kernel.
+func (h *Handle) Spec() *Spec {
+	return h.spec
 }
 }
 
 
 // Close destroys the handle.
 // Close destroys the handle.
@@ -563,43 +606,8 @@ func (h *Handle) FD() int {
 
 
 // Map is the BTF for a map.
 // Map is the BTF for a map.
 type Map struct {
 type Map struct {
-	spec       *Spec
-	key, value Type
-}
-
-// NewMap returns a new Map containing the given values.
-// The key and value arguments are initialized to Void if nil values are given.
-func NewMap(spec *Spec, key Type, value Type) Map {
-	if key == nil {
-		key = &Void{}
-	}
-	if value == nil {
-		value = &Void{}
-	}
-
-	return Map{
-		spec:  spec,
-		key:   key,
-		value: value,
-	}
-}
-
-// MapSpec should be a method on Map, but is a free function
-// to hide it from users of the ebpf package.
-func MapSpec(m *Map) *Spec {
-	return m.spec
-}
-
-// MapKey should be a method on Map, but is a free function
-// to hide it from users of the ebpf package.
-func MapKey(m *Map) Type {
-	return m.key
-}
-
-// MapValue should be a method on Map, but is a free function
-// to hide it from users of the ebpf package.
-func MapValue(m *Map) Type {
-	return m.value
+	Spec       *Spec
+	Key, Value Type
 }
 }
 
 
 // Program is the BTF information for a stream of instructions.
 // Program is the BTF information for a stream of instructions.
@@ -610,68 +618,59 @@ type Program struct {
 	coreRelos            coreRelos
 	coreRelos            coreRelos
 }
 }
 
 
-// ProgramSpec returns the Spec needed for loading function and line infos into the kernel.
-//
-// This is a free function instead of a method to hide it from users
-// of package ebpf.
-func ProgramSpec(s *Program) *Spec {
-	return s.spec
+// Spec returns the BTF spec of this program.
+func (p *Program) Spec() *Spec {
+	return p.spec
 }
 }
 
 
-// ProgramAppend the information from other to the Program.
-//
-// This is a free function instead of a method to hide it from users
-// of package ebpf.
-func ProgramAppend(s, other *Program) error {
-	funcInfos, err := s.funcInfos.append(other.funcInfos, s.length)
+// Append the information from other to the Program.
+func (p *Program) Append(other *Program) error {
+	if other.spec != p.spec {
+		return fmt.Errorf("can't append program with different BTF specs")
+	}
+
+	funcInfos, err := p.funcInfos.append(other.funcInfos, p.length)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("func infos: %w", err)
 		return fmt.Errorf("func infos: %w", err)
 	}
 	}
 
 
-	lineInfos, err := s.lineInfos.append(other.lineInfos, s.length)
+	lineInfos, err := p.lineInfos.append(other.lineInfos, p.length)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("line infos: %w", err)
 		return fmt.Errorf("line infos: %w", err)
 	}
 	}
 
 
-	s.funcInfos = funcInfos
-	s.lineInfos = lineInfos
-	s.coreRelos = s.coreRelos.append(other.coreRelos, s.length)
-	s.length += other.length
+	p.funcInfos = funcInfos
+	p.lineInfos = lineInfos
+	p.coreRelos = p.coreRelos.append(other.coreRelos, p.length)
+	p.length += other.length
 	return nil
 	return nil
 }
 }
 
 
-// ProgramFuncInfos returns the binary form of BTF function infos.
-//
-// This is a free function instead of a method to hide it from users
-// of package ebpf.
-func ProgramFuncInfos(s *Program) (recordSize uint32, bytes []byte, err error) {
-	bytes, err = s.funcInfos.MarshalBinary()
+// FuncInfos returns the binary form of BTF function infos.
+func (p *Program) FuncInfos() (recordSize uint32, bytes []byte, err error) {
+	bytes, err = p.funcInfos.MarshalBinary()
 	if err != nil {
 	if err != nil {
-		return 0, nil, err
+		return 0, nil, fmt.Errorf("func infos: %w", err)
 	}
 	}
 
 
-	return s.funcInfos.recordSize, bytes, nil
+	return p.funcInfos.recordSize, bytes, nil
 }
 }
 
 
-// ProgramLineInfos returns the binary form of BTF line infos.
-//
-// This is a free function instead of a method to hide it from users
-// of package ebpf.
-func ProgramLineInfos(s *Program) (recordSize uint32, bytes []byte, err error) {
-	bytes, err = s.lineInfos.MarshalBinary()
+// LineInfos returns the binary form of BTF line infos.
+func (p *Program) LineInfos() (recordSize uint32, bytes []byte, err error) {
+	bytes, err = p.lineInfos.MarshalBinary()
 	if err != nil {
 	if err != nil {
-		return 0, nil, err
+		return 0, nil, fmt.Errorf("line infos: %w", err)
 	}
 	}
 
 
-	return s.lineInfos.recordSize, bytes, nil
+	return p.lineInfos.recordSize, bytes, nil
 }
 }
 
 
-// ProgramFixups returns the changes required to adjust the program to the target.
+// Fixups returns the changes required to adjust the program to the target.
 //
 //
-// This is a free function instead of a method to hide it from users
-// of package ebpf.
-func ProgramFixups(s *Program, target *Spec) (COREFixups, error) {
-	if len(s.coreRelos) == 0 {
+// Passing a nil target will relocate against the running kernel.
+func (p *Program) Fixups(target *Spec) (COREFixups, error) {
+	if len(p.coreRelos) == 0 {
 		return nil, nil
 		return nil, nil
 	}
 	}
 
 
@@ -683,7 +682,7 @@ func ProgramFixups(s *Program, target *Spec) (COREFixups, error) {
 		}
 		}
 	}
 	}
 
 
-	return coreRelocate(s.spec, target, s.coreRelos)
+	return coreRelocate(p.spec, target, p.coreRelos)
 }
 }
 
 
 type bpfLoadBTFAttr struct {
 type bpfLoadBTFAttr struct {

+ 8 - 3
vendor/github.com/cilium/ebpf/internal/btf/btf_types.go

@@ -31,6 +31,8 @@ const (
 	// Added ~5.1
 	// Added ~5.1
 	kindVar
 	kindVar
 	kindDatasec
 	kindDatasec
+	// Added ~5.13
+	kindFloat
 )
 )
 
 
 // FuncLinkage describes BTF function linkage metadata.
 // FuncLinkage describes BTF function linkage metadata.
@@ -54,7 +56,7 @@ const (
 
 
 const (
 const (
 	btfTypeKindShift     = 24
 	btfTypeKindShift     = 24
-	btfTypeKindLen       = 4
+	btfTypeKindLen       = 5
 	btfTypeVlenShift     = 0
 	btfTypeVlenShift     = 0
 	btfTypeVlenMask      = 16
 	btfTypeVlenMask      = 16
 	btfTypeKindFlagShift = 31
 	btfTypeKindFlagShift = 31
@@ -67,8 +69,8 @@ type btfType struct {
 	/* "info" bits arrangement
 	/* "info" bits arrangement
 	 * bits  0-15: vlen (e.g. # of struct's members), linkage
 	 * bits  0-15: vlen (e.g. # of struct's members), linkage
 	 * bits 16-23: unused
 	 * bits 16-23: unused
-	 * bits 24-27: kind (e.g. int, ptr, array...etc)
-	 * bits 28-30: unused
+	 * bits 24-28: kind (e.g. int, ptr, array...etc)
+	 * bits 29-30: unused
 	 * bit     31: kind_flag, currently used by
 	 * bit     31: kind_flag, currently used by
 	 *             struct, union and fwd
 	 *             struct, union and fwd
 	 */
 	 */
@@ -117,6 +119,8 @@ func (k btfKind) String() string {
 		return "Variable"
 		return "Variable"
 	case kindDatasec:
 	case kindDatasec:
 		return "Section"
 		return "Section"
+	case kindFloat:
+		return "Float"
 	default:
 	default:
 		return fmt.Sprintf("Unknown (%d)", k)
 		return fmt.Sprintf("Unknown (%d)", k)
 	}
 	}
@@ -260,6 +264,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
 			data = new(btfVariable)
 			data = new(btfVariable)
 		case kindDatasec:
 		case kindDatasec:
 			data = make([]btfVarSecinfo, header.Vlen())
 			data = make([]btfVarSecinfo, header.Vlen())
+		case kindFloat:
 		default:
 		default:
 			return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
 			return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
 		}
 		}

+ 17 - 16
vendor/github.com/cilium/ebpf/internal/btf/core.go

@@ -234,13 +234,13 @@ func coreRelocate(local, target *Spec, relos coreRelos) (COREFixups, error) {
 		}
 		}
 
 
 		localType := local.types[id]
 		localType := local.types[id]
-		named, ok := localType.(namedType)
-		if !ok || named.name() == "" {
+		named, ok := localType.(NamedType)
+		if !ok || named.TypeName() == "" {
 			return nil, fmt.Errorf("relocate unnamed or anonymous type %s: %w", localType, ErrNotSupported)
 			return nil, fmt.Errorf("relocate unnamed or anonymous type %s: %w", localType, ErrNotSupported)
 		}
 		}
 
 
 		relos := relosByID[id]
 		relos := relosByID[id]
-		targets := target.namedTypes[named.essentialName()]
+		targets := target.namedTypes[essentialName(named.TypeName())]
 		fixups, err := coreCalculateFixups(localType, targets, relos)
 		fixups, err := coreCalculateFixups(localType, targets, relos)
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf("relocate %s: %w", localType, err)
 			return nil, fmt.Errorf("relocate %s: %w", localType, err)
@@ -262,7 +262,7 @@ var errImpossibleRelocation = errors.New("impossible relocation")
 //
 //
 // The best target is determined by scoring: the less poisoning we have to do
 // The best target is determined by scoring: the less poisoning we have to do
 // the better the target is.
 // the better the target is.
-func coreCalculateFixups(local Type, targets []namedType, relos coreRelos) ([]COREFixup, error) {
+func coreCalculateFixups(local Type, targets []NamedType, relos coreRelos) ([]COREFixup, error) {
 	localID := local.ID()
 	localID := local.ID()
 	local, err := copyType(local, skipQualifierAndTypedef)
 	local, err := copyType(local, skipQualifierAndTypedef)
 	if err != nil {
 	if err != nil {
@@ -467,8 +467,8 @@ func parseCoreAccessor(accessor string) (coreAccessor, error) {
 		return nil, fmt.Errorf("empty accessor")
 		return nil, fmt.Errorf("empty accessor")
 	}
 	}
 
 
-	var result coreAccessor
 	parts := strings.Split(accessor, ":")
 	parts := strings.Split(accessor, ":")
+	result := make(coreAccessor, 0, len(parts))
 	for _, part := range parts {
 	for _, part := range parts {
 		// 31 bits to avoid overflowing int on 32 bit platforms.
 		// 31 bits to avoid overflowing int on 32 bit platforms.
 		index, err := strconv.ParseUint(part, 10, 31)
 		index, err := strconv.ParseUint(part, 10, 31)
@@ -564,7 +564,7 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
 
 
 				// This is an anonymous struct or union, ignore it.
 				// This is an anonymous struct or union, ignore it.
 				local = localMember.Type
 				local = localMember.Type
-				localOffset += localMember.Offset
+				localOffset += localMember.OffsetBits
 				localMaybeFlex = false
 				localMaybeFlex = false
 				continue
 				continue
 			}
 			}
@@ -585,10 +585,10 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
 
 
 			local = localMember.Type
 			local = localMember.Type
 			localMaybeFlex = acc == len(localMembers)-1
 			localMaybeFlex = acc == len(localMembers)-1
-			localOffset += localMember.Offset
+			localOffset += localMember.OffsetBits
 			target = targetMember.Type
 			target = targetMember.Type
 			targetMaybeFlex = last
 			targetMaybeFlex = last
-			targetOffset += targetMember.Offset
+			targetOffset += targetMember.OffsetBits
 
 
 		case *Array:
 		case *Array:
 			// For arrays, acc is the index in the target.
 			// For arrays, acc is the index in the target.
@@ -639,7 +639,7 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
 
 
 // coreFindMember finds a member in a composite type while handling anonymous
 // coreFindMember finds a member in a composite type while handling anonymous
 // structs and unions.
 // structs and unions.
-func coreFindMember(typ composite, name Name) (Member, bool, error) {
+func coreFindMember(typ composite, name string) (Member, bool, error) {
 	if name == "" {
 	if name == "" {
 		return Member{}, false, errors.New("can't search for anonymous member")
 		return Member{}, false, errors.New("can't search for anonymous member")
 	}
 	}
@@ -670,7 +670,7 @@ func coreFindMember(typ composite, name Name) (Member, bool, error) {
 		for j, member := range members {
 		for j, member := range members {
 			if member.Name == name {
 			if member.Name == name {
 				// NB: This is safe because member is a copy.
 				// NB: This is safe because member is a copy.
-				member.Offset += target.offset
+				member.OffsetBits += target.offset
 				return member, j == len(members)-1, nil
 				return member, j == len(members)-1, nil
 			}
 			}
 
 
@@ -685,7 +685,7 @@ func coreFindMember(typ composite, name Name) (Member, bool, error) {
 				return Member{}, false, fmt.Errorf("anonymous non-composite type %T not allowed", member.Type)
 				return Member{}, false, fmt.Errorf("anonymous non-composite type %T not allowed", member.Type)
 			}
 			}
 
 
-			targets = append(targets, offsetTarget{comp, target.offset + member.Offset})
+			targets = append(targets, offsetTarget{comp, target.offset + member.OffsetBits})
 		}
 		}
 	}
 	}
 
 
@@ -704,9 +704,9 @@ func coreFindEnumValue(local Type, localAcc coreAccessor, target Type) (localVal
 		return nil, nil, errImpossibleRelocation
 		return nil, nil, errImpossibleRelocation
 	}
 	}
 
 
-	localName := localValue.Name.essentialName()
+	localName := essentialName(localValue.Name)
 	for i, targetValue := range targetEnum.Values {
 	for i, targetValue := range targetEnum.Values {
-		if targetValue.Name.essentialName() != localName {
+		if essentialName(targetValue.Name) != localName {
 			continue
 			continue
 		}
 		}
 
 
@@ -813,6 +813,7 @@ func coreAreTypesCompatible(localType Type, targetType Type) error {
  *     least one of enums should be anonymous;
  *     least one of enums should be anonymous;
  *   - for ENUMs, check sizes, names are ignored;
  *   - for ENUMs, check sizes, names are ignored;
  *   - for INT, size and signedness are ignored;
  *   - for INT, size and signedness are ignored;
+ *   - any two FLOATs are always compatible;
  *   - for ARRAY, dimensionality is ignored, element types are checked for
  *   - for ARRAY, dimensionality is ignored, element types are checked for
  *     compatibility recursively;
  *     compatibility recursively;
  *     [ NB: coreAreMembersCompatible doesn't recurse, this check is done
  *     [ NB: coreAreMembersCompatible doesn't recurse, this check is done
@@ -848,16 +849,16 @@ func coreAreMembersCompatible(localType Type, targetType Type) error {
 	}
 	}
 
 
 	switch lv := localType.(type) {
 	switch lv := localType.(type) {
-	case *Array, *Pointer:
+	case *Array, *Pointer, *Float:
 		return nil
 		return nil
 
 
 	case *Enum:
 	case *Enum:
 		tv := targetType.(*Enum)
 		tv := targetType.(*Enum)
-		return doNamesMatch(lv.name(), tv.name())
+		return doNamesMatch(lv.Name, tv.Name)
 
 
 	case *Fwd:
 	case *Fwd:
 		tv := targetType.(*Fwd)
 		tv := targetType.(*Fwd)
-		return doNamesMatch(lv.name(), tv.name())
+		return doNamesMatch(lv.Name, tv.Name)
 
 
 	case *Int:
 	case *Int:
 		tv := targetType.(*Int)
 		tv := targetType.(*Int)

+ 12 - 3
vendor/github.com/cilium/ebpf/internal/btf/ext_info.go

@@ -7,7 +7,6 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
-	"io/ioutil"
 
 
 	"github.com/cilium/ebpf/asm"
 	"github.com/cilium/ebpf/asm"
 	"github.com/cilium/ebpf/internal"
 	"github.com/cilium/ebpf/internal"
@@ -64,7 +63,7 @@ func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (f
 
 
 	// Of course, the .BTF.ext header has different semantics than the
 	// Of course, the .BTF.ext header has different semantics than the
 	// .BTF ext header. We need to ignore non-null values.
 	// .BTF ext header. We need to ignore non-null values.
-	_, err = io.CopyN(ioutil.Discard, r, remainder)
+	_, err = io.CopyN(io.Discard, r, remainder)
 	if err != nil {
 	if err != nil {
 		return nil, nil, nil, fmt.Errorf("header padding: %v", err)
 		return nil, nil, nil, fmt.Errorf("header padding: %v", err)
 	}
 	}
@@ -114,11 +113,16 @@ type extInfoRecord struct {
 }
 }
 
 
 type extInfo struct {
 type extInfo struct {
+	byteOrder  binary.ByteOrder
 	recordSize uint32
 	recordSize uint32
 	records    []extInfoRecord
 	records    []extInfoRecord
 }
 }
 
 
 func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
 func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
+	if other.byteOrder != ei.byteOrder {
+		return extInfo{}, fmt.Errorf("ext_info byte order mismatch, want %v (got %v)", ei.byteOrder, other.byteOrder)
+	}
+
 	if other.recordSize != ei.recordSize {
 	if other.recordSize != ei.recordSize {
 		return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
 		return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
 	}
 	}
@@ -131,10 +135,14 @@ func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
 			Opaque:  info.Opaque,
 			Opaque:  info.Opaque,
 		})
 		})
 	}
 	}
-	return extInfo{ei.recordSize, records}, nil
+	return extInfo{ei.byteOrder, ei.recordSize, records}, nil
 }
 }
 
 
 func (ei extInfo) MarshalBinary() ([]byte, error) {
 func (ei extInfo) MarshalBinary() ([]byte, error) {
+	if ei.byteOrder != internal.NativeEndian {
+		return nil, fmt.Errorf("%s is not the native byte order", ei.byteOrder)
+	}
+
 	if len(ei.records) == 0 {
 	if len(ei.records) == 0 {
 		return nil, nil
 		return nil, nil
 	}
 	}
@@ -197,6 +205,7 @@ func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[st
 		}
 		}
 
 
 		result[secName] = extInfo{
 		result[secName] = extInfo{
+			bo,
 			recordSize,
 			recordSize,
 			records,
 			records,
 		}
 		}

+ 1 - 0
vendor/github.com/cilium/ebpf/internal/btf/fuzz.go

@@ -1,3 +1,4 @@
+//go:build gofuzz
 // +build gofuzz
 // +build gofuzz
 
 
 // Use with https://github.com/dvyukov/go-fuzz
 // Use with https://github.com/dvyukov/go-fuzz

+ 48 - 0
vendor/github.com/cilium/ebpf/internal/btf/info.go

@@ -0,0 +1,48 @@
+package btf
+
+import (
+	"bytes"
+
+	"github.com/cilium/ebpf/internal"
+)
+
+// info describes a BTF object.
+type info struct {
+	BTF *Spec
+	ID  ID
+	// Name is an identifying name for the BTF, currently only used by the
+	// kernel.
+	Name string
+	// KernelBTF is true if the BTf originated with the kernel and not
+	// userspace.
+	KernelBTF bool
+}
+
+func newInfoFromFd(fd *internal.FD) (*info, error) {
+	// We invoke the syscall once with a empty BTF and name buffers to get size
+	// information to allocate buffers. Then we invoke it a second time with
+	// buffers to receive the data.
+	bpfInfo, err := bpfGetBTFInfoByFD(fd, nil, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	btfBuffer := make([]byte, bpfInfo.btfSize)
+	nameBuffer := make([]byte, bpfInfo.nameLen)
+	bpfInfo, err = bpfGetBTFInfoByFD(fd, btfBuffer, nameBuffer)
+	if err != nil {
+		return nil, err
+	}
+
+	spec, err := loadRawSpec(bytes.NewReader(btfBuffer), internal.NativeEndian, nil, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return &info{
+		BTF:       spec,
+		ID:        ID(bpfInfo.id),
+		Name:      internal.CString(nameBuffer),
+		KernelBTF: bpfInfo.kernelBTF != 0,
+	}, nil
+}

+ 1 - 7
vendor/github.com/cilium/ebpf/internal/btf/strings.go

@@ -5,13 +5,12 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
-	"io/ioutil"
 )
 )
 
 
 type stringTable []byte
 type stringTable []byte
 
 
 func readStringTable(r io.Reader) (stringTable, error) {
 func readStringTable(r io.Reader) (stringTable, error) {
-	contents, err := ioutil.ReadAll(r)
+	contents, err := io.ReadAll(r)
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("can't read string table: %v", err)
 		return nil, fmt.Errorf("can't read string table: %v", err)
 	}
 	}
@@ -53,8 +52,3 @@ func (st stringTable) Lookup(offset uint32) (string, error) {
 
 
 	return string(str[:end]), nil
 	return string(str[:end]), nil
 }
 }
-
-func (st stringTable) LookupName(offset uint32) (Name, error) {
-	str, err := st.Lookup(offset)
-	return Name(str), err
-}

+ 31 - 0
vendor/github.com/cilium/ebpf/internal/btf/syscalls.go

@@ -0,0 +1,31 @@
+package btf
+
+import (
+	"fmt"
+	"unsafe"
+
+	"github.com/cilium/ebpf/internal"
+)
+
+type bpfBTFInfo struct {
+	btf       internal.Pointer
+	btfSize   uint32
+	id        uint32
+	name      internal.Pointer
+	nameLen   uint32
+	kernelBTF uint32
+}
+
+func bpfGetBTFInfoByFD(fd *internal.FD, btf, name []byte) (*bpfBTFInfo, error) {
+	info := bpfBTFInfo{
+		btf:     internal.NewSlicePointer(btf),
+		btfSize: uint32(len(btf)),
+		name:    internal.NewSlicePointer(name),
+		nameLen: uint32(len(name)),
+	}
+	if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
+		return nil, fmt.Errorf("can't get program info: %w", err)
+	}
+
+	return &info, nil
+}

+ 126 - 62
vendor/github.com/cilium/ebpf/internal/btf/types.go

@@ -30,27 +30,26 @@ type Type interface {
 	walk(*typeDeque)
 	walk(*typeDeque)
 }
 }
 
 
-// namedType is a type with a name.
-//
-// Most named types simply embed Name.
-type namedType interface {
+// NamedType is a type with a name.
+type NamedType interface {
 	Type
 	Type
-	name() string
-	essentialName() string
-}
-
-// Name identifies a type.
-//
-// Anonymous types have an empty name.
-type Name string
 
 
-func (n Name) name() string {
-	return string(n)
+	// Name of the type, empty for anonymous types.
+	TypeName() string
 }
 }
 
 
-func (n Name) essentialName() string {
-	return essentialName(string(n))
-}
+var (
+	_ NamedType = (*Int)(nil)
+	_ NamedType = (*Struct)(nil)
+	_ NamedType = (*Union)(nil)
+	_ NamedType = (*Enum)(nil)
+	_ NamedType = (*Fwd)(nil)
+	_ NamedType = (*Func)(nil)
+	_ NamedType = (*Typedef)(nil)
+	_ NamedType = (*Var)(nil)
+	_ NamedType = (*Datasec)(nil)
+	_ NamedType = (*Float)(nil)
+)
 
 
 // Void is the unit type of BTF.
 // Void is the unit type of BTF.
 type Void struct{}
 type Void struct{}
@@ -72,19 +71,17 @@ const (
 // Int is an integer of a given length.
 // Int is an integer of a given length.
 type Int struct {
 type Int struct {
 	TypeID
 	TypeID
-	Name
+	Name string
 
 
 	// The size of the integer in bytes.
 	// The size of the integer in bytes.
 	Size     uint32
 	Size     uint32
 	Encoding IntEncoding
 	Encoding IntEncoding
-	// Offset is the starting bit offset. Currently always 0.
+	// OffsetBits is the starting bit offset. Currently always 0.
 	// See https://www.kernel.org/doc/html/latest/bpf/btf.html#btf-kind-int
 	// See https://www.kernel.org/doc/html/latest/bpf/btf.html#btf-kind-int
-	Offset uint32
-	Bits   byte
+	OffsetBits uint32
+	Bits       byte
 }
 }
 
 
-var _ namedType = (*Int)(nil)
-
 func (i *Int) String() string {
 func (i *Int) String() string {
 	var s strings.Builder
 	var s strings.Builder
 
 
@@ -110,15 +107,16 @@ func (i *Int) String() string {
 	return s.String()
 	return s.String()
 }
 }
 
 
-func (i *Int) size() uint32    { return i.Size }
-func (i *Int) walk(*typeDeque) {}
+func (i *Int) TypeName() string { return i.Name }
+func (i *Int) size() uint32     { return i.Size }
+func (i *Int) walk(*typeDeque)  {}
 func (i *Int) copy() Type {
 func (i *Int) copy() Type {
 	cpy := *i
 	cpy := *i
 	return &cpy
 	return &cpy
 }
 }
 
 
 func (i *Int) isBitfield() bool {
 func (i *Int) isBitfield() bool {
-	return i.Offset > 0
+	return i.OffsetBits > 0
 }
 }
 
 
 // Pointer is a pointer to another type.
 // Pointer is a pointer to another type.
@@ -158,7 +156,7 @@ func (arr *Array) copy() Type {
 // Struct is a compound type of consecutive members.
 // Struct is a compound type of consecutive members.
 type Struct struct {
 type Struct struct {
 	TypeID
 	TypeID
-	Name
+	Name string
 	// The size of the struct including padding, in bytes
 	// The size of the struct including padding, in bytes
 	Size    uint32
 	Size    uint32
 	Members []Member
 	Members []Member
@@ -168,6 +166,8 @@ func (s *Struct) String() string {
 	return fmt.Sprintf("struct#%d[%q]", s.TypeID, s.Name)
 	return fmt.Sprintf("struct#%d[%q]", s.TypeID, s.Name)
 }
 }
 
 
+func (s *Struct) TypeName() string { return s.Name }
+
 func (s *Struct) size() uint32 { return s.Size }
 func (s *Struct) size() uint32 { return s.Size }
 
 
 func (s *Struct) walk(tdq *typeDeque) {
 func (s *Struct) walk(tdq *typeDeque) {
@@ -189,7 +189,7 @@ func (s *Struct) members() []Member {
 // Union is a compound type where members occupy the same memory.
 // Union is a compound type where members occupy the same memory.
 type Union struct {
 type Union struct {
 	TypeID
 	TypeID
-	Name
+	Name string
 	// The size of the union including padding, in bytes.
 	// The size of the union including padding, in bytes.
 	Size    uint32
 	Size    uint32
 	Members []Member
 	Members []Member
@@ -199,6 +199,8 @@ func (u *Union) String() string {
 	return fmt.Sprintf("union#%d[%q]", u.TypeID, u.Name)
 	return fmt.Sprintf("union#%d[%q]", u.TypeID, u.Name)
 }
 }
 
 
+func (u *Union) TypeName() string { return u.Name }
+
 func (u *Union) size() uint32 { return u.Size }
 func (u *Union) size() uint32 { return u.Size }
 
 
 func (u *Union) walk(tdq *typeDeque) {
 func (u *Union) walk(tdq *typeDeque) {
@@ -236,17 +238,17 @@ var (
 //
 //
 // It is not a valid Type.
 // It is not a valid Type.
 type Member struct {
 type Member struct {
-	Name
+	Name string
 	Type Type
 	Type Type
-	// Offset is the bit offset of this member
-	Offset       uint32
+	// OffsetBits is the bit offset of this member.
+	OffsetBits   uint32
 	BitfieldSize uint32
 	BitfieldSize uint32
 }
 }
 
 
 // Enum lists possible values.
 // Enum lists possible values.
 type Enum struct {
 type Enum struct {
 	TypeID
 	TypeID
-	Name
+	Name   string
 	Values []EnumValue
 	Values []EnumValue
 }
 }
 
 
@@ -254,11 +256,13 @@ func (e *Enum) String() string {
 	return fmt.Sprintf("enum#%d[%q]", e.TypeID, e.Name)
 	return fmt.Sprintf("enum#%d[%q]", e.TypeID, e.Name)
 }
 }
 
 
+func (e *Enum) TypeName() string { return e.Name }
+
 // EnumValue is part of an Enum
 // EnumValue is part of an Enum
 //
 //
 // Is is not a valid Type
 // Is is not a valid Type
 type EnumValue struct {
 type EnumValue struct {
-	Name
+	Name  string
 	Value int32
 	Value int32
 }
 }
 
 
@@ -294,7 +298,7 @@ func (fk FwdKind) String() string {
 // Fwd is a forward declaration of a Type.
 // Fwd is a forward declaration of a Type.
 type Fwd struct {
 type Fwd struct {
 	TypeID
 	TypeID
-	Name
+	Name string
 	Kind FwdKind
 	Kind FwdKind
 }
 }
 
 
@@ -302,6 +306,8 @@ func (f *Fwd) String() string {
 	return fmt.Sprintf("fwd#%d[%s %q]", f.TypeID, f.Kind, f.Name)
 	return fmt.Sprintf("fwd#%d[%s %q]", f.TypeID, f.Kind, f.Name)
 }
 }
 
 
+func (f *Fwd) TypeName() string { return f.Name }
+
 func (f *Fwd) walk(*typeDeque) {}
 func (f *Fwd) walk(*typeDeque) {}
 func (f *Fwd) copy() Type {
 func (f *Fwd) copy() Type {
 	cpy := *f
 	cpy := *f
@@ -311,7 +317,7 @@ func (f *Fwd) copy() Type {
 // Typedef is an alias of a Type.
 // Typedef is an alias of a Type.
 type Typedef struct {
 type Typedef struct {
 	TypeID
 	TypeID
-	Name
+	Name string
 	Type Type
 	Type Type
 }
 }
 
 
@@ -319,6 +325,8 @@ func (td *Typedef) String() string {
 	return fmt.Sprintf("typedef#%d[%q #%d]", td.TypeID, td.Name, td.Type.ID())
 	return fmt.Sprintf("typedef#%d[%q #%d]", td.TypeID, td.Name, td.Type.ID())
 }
 }
 
 
+func (td *Typedef) TypeName() string { return td.Name }
+
 func (td *Typedef) walk(tdq *typeDeque) { tdq.push(&td.Type) }
 func (td *Typedef) walk(tdq *typeDeque) { tdq.push(&td.Type) }
 func (td *Typedef) copy() Type {
 func (td *Typedef) copy() Type {
 	cpy := *td
 	cpy := *td
@@ -379,7 +387,7 @@ func (r *Restrict) copy() Type {
 // Func is a function definition.
 // Func is a function definition.
 type Func struct {
 type Func struct {
 	TypeID
 	TypeID
-	Name
+	Name    string
 	Type    Type
 	Type    Type
 	Linkage FuncLinkage
 	Linkage FuncLinkage
 }
 }
@@ -388,6 +396,8 @@ func (f *Func) String() string {
 	return fmt.Sprintf("func#%d[%s %q proto=#%d]", f.TypeID, f.Linkage, f.Name, f.Type.ID())
 	return fmt.Sprintf("func#%d[%s %q proto=#%d]", f.TypeID, f.Linkage, f.Name, f.Type.ID())
 }
 }
 
 
+func (f *Func) TypeName() string { return f.Name }
+
 func (f *Func) walk(tdq *typeDeque) { tdq.push(&f.Type) }
 func (f *Func) walk(tdq *typeDeque) { tdq.push(&f.Type) }
 func (f *Func) copy() Type {
 func (f *Func) copy() Type {
 	cpy := *f
 	cpy := *f
@@ -426,14 +436,14 @@ func (fp *FuncProto) copy() Type {
 }
 }
 
 
 type FuncParam struct {
 type FuncParam struct {
-	Name
+	Name string
 	Type Type
 	Type Type
 }
 }
 
 
 // Var is a global variable.
 // Var is a global variable.
 type Var struct {
 type Var struct {
 	TypeID
 	TypeID
-	Name
+	Name    string
 	Type    Type
 	Type    Type
 	Linkage VarLinkage
 	Linkage VarLinkage
 }
 }
@@ -442,6 +452,8 @@ func (v *Var) String() string {
 	return fmt.Sprintf("var#%d[%s %q]", v.TypeID, v.Linkage, v.Name)
 	return fmt.Sprintf("var#%d[%s %q]", v.TypeID, v.Linkage, v.Name)
 }
 }
 
 
+func (v *Var) TypeName() string { return v.Name }
+
 func (v *Var) walk(tdq *typeDeque) { tdq.push(&v.Type) }
 func (v *Var) walk(tdq *typeDeque) { tdq.push(&v.Type) }
 func (v *Var) copy() Type {
 func (v *Var) copy() Type {
 	cpy := *v
 	cpy := *v
@@ -451,7 +463,7 @@ func (v *Var) copy() Type {
 // Datasec is a global program section containing data.
 // Datasec is a global program section containing data.
 type Datasec struct {
 type Datasec struct {
 	TypeID
 	TypeID
-	Name
+	Name string
 	Size uint32
 	Size uint32
 	Vars []VarSecinfo
 	Vars []VarSecinfo
 }
 }
@@ -460,6 +472,8 @@ func (ds *Datasec) String() string {
 	return fmt.Sprintf("section#%d[%q]", ds.TypeID, ds.Name)
 	return fmt.Sprintf("section#%d[%q]", ds.TypeID, ds.Name)
 }
 }
 
 
+func (ds *Datasec) TypeName() string { return ds.Name }
+
 func (ds *Datasec) size() uint32 { return ds.Size }
 func (ds *Datasec) size() uint32 { return ds.Size }
 
 
 func (ds *Datasec) walk(tdq *typeDeque) {
 func (ds *Datasec) walk(tdq *typeDeque) {
@@ -475,7 +489,7 @@ func (ds *Datasec) copy() Type {
 	return &cpy
 	return &cpy
 }
 }
 
 
-// VarSecinfo describes variable in a Datasec
+// VarSecinfo describes variable in a Datasec.
 //
 //
 // It is not a valid Type.
 // It is not a valid Type.
 type VarSecinfo struct {
 type VarSecinfo struct {
@@ -484,6 +498,27 @@ type VarSecinfo struct {
 	Size   uint32
 	Size   uint32
 }
 }
 
 
+// Float is a float of a given length.
+type Float struct {
+	TypeID
+	Name string
+
+	// The size of the float in bytes.
+	Size uint32
+}
+
+func (f *Float) String() string {
+	return fmt.Sprintf("float%d#%d[%q]", f.Size*8, f.TypeID, f.Name)
+}
+
+func (f *Float) TypeName() string { return f.Name }
+func (f *Float) size() uint32     { return f.Size }
+func (f *Float) walk(*typeDeque)  {}
+func (f *Float) copy() Type {
+	cpy := *f
+	return &cpy
+}
+
 type sizer interface {
 type sizer interface {
 	size() uint32
 	size() uint32
 }
 }
@@ -565,14 +600,36 @@ func Sizeof(typ Type) (int, error) {
 //
 //
 // Returns any errors from transform verbatim.
 // Returns any errors from transform verbatim.
 func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
 func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
-	var (
-		copies = make(map[Type]Type)
-		work   typeDeque
-	)
+	copies := make(copier)
+	return typ, copies.copy(&typ, transform)
+}
 
 
-	for t := &typ; t != nil; t = work.pop() {
+// copy a slice of Types recursively.
+//
+// Types may form a cycle.
+//
+// Returns any errors from transform verbatim.
+func copyTypes(types []Type, transform func(Type) (Type, error)) ([]Type, error) {
+	result := make([]Type, len(types))
+	copy(result, types)
+
+	copies := make(copier)
+	for i := range result {
+		if err := copies.copy(&result[i], transform); err != nil {
+			return nil, err
+		}
+	}
+
+	return result, nil
+}
+
+type copier map[Type]Type
+
+func (c copier) copy(typ *Type, transform func(Type) (Type, error)) error {
+	var work typeDeque
+	for t := typ; t != nil; t = work.pop() {
 		// *t is the identity of the type.
 		// *t is the identity of the type.
-		if cpy := copies[*t]; cpy != nil {
+		if cpy := c[*t]; cpy != nil {
 			*t = cpy
 			*t = cpy
 			continue
 			continue
 		}
 		}
@@ -581,21 +638,21 @@ func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
 		if transform != nil {
 		if transform != nil {
 			tf, err := transform(*t)
 			tf, err := transform(*t)
 			if err != nil {
 			if err != nil {
-				return nil, fmt.Errorf("copy %s: %w", typ, err)
+				return fmt.Errorf("copy %s: %w", *t, err)
 			}
 			}
 			cpy = tf.copy()
 			cpy = tf.copy()
 		} else {
 		} else {
 			cpy = (*t).copy()
 			cpy = (*t).copy()
 		}
 		}
 
 
-		copies[*t] = cpy
+		c[*t] = cpy
 		*t = cpy
 		*t = cpy
 
 
 		// Mark any nested types for copying.
 		// Mark any nested types for copying.
 		cpy.walk(&work)
 		cpy.walk(&work)
 	}
 	}
 
 
-	return typ, nil
+	return nil
 }
 }
 
 
 // typeDeque keeps track of pointers to types which still
 // typeDeque keeps track of pointers to types which still
@@ -606,6 +663,10 @@ type typeDeque struct {
 	mask        uint64
 	mask        uint64
 }
 }
 
 
+func (dq *typeDeque) empty() bool {
+	return dq.read == dq.write
+}
+
 // push adds a type to the stack.
 // push adds a type to the stack.
 func (dq *typeDeque) push(t *Type) {
 func (dq *typeDeque) push(t *Type) {
 	if dq.write-dq.read < uint64(len(dq.types)) {
 	if dq.write-dq.read < uint64(len(dq.types)) {
@@ -632,7 +693,7 @@ func (dq *typeDeque) push(t *Type) {
 
 
 // shift returns the first element or null.
 // shift returns the first element or null.
 func (dq *typeDeque) shift() *Type {
 func (dq *typeDeque) shift() *Type {
-	if dq.read == dq.write {
+	if dq.empty() {
 		return nil
 		return nil
 	}
 	}
 
 
@@ -645,7 +706,7 @@ func (dq *typeDeque) shift() *Type {
 
 
 // pop returns the last element or null.
 // pop returns the last element or null.
 func (dq *typeDeque) pop() *Type {
 func (dq *typeDeque) pop() *Type {
-	if dq.read == dq.write {
+	if dq.empty() {
 		return nil
 		return nil
 	}
 	}
 
 
@@ -674,7 +735,7 @@ func (dq *typeDeque) all() []*Type {
 // Returns a map of named types (so, where NameOff is non-zero) and a slice of types
 // Returns a map of named types (so, where NameOff is non-zero) and a slice of types
 // indexed by TypeID. Since BTF ignores compilation units, multiple types may share
 // indexed by TypeID. Since BTF ignores compilation units, multiple types may share
 // the same name. A Type may form a cyclic graph by pointing at itself.
 // the same name. A Type may form a cyclic graph by pointing at itself.
-func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, namedTypes map[string][]namedType, err error) {
+func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, namedTypes map[string][]NamedType, err error) {
 	type fixupDef struct {
 	type fixupDef struct {
 		id           TypeID
 		id           TypeID
 		expectedKind btfKind
 		expectedKind btfKind
@@ -691,17 +752,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
 		// work, since otherwise append might re-allocate members.
 		// work, since otherwise append might re-allocate members.
 		members := make([]Member, 0, len(raw))
 		members := make([]Member, 0, len(raw))
 		for i, btfMember := range raw {
 		for i, btfMember := range raw {
-			name, err := rawStrings.LookupName(btfMember.NameOff)
+			name, err := rawStrings.Lookup(btfMember.NameOff)
 			if err != nil {
 			if err != nil {
 				return nil, fmt.Errorf("can't get name for member %d: %w", i, err)
 				return nil, fmt.Errorf("can't get name for member %d: %w", i, err)
 			}
 			}
 			m := Member{
 			m := Member{
-				Name:   name,
-				Offset: btfMember.Offset,
+				Name:       name,
+				OffsetBits: btfMember.Offset,
 			}
 			}
 			if kindFlag {
 			if kindFlag {
 				m.BitfieldSize = btfMember.Offset >> 24
 				m.BitfieldSize = btfMember.Offset >> 24
-				m.Offset &= 0xffffff
+				m.OffsetBits &= 0xffffff
 			}
 			}
 			members = append(members, m)
 			members = append(members, m)
 		}
 		}
@@ -713,7 +774,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
 
 
 	types = make([]Type, 0, len(rawTypes))
 	types = make([]Type, 0, len(rawTypes))
 	types = append(types, (*Void)(nil))
 	types = append(types, (*Void)(nil))
-	namedTypes = make(map[string][]namedType)
+	namedTypes = make(map[string][]NamedType)
 
 
 	for i, raw := range rawTypes {
 	for i, raw := range rawTypes {
 		var (
 		var (
@@ -723,7 +784,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
 			typ Type
 			typ Type
 		)
 		)
 
 
-		name, err := rawStrings.LookupName(raw.NameOff)
+		name, err := rawStrings.Lookup(raw.NameOff)
 		if err != nil {
 		if err != nil {
 			return nil, nil, fmt.Errorf("get name for type id %d: %w", id, err)
 			return nil, nil, fmt.Errorf("get name for type id %d: %w", id, err)
 		}
 		}
@@ -765,7 +826,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
 			rawvals := raw.data.([]btfEnum)
 			rawvals := raw.data.([]btfEnum)
 			vals := make([]EnumValue, 0, len(rawvals))
 			vals := make([]EnumValue, 0, len(rawvals))
 			for i, btfVal := range rawvals {
 			for i, btfVal := range rawvals {
-				name, err := rawStrings.LookupName(btfVal.NameOff)
+				name, err := rawStrings.Lookup(btfVal.NameOff)
 				if err != nil {
 				if err != nil {
 					return nil, nil, fmt.Errorf("get name for enum value %d: %s", i, err)
 					return nil, nil, fmt.Errorf("get name for enum value %d: %s", i, err)
 				}
 				}
@@ -812,7 +873,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
 			rawparams := raw.data.([]btfParam)
 			rawparams := raw.data.([]btfParam)
 			params := make([]FuncParam, 0, len(rawparams))
 			params := make([]FuncParam, 0, len(rawparams))
 			for i, param := range rawparams {
 			for i, param := range rawparams {
-				name, err := rawStrings.LookupName(param.NameOff)
+				name, err := rawStrings.Lookup(param.NameOff)
 				if err != nil {
 				if err != nil {
 					return nil, nil, fmt.Errorf("get name for func proto parameter %d: %s", i, err)
 					return nil, nil, fmt.Errorf("get name for func proto parameter %d: %s", i, err)
 				}
 				}
@@ -848,14 +909,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
 			}
 			}
 			typ = &Datasec{id, name, raw.SizeType, vars}
 			typ = &Datasec{id, name, raw.SizeType, vars}
 
 
+		case kindFloat:
+			typ = &Float{id, name, raw.Size()}
+
 		default:
 		default:
 			return nil, nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
 			return nil, nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
 		}
 		}
 
 
 		types = append(types, typ)
 		types = append(types, typ)
 
 
-		if named, ok := typ.(namedType); ok {
-			if name := essentialName(named.name()); name != "" {
+		if named, ok := typ.(NamedType); ok {
+			if name := essentialName(named.TypeName()); name != "" {
 				namedTypes[name] = append(namedTypes[name], named)
 				namedTypes[name] = append(namedTypes[name], named)
 			}
 			}
 		}
 		}

+ 2 - 2
vendor/github.com/cilium/ebpf/internal/cpu.go

@@ -2,7 +2,7 @@ package internal
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"io/ioutil"
+	"os"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 )
 )
@@ -24,7 +24,7 @@ func PossibleCPUs() (int, error) {
 }
 }
 
 
 func parseCPUsFromFile(path string) (int, error) {
 func parseCPUsFromFile(path string) (int, error) {
-	spec, err := ioutil.ReadFile(path)
+	spec, err := os.ReadFile(path)
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}

+ 1 - 0
vendor/github.com/cilium/ebpf/internal/ptr_32_be.go

@@ -1,3 +1,4 @@
+//go:build armbe || mips || mips64p32
 // +build armbe mips mips64p32
 // +build armbe mips mips64p32
 
 
 package internal
 package internal

+ 1 - 0
vendor/github.com/cilium/ebpf/internal/ptr_32_le.go

@@ -1,3 +1,4 @@
+//go:build 386 || amd64p32 || arm || mipsle || mips64p32le
 // +build 386 amd64p32 arm mipsle mips64p32le
 // +build 386 amd64p32 arm mipsle mips64p32le
 
 
 package internal
 package internal

+ 2 - 2
vendor/github.com/cilium/ebpf/internal/ptr_64.go

@@ -1,5 +1,5 @@
-// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le
-// +build !armbe,!mips,!mips64p32
+//go:build !386 && !amd64p32 && !arm && !mipsle && !mips64p32le && !armbe && !mips && !mips64p32
+// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le,!armbe,!mips,!mips64p32
 
 
 package internal
 package internal
 
 

+ 59 - 0
vendor/github.com/cilium/ebpf/internal/syscall.go

@@ -1,6 +1,7 @@
 package internal
 package internal
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"path/filepath"
 	"path/filepath"
 	"runtime"
 	"runtime"
@@ -68,6 +69,48 @@ func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
 	return r1, err
 	return r1, err
 }
 }
 
 
+type BPFProgLoadAttr struct {
+	ProgType           uint32
+	InsCount           uint32
+	Instructions       Pointer
+	License            Pointer
+	LogLevel           uint32
+	LogSize            uint32
+	LogBuf             Pointer
+	KernelVersion      uint32     // since 4.1  2541517c32be
+	ProgFlags          uint32     // since 4.11 e07b98d9bffe
+	ProgName           BPFObjName // since 4.15 067cae47771c
+	ProgIfIndex        uint32     // since 4.15 1f6f4cb7ba21
+	ExpectedAttachType uint32     // since 4.17 5e43f899b03a
+	ProgBTFFd          uint32
+	FuncInfoRecSize    uint32
+	FuncInfo           Pointer
+	FuncInfoCnt        uint32
+	LineInfoRecSize    uint32
+	LineInfo           Pointer
+	LineInfoCnt        uint32
+	AttachBTFID        uint32
+	AttachProgFd       uint32
+}
+
+// BPFProgLoad wraps BPF_PROG_LOAD.
+func BPFProgLoad(attr *BPFProgLoadAttr) (*FD, error) {
+	for {
+		fd, err := BPF(BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
+		// As of ~4.20 the verifier can be interrupted by a signal,
+		// and returns EAGAIN in that case.
+		if errors.Is(err, unix.EAGAIN) {
+			continue
+		}
+
+		if err != nil {
+			return nil, err
+		}
+
+		return NewFD(uint32(fd)), nil
+	}
+}
+
 type BPFProgAttachAttr struct {
 type BPFProgAttachAttr struct {
 	TargetFd     uint32
 	TargetFd     uint32
 	AttachBpfFd  uint32
 	AttachBpfFd  uint32
@@ -180,6 +223,22 @@ func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error {
 	return nil
 	return nil
 }
 }
 
 
+type bpfGetFDByIDAttr struct {
+	id   uint32
+	next uint32
+}
+
+// BPFObjGetInfoByFD wraps BPF_*_GET_FD_BY_ID.
+//
+// Available from 4.13.
+func BPFObjGetFDByID(cmd BPFCmd, id uint32) (*FD, error) {
+	attr := bpfGetFDByIDAttr{
+		id: id,
+	}
+	ptr, err := BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
+	return NewFD(uint32(ptr)), err
+}
+
 // BPFObjName is a null-terminated string made up of
 // BPFObjName is a null-terminated string made up of
 // 'A-Za-z0-9_' characters.
 // 'A-Za-z0-9_' characters.
 type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte
 type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte

+ 10 - 6
vendor/github.com/cilium/ebpf/internal/unix/types_linux.go

@@ -1,3 +1,4 @@
+//go:build linux
 // +build linux
 // +build linux
 
 
 package unix
 package unix
@@ -20,10 +21,11 @@ const (
 	EPERM   = linux.EPERM
 	EPERM   = linux.EPERM
 	ESRCH   = linux.ESRCH
 	ESRCH   = linux.ESRCH
 	ENODEV  = linux.ENODEV
 	ENODEV  = linux.ENODEV
+	EBADF   = linux.EBADF
+	E2BIG   = linux.E2BIG
 	// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
 	// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
 	ENOTSUPP = syscall.Errno(0x20c)
 	ENOTSUPP = syscall.Errno(0x20c)
 
 
-	EBADF                    = linux.EBADF
 	BPF_F_NO_PREALLOC        = linux.BPF_F_NO_PREALLOC
 	BPF_F_NO_PREALLOC        = linux.BPF_F_NO_PREALLOC
 	BPF_F_NUMA_NODE          = linux.BPF_F_NUMA_NODE
 	BPF_F_NUMA_NODE          = linux.BPF_F_NUMA_NODE
 	BPF_F_RDONLY             = linux.BPF_F_RDONLY
 	BPF_F_RDONLY             = linux.BPF_F_RDONLY
@@ -35,6 +37,9 @@ const (
 	BPF_F_INNER_MAP          = linux.BPF_F_INNER_MAP
 	BPF_F_INNER_MAP          = linux.BPF_F_INNER_MAP
 	BPF_OBJ_NAME_LEN         = linux.BPF_OBJ_NAME_LEN
 	BPF_OBJ_NAME_LEN         = linux.BPF_OBJ_NAME_LEN
 	BPF_TAG_SIZE             = linux.BPF_TAG_SIZE
 	BPF_TAG_SIZE             = linux.BPF_TAG_SIZE
+	BPF_RINGBUF_BUSY_BIT     = linux.BPF_RINGBUF_BUSY_BIT
+	BPF_RINGBUF_DISCARD_BIT  = linux.BPF_RINGBUF_DISCARD_BIT
+	BPF_RINGBUF_HDR_SZ       = linux.BPF_RINGBUF_HDR_SZ
 	SYS_BPF                  = linux.SYS_BPF
 	SYS_BPF                  = linux.SYS_BPF
 	F_DUPFD_CLOEXEC          = linux.F_DUPFD_CLOEXEC
 	F_DUPFD_CLOEXEC          = linux.F_DUPFD_CLOEXEC
 	EPOLL_CTL_ADD            = linux.EPOLL_CTL_ADD
 	EPOLL_CTL_ADD            = linux.EPOLL_CTL_ADD
@@ -69,11 +74,6 @@ type Statfs_t = linux.Statfs_t
 // Rlimit is a wrapper
 // Rlimit is a wrapper
 type Rlimit = linux.Rlimit
 type Rlimit = linux.Rlimit
 
 
-// Setrlimit is a wrapper
-func Setrlimit(resource int, rlim *Rlimit) (err error) {
-	return linux.Setrlimit(resource, rlim)
-}
-
 // Syscall is a wrapper
 // Syscall is a wrapper
 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
 	return linux.Syscall(trap, a1, a2, a3)
 	return linux.Syscall(trap, a1, a2, a3)
@@ -202,3 +202,7 @@ func KernelRelease() (string, error) {
 	release := string(uname.Release[:end])
 	release := string(uname.Release[:end])
 	return release, nil
 	return release, nil
 }
 }
+
+func Prlimit(pid, resource int, new, old *Rlimit) error {
+	return linux.Prlimit(pid, resource, new, old)
+}

+ 9 - 5
vendor/github.com/cilium/ebpf/internal/unix/types_other.go

@@ -1,3 +1,4 @@
+//go:build !linux
 // +build !linux
 // +build !linux
 
 
 package unix
 package unix
@@ -21,6 +22,7 @@ const (
 	ESRCH  = syscall.ESRCH
 	ESRCH  = syscall.ESRCH
 	ENODEV = syscall.ENODEV
 	ENODEV = syscall.ENODEV
 	EBADF  = syscall.Errno(0)
 	EBADF  = syscall.Errno(0)
+	E2BIG  = syscall.Errno(0)
 	// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
 	// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
 	ENOTSUPP = syscall.Errno(0x20c)
 	ENOTSUPP = syscall.Errno(0x20c)
 
 
@@ -35,6 +37,9 @@ const (
 	BPF_F_INNER_MAP          = 0
 	BPF_F_INNER_MAP          = 0
 	BPF_OBJ_NAME_LEN         = 0x10
 	BPF_OBJ_NAME_LEN         = 0x10
 	BPF_TAG_SIZE             = 0x8
 	BPF_TAG_SIZE             = 0x8
+	BPF_RINGBUF_BUSY_BIT     = 0
+	BPF_RINGBUF_DISCARD_BIT  = 0
+	BPF_RINGBUF_HDR_SZ       = 0
 	SYS_BPF                  = 321
 	SYS_BPF                  = 321
 	F_DUPFD_CLOEXEC          = 0x406
 	F_DUPFD_CLOEXEC          = 0x406
 	EPOLLIN                  = 0x1
 	EPOLLIN                  = 0x1
@@ -86,11 +91,6 @@ type Rlimit struct {
 	Max uint64
 	Max uint64
 }
 }
 
 
-// Setrlimit is a wrapper
-func Setrlimit(resource int, rlim *Rlimit) (err error) {
-	return errNonLinux
-}
-
 // Syscall is a wrapper
 // Syscall is a wrapper
 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
 	return 0, 0, syscall.Errno(1)
 	return 0, 0, syscall.Errno(1)
@@ -261,3 +261,7 @@ func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags
 func KernelRelease() (string, error) {
 func KernelRelease() (string, error) {
 	return "", errNonLinux
 	return "", errNonLinux
 }
 }
+
+func Prlimit(pid, resource int, new, old *Rlimit) error {
+	return errNonLinux
+}

+ 2 - 2
vendor/github.com/cilium/ebpf/internal/version.go

@@ -2,7 +2,7 @@ package internal
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"io/ioutil"
+	"os"
 	"regexp"
 	"regexp"
 	"sync"
 	"sync"
 
 
@@ -109,7 +109,7 @@ func detectKernelVersion() (Version, error) {
 	// Example format: Ubuntu 4.15.0-91.92-generic 4.15.18
 	// Example format: Ubuntu 4.15.0-91.92-generic 4.15.18
 	// This method exists in the kernel itself, see d18acd15c
 	// This method exists in the kernel itself, see d18acd15c
 	// ("perf tools: Fix kernel version error in ubuntu").
 	// ("perf tools: Fix kernel version error in ubuntu").
-	if pvs, err := ioutil.ReadFile("/proc/version_signature"); err == nil {
+	if pvs, err := os.ReadFile("/proc/version_signature"); err == nil {
 		// If /proc/version_signature exists, failing to parse it is an error.
 		// If /proc/version_signature exists, failing to parse it is an error.
 		// It only exists on Ubuntu, where the real patch level is not obtainable
 		// It only exists on Ubuntu, where the real patch level is not obtainable
 		// through any other method.
 		// through any other method.

+ 88 - 0
vendor/github.com/cilium/ebpf/link/freplace.go

@@ -0,0 +1,88 @@
+package link
+
+import (
+	"fmt"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/internal/btf"
+)
+
+type FreplaceLink struct {
+	RawLink
+}
+
+// AttachFreplace attaches the given eBPF program to the function it replaces.
+//
+// The program and name can either be provided at link time, or can be provided
+// at program load time. If they were provided at load time, they should be nil
+// and empty respectively here, as they will be ignored by the kernel.
+// Examples:
+//
+//	AttachFreplace(dispatcher, "function", replacement)
+//	AttachFreplace(nil, "", replacement)
+func AttachFreplace(targetProg *ebpf.Program, name string, prog *ebpf.Program) (*FreplaceLink, error) {
+	if (name == "") != (targetProg == nil) {
+		return nil, fmt.Errorf("must provide both or neither of name and targetProg: %w", errInvalidInput)
+	}
+	if prog == nil {
+		return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
+	}
+	if prog.Type() != ebpf.Extension {
+		return nil, fmt.Errorf("eBPF program type %s is not an Extension: %w", prog.Type(), errInvalidInput)
+	}
+
+	var (
+		target int
+		typeID btf.TypeID
+	)
+	if targetProg != nil {
+		info, err := targetProg.Info()
+		if err != nil {
+			return nil, err
+		}
+		btfID, ok := info.BTFID()
+		if !ok {
+			return nil, fmt.Errorf("could not get BTF ID for program %s: %w", info.Name, errInvalidInput)
+		}
+		btfHandle, err := btf.NewHandleFromID(btfID)
+		if err != nil {
+			return nil, err
+		}
+		defer btfHandle.Close()
+
+		var function *btf.Func
+		if err := btfHandle.Spec().FindType(name, &function); err != nil {
+			return nil, err
+		}
+
+		target = targetProg.FD()
+		typeID = function.ID()
+	}
+
+	link, err := AttachRawLink(RawLinkOptions{
+		Target:  target,
+		Program: prog,
+		Attach:  ebpf.AttachNone,
+		BTF:     typeID,
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return &FreplaceLink{*link}, nil
+}
+
+// Update implements the Link interface.
+func (f *FreplaceLink) Update(new *ebpf.Program) error {
+	return fmt.Errorf("freplace update: %w", ErrNotSupported)
+}
+
+// LoadPinnedFreplace loads a pinned iterator from a bpffs.
+func LoadPinnedFreplace(fileName string, opts *ebpf.LoadPinOptions) (*FreplaceLink, error) {
+	link, err := LoadPinnedRawLink(fileName, TracingType, opts)
+	if err != nil {
+		return nil, err
+	}
+
+	return &FreplaceLink{*link}, err
+}

+ 22 - 16
vendor/github.com/cilium/ebpf/link/kprobe.go

@@ -5,7 +5,6 @@ import (
 	"crypto/rand"
 	"crypto/rand"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"runtime"
 	"runtime"
@@ -72,10 +71,11 @@ func (pt probeType) RetprobeBit() (uint64, error) {
 // given kernel symbol starts executing. See /proc/kallsyms for available
 // given kernel symbol starts executing. See /proc/kallsyms for available
 // symbols. For example, printk():
 // symbols. For example, printk():
 //
 //
-//	Kprobe("printk", prog)
+//	kp, err := Kprobe("printk", prog)
 //
 //
-// The resulting Link must be Closed during program shutdown to avoid leaking
-// system resources.
+// Losing the reference to the resulting Link (kp) will close the Kprobe
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
 func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
 func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
 	k, err := kprobe(symbol, prog, false)
 	k, err := kprobe(symbol, prog, false)
 	if err != nil {
 	if err != nil {
@@ -95,10 +95,11 @@ func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
 // before the given kernel symbol exits, with the function stack left intact.
 // before the given kernel symbol exits, with the function stack left intact.
 // See /proc/kallsyms for available symbols. For example, printk():
 // See /proc/kallsyms for available symbols. For example, printk():
 //
 //
-//	Kretprobe("printk", prog)
+//	kp, err := Kretprobe("printk", prog)
 //
 //
-// The resulting Link must be Closed during program shutdown to avoid leaking
-// system resources.
+// Losing the reference to the resulting Link (kp) will close the Kretprobe
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
 func Kretprobe(symbol string, prog *ebpf.Program) (Link, error) {
 func Kretprobe(symbol string, prog *ebpf.Program) (Link, error) {
 	k, err := kprobe(symbol, prog, true)
 	k, err := kprobe(symbol, prog, true)
 	if err != nil {
 	if err != nil {
@@ -157,7 +158,7 @@ func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) {
 // pmuKprobe opens a perf event based on the kprobe PMU.
 // pmuKprobe opens a perf event based on the kprobe PMU.
 // Returns os.ErrNotExist if the given symbol does not exist in the kernel.
 // Returns os.ErrNotExist if the given symbol does not exist in the kernel.
 func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
 func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
-	return pmuProbe(kprobeType, symbol, "", 0, ret)
+	return pmuProbe(kprobeType, symbol, "", 0, perfAllThreads, ret)
 }
 }
 
 
 // pmuProbe opens a perf event based on a Performance Monitoring Unit.
 // pmuProbe opens a perf event based on a Performance Monitoring Unit.
@@ -167,7 +168,7 @@ func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
 // 33ea4b24277b "perf/core: Implement the 'perf_uprobe' PMU"
 // 33ea4b24277b "perf/core: Implement the 'perf_uprobe' PMU"
 //
 //
 // Returns ErrNotSupported if the kernel doesn't support perf_[k,u]probe PMU
 // Returns ErrNotSupported if the kernel doesn't support perf_[k,u]probe PMU
-func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
+func pmuProbe(typ probeType, symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
 	// Getting the PMU type will fail if the kernel doesn't support
 	// Getting the PMU type will fail if the kernel doesn't support
 	// the perf_[k,u]probe PMU.
 	// the perf_[k,u]probe PMU.
 	et, err := getPMUEventType(typ)
 	et, err := getPMUEventType(typ)
@@ -191,7 +192,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
 	switch typ {
 	switch typ {
 	case kprobeType:
 	case kprobeType:
 		// Create a pointer to a NUL-terminated string for the kernel.
 		// Create a pointer to a NUL-terminated string for the kernel.
-		sp, err := unsafeStringPtr(symbol)
+		sp, err = unsafeStringPtr(symbol)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -202,7 +203,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
 			Config: config,              // Retprobe flag
 			Config: config,              // Retprobe flag
 		}
 		}
 	case uprobeType:
 	case uprobeType:
-		sp, err := unsafeStringPtr(path)
+		sp, err = unsafeStringPtr(path)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -220,7 +221,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
 		}
 		}
 	}
 	}
 
 
-	fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
+	fd, err := unix.PerfEventOpen(&attr, pid, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
 
 
 	// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
 	// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
 	// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
 	// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
@@ -228,6 +229,11 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
 	if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
 	if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
 		return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, os.ErrNotExist)
 		return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, os.ErrNotExist)
 	}
 	}
+	// Since at least commit cb9a19fe4aa51, ENOTSUPP is returned
+	// when attempting to set a uprobe on a trap instruction.
+	if errors.Is(err, unix.ENOTSUPP) {
+		return nil, fmt.Errorf("failed setting uprobe on offset %#x (possible trap insn): %w", offset, err)
+	}
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("opening perf event: %w", err)
 		return nil, fmt.Errorf("opening perf event: %w", err)
 	}
 	}
@@ -246,7 +252,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
 
 
 // tracefsKprobe creates a Kprobe tracefs entry.
 // tracefsKprobe creates a Kprobe tracefs entry.
 func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
 func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
-	return tracefsProbe(kprobeType, symbol, "", 0, ret)
+	return tracefsProbe(kprobeType, symbol, "", 0, perfAllThreads, ret)
 }
 }
 
 
 // tracefsProbe creates a trace event by writing an entry to <tracefs>/[k,u]probe_events.
 // tracefsProbe creates a trace event by writing an entry to <tracefs>/[k,u]probe_events.
@@ -255,7 +261,7 @@ func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
 // Path and offset are only set in the case of uprobe(s) and are used to set
 // 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.
 // 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.
 // A perf event is then opened on the newly-created trace event and returned to the caller.
-func tracefsProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
+func tracefsProbe(typ probeType, symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
 	// Generate a random string for each trace event we attempt to create.
 	// 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
 	// This value is used as the 'group' token in tracefs to allow creating
 	// multiple kprobe trace events with the same name.
 	// multiple kprobe trace events with the same name.
@@ -288,7 +294,7 @@ func tracefsProbe(typ probeType, symbol, path string, offset uint64, ret bool) (
 	}
 	}
 
 
 	// Kprobes are ephemeral tracepoints and share the same perf event type.
 	// Kprobes are ephemeral tracepoints and share the same perf event type.
-	fd, err := openTracepointPerfEvent(tid)
+	fd, err := openTracepointPerfEvent(tid, pid)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -413,7 +419,7 @@ func probePrefix(ret bool) string {
 func determineRetprobeBit(typ probeType) (uint64, error) {
 func determineRetprobeBit(typ probeType) (uint64, error) {
 	p := filepath.Join("/sys/bus/event_source/devices/", typ.String(), "/format/retprobe")
 	p := filepath.Join("/sys/bus/event_source/devices/", typ.String(), "/format/retprobe")
 
 
-	data, err := ioutil.ReadFile(p)
+	data, err := os.ReadFile(p)
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}

+ 9 - 5
vendor/github.com/cilium/ebpf/link/link.go

@@ -6,6 +6,7 @@ import (
 
 
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf/internal"
 	"github.com/cilium/ebpf/internal"
+	"github.com/cilium/ebpf/internal/btf"
 )
 )
 
 
 var ErrNotSupported = internal.ErrNotSupported
 var ErrNotSupported = internal.ErrNotSupported
@@ -29,8 +30,8 @@ type Link interface {
 
 
 	// Close frees resources.
 	// Close frees resources.
 	//
 	//
-	// The link will be broken unless it has been pinned. A link
-	// may continue past the lifetime of the process if Close is
+	// The link will be broken unless it has been successfully pinned.
+	// A link may continue past the lifetime of the process if Close is
 	// not called.
 	// not called.
 	Close() error
 	Close() error
 
 
@@ -49,6 +50,8 @@ type RawLinkOptions struct {
 	Program *ebpf.Program
 	Program *ebpf.Program
 	// Attach must match the attach type of Program.
 	// Attach must match the attach type of Program.
 	Attach ebpf.AttachType
 	Attach ebpf.AttachType
+	// BTF is the BTF of the attachment target.
+	BTF btf.TypeID
 }
 }
 
 
 // RawLinkInfo contains metadata on a link.
 // RawLinkInfo contains metadata on a link.
@@ -83,9 +86,10 @@ func AttachRawLink(opts RawLinkOptions) (*RawLink, error) {
 	}
 	}
 
 
 	attr := bpfLinkCreateAttr{
 	attr := bpfLinkCreateAttr{
-		targetFd:   uint32(opts.Target),
-		progFd:     uint32(progFd),
-		attachType: opts.Attach,
+		targetFd:    uint32(opts.Target),
+		progFd:      uint32(progFd),
+		attachType:  opts.Attach,
+		targetBTFID: uint32(opts.BTF),
 	}
 	}
 	fd, err := bpfLinkCreate(&attr)
 	fd, err := bpfLinkCreate(&attr)
 	if err != nil {
 	if err != nil {

+ 3 - 4
vendor/github.com/cilium/ebpf/link/perf_event.go

@@ -4,7 +4,6 @@ import (
 	"bytes"
 	"bytes"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"regexp"
 	"regexp"
@@ -236,7 +235,7 @@ func getPMUEventType(typ probeType) (uint64, error) {
 // openTracepointPerfEvent opens a tracepoint-type perf event. System-wide
 // openTracepointPerfEvent opens a tracepoint-type perf event. System-wide
 // [k,u]probes created by writing to <tracefs>/[k,u]probe_events are tracepoints
 // [k,u]probes created by writing to <tracefs>/[k,u]probe_events are tracepoints
 // behind the scenes, and can be attached to using these perf events.
 // behind the scenes, and can be attached to using these perf events.
-func openTracepointPerfEvent(tid uint64) (*internal.FD, error) {
+func openTracepointPerfEvent(tid uint64, pid int) (*internal.FD, error) {
 	attr := unix.PerfEventAttr{
 	attr := unix.PerfEventAttr{
 		Type:        unix.PERF_TYPE_TRACEPOINT,
 		Type:        unix.PERF_TYPE_TRACEPOINT,
 		Config:      tid,
 		Config:      tid,
@@ -245,7 +244,7 @@ func openTracepointPerfEvent(tid uint64) (*internal.FD, error) {
 		Wakeup:      1,
 		Wakeup:      1,
 	}
 	}
 
 
-	fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
+	fd, err := unix.PerfEventOpen(&attr, pid, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("opening tracepoint perf event: %w", err)
 		return nil, fmt.Errorf("opening tracepoint perf event: %w", err)
 	}
 	}
@@ -263,7 +262,7 @@ func uint64FromFile(base string, path ...string) (uint64, error) {
 		return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput)
 		return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput)
 	}
 	}
 
 
-	data, err := ioutil.ReadFile(p)
+	data, err := os.ReadFile(p)
 	if err != nil {
 	if err != nil {
 		return 0, fmt.Errorf("reading file %s: %w", p, err)
 		return 0, fmt.Errorf("reading file %s: %w", p, err)
 	}
 	}

+ 5 - 4
vendor/github.com/cilium/ebpf/link/syscalls.go

@@ -88,10 +88,11 @@ var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replace
 })
 })
 
 
 type bpfLinkCreateAttr struct {
 type bpfLinkCreateAttr struct {
-	progFd     uint32
-	targetFd   uint32
-	attachType ebpf.AttachType
-	flags      uint32
+	progFd      uint32
+	targetFd    uint32
+	attachType  ebpf.AttachType
+	flags       uint32
+	targetBTFID uint32
 }
 }
 
 
 func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {
 func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {

+ 6 - 2
vendor/github.com/cilium/ebpf/link/tracepoint.go

@@ -11,7 +11,11 @@ import (
 // tracepoints. The top-level directory is the group, the event's subdirectory
 // tracepoints. The top-level directory is the group, the event's subdirectory
 // is the name. Example:
 // is the name. Example:
 //
 //
-//	Tracepoint("syscalls", "sys_enter_fork", prog)
+//	tp, err := Tracepoint("syscalls", "sys_enter_fork", prog)
+//
+// Losing the reference to the resulting Link (tp) will close the Tracepoint
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
 //
 //
 // Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is
 // Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is
 // only possible as of kernel 4.14 (commit cf5f5ce).
 // only possible as of kernel 4.14 (commit cf5f5ce).
@@ -34,7 +38,7 @@ func Tracepoint(group, name string, prog *ebpf.Program) (Link, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	fd, err := openTracepointPerfEvent(tid)
+	fd, err := openTracepointPerfEvent(tid, perfAllThreads)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 92 - 41
vendor/github.com/cilium/ebpf/link/uprobe.go

@@ -25,14 +25,18 @@ var (
 		value uint64
 		value uint64
 		err   error
 		err   error
 	}{}
 	}{}
+
+	// ErrNoSymbol indicates that the given symbol was not found
+	// in the ELF symbols table.
+	ErrNoSymbol = errors.New("not found")
 )
 )
 
 
 // Executable defines an executable program on the filesystem.
 // Executable defines an executable program on the filesystem.
 type Executable struct {
 type Executable struct {
 	// Path of the executable on the filesystem.
 	// Path of the executable on the filesystem.
 	path string
 	path string
-	// Parsed ELF symbols and dynamic symbols.
-	symbols map[string]elf.Symbol
+	// Parsed ELF symbols and dynamic symbols offsets.
+	offsets map[string]uint64
 }
 }
 
 
 // UprobeOptions defines additional parameters that will be used
 // UprobeOptions defines additional parameters that will be used
@@ -41,6 +45,9 @@ type UprobeOptions struct {
 	// Symbol offset. Must be provided in case of external symbols (shared libs).
 	// Symbol offset. Must be provided in case of external symbols (shared libs).
 	// If set, overrides the offset eventually parsed from the executable.
 	// If set, overrides the offset eventually parsed from the executable.
 	Offset uint64
 	Offset uint64
+	// Only set the uprobe on the given process ID. Useful when tracing
+	// shared library calls or programs that have many running instances.
+	PID int
 }
 }
 
 
 // To open a new Executable, use:
 // To open a new Executable, use:
@@ -64,42 +71,84 @@ func OpenExecutable(path string) (*Executable, error) {
 		return nil, fmt.Errorf("parse ELF file: %w", err)
 		return nil, fmt.Errorf("parse ELF file: %w", err)
 	}
 	}
 
 
-	var ex = Executable{
-		path:    path,
-		symbols: make(map[string]elf.Symbol),
+	if se.Type != elf.ET_EXEC && se.Type != elf.ET_DYN {
+		// ELF is not an executable or a shared object.
+		return nil, errors.New("the given file is not an executable or a shared object")
 	}
 	}
-	if err := ex.addSymbols(se.Symbols); err != nil {
-		return nil, err
+
+	ex := Executable{
+		path:    path,
+		offsets: make(map[string]uint64),
 	}
 	}
 
 
-	if err := ex.addSymbols(se.DynamicSymbols); err != nil {
+	if err := ex.load(se); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
 	return &ex, nil
 	return &ex, nil
 }
 }
 
 
-func (ex *Executable) addSymbols(f func() ([]elf.Symbol, error)) error {
-	// elf.Symbols and elf.DynamicSymbols return ErrNoSymbols if the section is not found.
-	syms, err := f()
+func (ex *Executable) load(f *internal.SafeELFFile) error {
+	syms, err := f.Symbols()
 	if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
 	if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
 		return err
 		return err
 	}
 	}
+
+	dynsyms, err := f.DynamicSymbols()
+	if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
+		return err
+	}
+
+	syms = append(syms, dynsyms...)
+
 	for _, s := range syms {
 	for _, s := range syms {
 		if elf.ST_TYPE(s.Info) != elf.STT_FUNC {
 		if elf.ST_TYPE(s.Info) != elf.STT_FUNC {
 			// Symbol not associated with a function or other executable code.
 			// Symbol not associated with a function or other executable code.
 			continue
 			continue
 		}
 		}
-		ex.symbols[s.Name] = s
+
+		off := s.Value
+
+		// Loop over ELF segments.
+		for _, prog := range f.Progs {
+			// Skip uninteresting segments.
+			if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 {
+				continue
+			}
+
+			if prog.Vaddr <= s.Value && s.Value < (prog.Vaddr+prog.Memsz) {
+				// If the symbol value is contained in the segment, calculate
+				// the symbol offset.
+				//
+				// fn symbol offset = fn symbol VA - .text VA + .text offset
+				//
+				// stackoverflow.com/a/40249502
+				off = s.Value - prog.Vaddr + prog.Off
+				break
+			}
+		}
+
+		ex.offsets[s.Name] = off
 	}
 	}
+
 	return nil
 	return nil
 }
 }
 
 
-func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) {
-	if s, ok := ex.symbols[symbol]; ok {
-		return &s, nil
+func (ex *Executable) offset(symbol string) (uint64, error) {
+	if off, ok := ex.offsets[symbol]; ok {
+		// Symbols with location 0 from section undef are shared library calls and
+		// are relocated before the binary is executed. Dynamic linking is not
+		// implemented by the library, so mark this as unsupported for now.
+		//
+		// Since only offset values are stored and not elf.Symbol, if the value is 0,
+		// assume it's an external symbol.
+		if off == 0 {
+			return 0, fmt.Errorf("cannot resolve %s library call '%s', "+
+				"consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported)
+		}
+		return off, nil
 	}
 	}
-	return nil, fmt.Errorf("symbol %s not found", symbol)
+	return 0, fmt.Errorf("symbol %s: %w", symbol, ErrNoSymbol)
 }
 }
 
 
 // Uprobe attaches the given eBPF program to a perf event that fires when the
 // Uprobe attaches the given eBPF program to a perf event that fires when the
@@ -112,11 +161,14 @@ func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) {
 // When using symbols which belongs to shared libraries,
 // When using symbols which belongs to shared libraries,
 // an offset must be provided via options:
 // an offset must be provided via options:
 //
 //
-//  ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
+//	up, err := ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
+//
+// Losing the reference to the resulting Link (up) will close the Uprobe
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
 //
 //
-// The resulting Link must be Closed during program shutdown to avoid leaking
-// system resources. Functions provided by shared libraries can currently not
-// be traced and will result in an ErrNotSupported.
+// Functions provided by shared libraries can currently not be traced and
+// will result in an ErrNotSupported.
 func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
 func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
 	u, err := ex.uprobe(symbol, prog, opts, false)
 	u, err := ex.uprobe(symbol, prog, opts, false)
 	if err != nil {
 	if err != nil {
@@ -141,11 +193,14 @@ func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
 // When using symbols which belongs to shared libraries,
 // When using symbols which belongs to shared libraries,
 // an offset must be provided via options:
 // an offset must be provided via options:
 //
 //
-//  ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
+//	up, err := ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
+//
+// Losing the reference to the resulting Link (up) will close the Uprobe
+// and prevent further execution of prog. The Link must be Closed during
+// program shutdown to avoid leaking system resources.
 //
 //
-// The resulting Link must be Closed during program shutdown to avoid leaking
-// system resources. Functions provided by shared libraries can currently not
-// be traced and will result in an ErrNotSupported.
+// Functions provided by shared libraries can currently not be traced and
+// will result in an ErrNotSupported.
 func (ex *Executable) Uretprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
 func (ex *Executable) Uretprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
 	u, err := ex.uprobe(symbol, prog, opts, true)
 	u, err := ex.uprobe(symbol, prog, opts, true)
 	if err != nil {
 	if err != nil {
@@ -175,24 +230,20 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
 	if opts != nil && opts.Offset != 0 {
 	if opts != nil && opts.Offset != 0 {
 		offset = opts.Offset
 		offset = opts.Offset
 	} else {
 	} else {
-		sym, err := ex.symbol(symbol)
+		off, err := ex.offset(symbol)
 		if err != nil {
 		if err != nil {
-			return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, err)
-		}
-
-		// Symbols with location 0 from section undef are shared library calls and
-		// are relocated before the binary is executed. Dynamic linking is not
-		// implemented by the library, so mark this as unsupported for now.
-		if sym.Section == elf.SHN_UNDEF && sym.Value == 0 {
-			return nil, fmt.Errorf("cannot resolve %s library call '%s', "+
-				"consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported)
+			return nil, err
 		}
 		}
+		offset = off
+	}
 
 
-		offset = sym.Value
+	pid := perfAllThreads
+	if opts != nil && opts.PID != 0 {
+		pid = opts.PID
 	}
 	}
 
 
 	// Use uprobe PMU if the kernel has it available.
 	// Use uprobe PMU if the kernel has it available.
-	tp, err := pmuUprobe(symbol, ex.path, offset, ret)
+	tp, err := pmuUprobe(symbol, ex.path, offset, pid, ret)
 	if err == nil {
 	if err == nil {
 		return tp, nil
 		return tp, nil
 	}
 	}
@@ -201,7 +252,7 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
 	}
 	}
 
 
 	// Use tracefs if uprobe PMU is missing.
 	// Use tracefs if uprobe PMU is missing.
-	tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, ret)
+	tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, pid, ret)
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err)
 		return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err)
 	}
 	}
@@ -210,13 +261,13 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
 }
 }
 
 
 // pmuUprobe opens a perf event based on the uprobe PMU.
 // pmuUprobe opens a perf event based on the uprobe PMU.
-func pmuUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
-	return pmuProbe(uprobeType, symbol, path, offset, ret)
+func pmuUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
+	return pmuProbe(uprobeType, symbol, path, offset, pid, ret)
 }
 }
 
 
 // tracefsUprobe creates a Uprobe tracefs entry.
 // tracefsUprobe creates a Uprobe tracefs entry.
-func tracefsUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
-	return tracefsProbe(uprobeType, symbol, path, offset, ret)
+func tracefsUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
+	return tracefsProbe(uprobeType, symbol, path, offset, pid, ret)
 }
 }
 
 
 // uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore.
 // uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore.

+ 21 - 2
vendor/github.com/cilium/ebpf/linker.go

@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"fmt"
 
 
 	"github.com/cilium/ebpf/asm"
 	"github.com/cilium/ebpf/asm"
-	"github.com/cilium/ebpf/internal/btf"
 )
 )
 
 
 // link resolves bpf-to-bpf calls.
 // link resolves bpf-to-bpf calls.
@@ -40,7 +39,7 @@ func link(prog *ProgramSpec, libs []*ProgramSpec) error {
 			pending = append(pending, lib.Instructions)
 			pending = append(pending, lib.Instructions)
 
 
 			if prog.BTF != nil && lib.BTF != nil {
 			if prog.BTF != nil && lib.BTF != nil {
-				if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil {
+				if err := prog.BTF.Append(lib.BTF); err != nil {
 					return fmt.Errorf("linking BTF of %s: %w", lib.Name, err)
 					return fmt.Errorf("linking BTF of %s: %w", lib.Name, err)
 				}
 				}
 			}
 			}
@@ -136,5 +135,25 @@ func fixupJumpsAndCalls(insns asm.Instructions) error {
 		}
 		}
 	}
 	}
 
 
+	// fixupBPFCalls replaces bpf_probe_read_{kernel,user}[_str] with bpf_probe_read[_str] on older kernels
+	// https://github.com/libbpf/libbpf/blob/master/src/libbpf.c#L6009
+	iter = insns.Iterate()
+	for iter.Next() {
+		ins := iter.Ins
+		if !ins.IsBuiltinCall() {
+			continue
+		}
+		switch asm.BuiltinFunc(ins.Constant) {
+		case asm.FnProbeReadKernel, asm.FnProbeReadUser:
+			if err := haveProbeReadKernel(); err != nil {
+				ins.Constant = int64(asm.FnProbeRead)
+			}
+		case asm.FnProbeReadKernelStr, asm.FnProbeReadUserStr:
+			if err := haveProbeReadKernel(); err != nil {
+				ins.Constant = int64(asm.FnProbeReadStr)
+			}
+		}
+	}
+
 	return nil
 	return nil
 }
 }

+ 65 - 30
vendor/github.com/cilium/ebpf/map.go

@@ -1,6 +1,7 @@
 package ebpf
 package ebpf
 
 
 import (
 import (
+	"bytes"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
@@ -65,6 +66,11 @@ type MapSpec struct {
 	// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
 	// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
 	InnerMap *MapSpec
 	InnerMap *MapSpec
 
 
+	// Extra trailing bytes found in the ELF map definition when using structs
+	// larger than libbpf's bpf_map_def. Must be empty before instantiating
+	// the MapSpec into a Map.
+	Extra bytes.Reader
+
 	// The BTF associated with this map.
 	// The BTF associated with this map.
 	BTF *btf.Map
 	BTF *btf.Map
 }
 }
@@ -82,9 +88,12 @@ func (ms *MapSpec) Copy() *MapSpec {
 	}
 	}
 
 
 	cpy := *ms
 	cpy := *ms
+
 	cpy.Contents = make([]MapKV, len(ms.Contents))
 	cpy.Contents = make([]MapKV, len(ms.Contents))
 	copy(cpy.Contents, ms.Contents)
 	copy(cpy.Contents, ms.Contents)
+
 	cpy.InnerMap = ms.InnerMap.Copy()
 	cpy.InnerMap = ms.InnerMap.Copy()
+
 	return &cpy
 	return &cpy
 }
 }
 
 
@@ -188,14 +197,24 @@ func NewMap(spec *MapSpec) (*Map, error) {
 //
 //
 // The caller is responsible for ensuring the process' rlimit is set
 // The caller is responsible for ensuring the process' rlimit is set
 // sufficiently high for locking memory during map creation. This can be done
 // sufficiently high for locking memory during map creation. This can be done
-// by calling unix.Setrlimit with unix.RLIMIT_MEMLOCK prior to calling NewMapWithOptions.
+// by calling rlimit.RemoveMemlock() prior to calling NewMapWithOptions.
 //
 //
 // May return an error wrapping ErrMapIncompatible.
 // May return an error wrapping ErrMapIncompatible.
 func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) {
 func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) {
 	handles := newHandleCache()
 	handles := newHandleCache()
 	defer handles.close()
 	defer handles.close()
 
 
-	return newMapWithOptions(spec, opts, handles)
+	m, err := newMapWithOptions(spec, opts, handles)
+	if err != nil {
+		return nil, fmt.Errorf("creating map: %w", err)
+	}
+
+	err = m.finalize(spec)
+	if err != nil {
+		return nil, fmt.Errorf("populating map: %w", err)
+	}
+
+	return m, nil
 }
 }
 
 
 func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) {
 func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) {
@@ -207,8 +226,12 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
 
 
 	switch spec.Pinning {
 	switch spec.Pinning {
 	case PinByName:
 	case PinByName:
-		if spec.Name == "" || opts.PinPath == "" {
-			return nil, fmt.Errorf("pin by name: missing Name or PinPath")
+		if spec.Name == "" {
+			return nil, fmt.Errorf("pin by name: missing Name")
+		}
+
+		if opts.PinPath == "" {
+			return nil, fmt.Errorf("pin by name: missing MapOptions.PinPath")
 		}
 		}
 
 
 		path := filepath.Join(opts.PinPath, spec.Name)
 		path := filepath.Join(opts.PinPath, spec.Name)
@@ -244,16 +267,19 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
 			return nil, errors.New("inner maps cannot be pinned")
 			return nil, errors.New("inner maps cannot be pinned")
 		}
 		}
 
 
-		template, err := createMap(spec.InnerMap, nil, opts, handles)
+		template, err := spec.InnerMap.createMap(nil, opts, handles)
 		if err != nil {
 		if err != nil {
-			return nil, err
+			return nil, fmt.Errorf("inner map: %w", err)
 		}
 		}
 		defer template.Close()
 		defer template.Close()
 
 
+		// Intentionally skip populating and freezing (finalizing)
+		// the inner map template since it will be removed shortly.
+
 		innerFd = template.fd
 		innerFd = template.fd
 	}
 	}
 
 
-	m, err := createMap(spec, innerFd, opts, handles)
+	m, err := spec.createMap(innerFd, opts, handles)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -269,7 +295,9 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
 	return m, nil
 	return m, nil
 }
 }
 
 
-func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) {
+// createMap validates the spec's properties and creates the map in the kernel
+// using the given opts. It does not populate or freeze the map.
+func (spec *MapSpec) createMap(inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) {
 	closeOnError := func(closer io.Closer) {
 	closeOnError := func(closer io.Closer) {
 		if err != nil {
 		if err != nil {
 			closer.Close()
 			closer.Close()
@@ -278,10 +306,16 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
 
 
 	spec = spec.Copy()
 	spec = spec.Copy()
 
 
+	// Kernels 4.13 through 5.4 used a struct bpf_map_def that contained
+	// additional 'inner_map_idx' and later 'numa_node' fields.
+	// In order to support loading these definitions, tolerate the presence of
+	// extra bytes, but require them to be zeroes.
+	if _, err := io.Copy(internal.DiscardZeroes{}, &spec.Extra); err != nil {
+		return nil, errors.New("extra contains unhandled non-zero bytes, drain before creating map")
+	}
+
 	switch spec.Type {
 	switch spec.Type {
-	case ArrayOfMaps:
-		fallthrough
-	case HashOfMaps:
+	case ArrayOfMaps, HashOfMaps:
 		if err := haveNestedMaps(); err != nil {
 		if err := haveNestedMaps(); err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -350,7 +384,7 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
 
 
 	var btfDisabled bool
 	var btfDisabled bool
 	if spec.BTF != nil {
 	if spec.BTF != nil {
-		handle, err := handles.btfHandle(btf.MapSpec(spec.BTF))
+		handle, err := handles.btfHandle(spec.BTF.Spec)
 		btfDisabled = errors.Is(err, btf.ErrNotSupported)
 		btfDisabled = errors.Is(err, btf.ErrNotSupported)
 		if err != nil && !btfDisabled {
 		if err != nil && !btfDisabled {
 			return nil, fmt.Errorf("load BTF: %w", err)
 			return nil, fmt.Errorf("load BTF: %w", err)
@@ -358,15 +392,15 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
 
 
 		if handle != nil {
 		if handle != nil {
 			attr.BTFFd = uint32(handle.FD())
 			attr.BTFFd = uint32(handle.FD())
-			attr.BTFKeyTypeID = uint32(btf.MapKey(spec.BTF).ID())
-			attr.BTFValueTypeID = uint32(btf.MapValue(spec.BTF).ID())
+			attr.BTFKeyTypeID = uint32(spec.BTF.Key.ID())
+			attr.BTFValueTypeID = uint32(spec.BTF.Value.ID())
 		}
 		}
 	}
 	}
 
 
 	fd, err := internal.BPFMapCreate(&attr)
 	fd, err := internal.BPFMapCreate(&attr)
 	if err != nil {
 	if err != nil {
 		if errors.Is(err, unix.EPERM) {
 		if errors.Is(err, unix.EPERM) {
-			return nil, fmt.Errorf("map create: RLIMIT_MEMLOCK may be too low: %w", err)
+			return nil, fmt.Errorf("map create: %w (MEMLOCK bay be too low, consider rlimit.RemoveMemlock)", err)
 		}
 		}
 		if btfDisabled {
 		if btfDisabled {
 			return nil, fmt.Errorf("map create without BTF: %w", err)
 			return nil, fmt.Errorf("map create without BTF: %w", err)
@@ -380,19 +414,11 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
 		return nil, fmt.Errorf("map create: %w", err)
 		return nil, fmt.Errorf("map create: %w", err)
 	}
 	}
 
 
-	if err := m.populate(spec.Contents); err != nil {
-		return nil, fmt.Errorf("map create: can't set initial contents: %w", err)
-	}
-
-	if spec.Freeze {
-		if err := m.Freeze(); err != nil {
-			return nil, fmt.Errorf("can't freeze map: %w", err)
-		}
-	}
-
 	return m, nil
 	return m, nil
 }
 }
 
 
+// newMap allocates and returns a new Map structure.
+// Sets the fullValueSize on per-CPU maps.
 func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEntries, flags uint32) (*Map, error) {
 func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEntries, flags uint32) (*Map, error) {
 	m := &Map{
 	m := &Map{
 		name,
 		name,
@@ -415,7 +441,7 @@ func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEn
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	m.fullValueSize = align(int(valueSize), 8) * possibleCPUs
+	m.fullValueSize = internal.Align(int(valueSize), 8) * possibleCPUs
 	return m, nil
 	return m, nil
 }
 }
 
 
@@ -892,12 +918,21 @@ func (m *Map) Freeze() error {
 	return nil
 	return nil
 }
 }
 
 
-func (m *Map) populate(contents []MapKV) error {
-	for _, kv := range contents {
+// finalize populates the Map according to the Contents specified
+// in spec and freezes the Map if requested by spec.
+func (m *Map) finalize(spec *MapSpec) error {
+	for _, kv := range spec.Contents {
 		if err := m.Put(kv.Key, kv.Value); err != nil {
 		if err := m.Put(kv.Key, kv.Value); err != nil {
-			return fmt.Errorf("key %v: %w", kv.Key, err)
+			return fmt.Errorf("putting value: key %v: %w", kv.Key, err)
 		}
 		}
 	}
 	}
+
+	if spec.Freeze {
+		if err := m.Freeze(); err != nil {
+			return fmt.Errorf("freezing map: %w", err)
+		}
+	}
+
 	return nil
 	return nil
 }
 }
 
 
@@ -1212,7 +1247,7 @@ func MapGetNextID(startID MapID) (MapID, error) {
 //
 //
 // Returns ErrNotExist, if there is no eBPF map with the given id.
 // Returns ErrNotExist, if there is no eBPF map with the given id.
 func NewMapFromID(id MapID) (*Map, error) {
 func NewMapFromID(id MapID) (*Map, error) {
-	fd, err := bpfObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id))
+	fd, err := internal.BPFObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id))
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 49 - 14
vendor/github.com/cilium/ebpf/marshalers.go

@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"fmt"
 	"reflect"
 	"reflect"
 	"runtime"
 	"runtime"
+	"sync"
 	"unsafe"
 	"unsafe"
 
 
 	"github.com/cilium/ebpf/internal"
 	"github.com/cilium/ebpf/internal"
@@ -39,6 +40,10 @@ func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
 // Returns an error if the given value isn't representable in exactly
 // Returns an error if the given value isn't representable in exactly
 // length bytes.
 // length bytes.
 func marshalBytes(data interface{}, length int) (buf []byte, err error) {
 func marshalBytes(data interface{}, length int) (buf []byte, err error) {
+	if data == nil {
+		return nil, errors.New("can't marshal a nil value")
+	}
+
 	switch value := data.(type) {
 	switch value := data.(type) {
 	case encoding.BinaryMarshaler:
 	case encoding.BinaryMarshaler:
 		buf, err = value.MarshalBinary()
 		buf, err = value.MarshalBinary()
@@ -77,22 +82,30 @@ func makeBuffer(dst interface{}, length int) (internal.Pointer, []byte) {
 	return internal.NewSlicePointer(buf), buf
 	return internal.NewSlicePointer(buf), buf
 }
 }
 
 
+var bytesReaderPool = sync.Pool{
+	New: func() interface{} {
+		return new(bytes.Reader)
+	},
+}
+
 // unmarshalBytes converts a byte buffer into an arbitrary value.
 // unmarshalBytes converts a byte buffer into an arbitrary value.
 //
 //
 // Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
 // Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
 // those have special cases that allow more types to be encoded.
 // those have special cases that allow more types to be encoded.
+//
+// The common int32 and int64 types are directly handled to avoid
+// unnecessary heap allocations as happening in the default case.
 func unmarshalBytes(data interface{}, buf []byte) error {
 func unmarshalBytes(data interface{}, buf []byte) error {
 	switch value := data.(type) {
 	switch value := data.(type) {
 	case unsafe.Pointer:
 	case unsafe.Pointer:
-		// This could be solved in Go 1.17 by unsafe.Slice instead. (https://github.com/golang/go/issues/19367)
-		// We could opt for removing unsafe.Pointer support in the lib as well.
-		sh := &reflect.SliceHeader{ //nolint:govet
-			Data: uintptr(value),
-			Len:  len(buf),
-			Cap:  len(buf),
-		}
+		var dst []byte
+		// Use unsafe.Slice when we drop support for pre1.17 (https://github.com/golang/go/issues/19367)
+		// We could opt for removing unsafe.Pointer support in the lib as well
+		sh := (*reflect.SliceHeader)(unsafe.Pointer(&dst))
+		sh.Data = uintptr(value)
+		sh.Len = len(buf)
+		sh.Cap = len(buf)
 
 
-		dst := *(*[]byte)(unsafe.Pointer(sh))
 		copy(dst, buf)
 		copy(dst, buf)
 		runtime.KeepAlive(value)
 		runtime.KeepAlive(value)
 		return nil
 		return nil
@@ -106,12 +119,38 @@ func unmarshalBytes(data interface{}, buf []byte) error {
 	case *[]byte:
 	case *[]byte:
 		*value = buf
 		*value = buf
 		return nil
 		return nil
+	case *int32:
+		if len(buf) < 4 {
+			return errors.New("int32 requires 4 bytes")
+		}
+		*value = int32(internal.NativeEndian.Uint32(buf))
+		return nil
+	case *uint32:
+		if len(buf) < 4 {
+			return errors.New("uint32 requires 4 bytes")
+		}
+		*value = internal.NativeEndian.Uint32(buf)
+		return nil
+	case *int64:
+		if len(buf) < 8 {
+			return errors.New("int64 requires 8 bytes")
+		}
+		*value = int64(internal.NativeEndian.Uint64(buf))
+		return nil
+	case *uint64:
+		if len(buf) < 8 {
+			return errors.New("uint64 requires 8 bytes")
+		}
+		*value = internal.NativeEndian.Uint64(buf)
+		return nil
 	case string:
 	case string:
 		return errors.New("require pointer to string")
 		return errors.New("require pointer to string")
 	case []byte:
 	case []byte:
 		return errors.New("require pointer to []byte")
 		return errors.New("require pointer to []byte")
 	default:
 	default:
-		rd := bytes.NewReader(buf)
+		rd := bytesReaderPool.Get().(*bytes.Reader)
+		rd.Reset(buf)
+		defer bytesReaderPool.Put(rd)
 		if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
 		if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
 			return fmt.Errorf("decoding %T: %v", value, err)
 			return fmt.Errorf("decoding %T: %v", value, err)
 		}
 		}
@@ -142,7 +181,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er
 		return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
 		return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
 	}
 	}
 
 
-	alignedElemLength := align(elemLength, 8)
+	alignedElemLength := internal.Align(elemLength, 8)
 	buf := make([]byte, alignedElemLength*possibleCPUs)
 	buf := make([]byte, alignedElemLength*possibleCPUs)
 
 
 	for i := 0; i < sliceLen; i++ {
 	for i := 0; i < sliceLen; i++ {
@@ -212,7 +251,3 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro
 	reflect.ValueOf(slicePtr).Elem().Set(slice)
 	reflect.ValueOf(slicePtr).Elem().Set(slice)
 	return nil
 	return nil
 }
 }
-
-func align(n, alignment int) int {
-	return (int(n) + alignment - 1) / alignment * alignment
-}

+ 78 - 45
vendor/github.com/cilium/ebpf/prog.go

@@ -57,16 +57,21 @@ type ProgramSpec struct {
 	// Name is passed to the kernel as a debug aid. Must only contain
 	// Name is passed to the kernel as a debug aid. Must only contain
 	// alpha numeric and '_' characters.
 	// alpha numeric and '_' characters.
 	Name string
 	Name string
+
 	// Type determines at which hook in the kernel a program will run.
 	// Type determines at which hook in the kernel a program will run.
 	Type       ProgramType
 	Type       ProgramType
 	AttachType AttachType
 	AttachType AttachType
-	// Name of a kernel data structure to attach to. It's interpretation
-	// depends on Type and AttachType.
-	AttachTo     string
+	// Name of a kernel data structure or function to attach to. Its
+	// interpretation depends on Type and AttachType.
+	AttachTo string
+	// The program to attach to. Must be provided manually.
+	AttachTarget *Program
 	Instructions asm.Instructions
 	Instructions asm.Instructions
+
 	// Flags is passed to the kernel and specifies additional program
 	// Flags is passed to the kernel and specifies additional program
 	// load attributes.
 	// load attributes.
 	Flags uint32
 	Flags uint32
+
 	// License of the program. Some helpers are only available if
 	// License of the program. Some helpers are only available if
 	// the license is deemed compatible with the GPL.
 	// the license is deemed compatible with the GPL.
 	//
 	//
@@ -146,7 +151,7 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
 
 
 func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *handleCache) (*Program, error) {
 func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *handleCache) (*Program, error) {
 	if len(spec.Instructions) == 0 {
 	if len(spec.Instructions) == 0 {
-		return nil, errors.New("Instructions cannot be empty")
+		return nil, errors.New("instructions cannot be empty")
 	}
 	}
 
 
 	if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
 	if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
@@ -166,16 +171,16 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
 		kv = v.Kernel()
 		kv = v.Kernel()
 	}
 	}
 
 
-	attr := &bpfProgLoadAttr{
-		progType:           spec.Type,
-		progFlags:          spec.Flags,
-		expectedAttachType: spec.AttachType,
-		license:            internal.NewStringPointer(spec.License),
-		kernelVersion:      kv,
+	attr := &internal.BPFProgLoadAttr{
+		ProgType:           uint32(spec.Type),
+		ProgFlags:          spec.Flags,
+		ExpectedAttachType: uint32(spec.AttachType),
+		License:            internal.NewStringPointer(spec.License),
+		KernelVersion:      kv,
 	}
 	}
 
 
 	if haveObjName() == nil {
 	if haveObjName() == nil {
-		attr.progName = internal.NewBPFObjName(spec.Name)
+		attr.ProgName = internal.NewBPFObjName(spec.Name)
 	}
 	}
 
 
 	var err error
 	var err error
@@ -190,35 +195,35 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
 	var btfDisabled bool
 	var btfDisabled bool
 	var core btf.COREFixups
 	var core btf.COREFixups
 	if spec.BTF != nil {
 	if spec.BTF != nil {
-		core, err = btf.ProgramFixups(spec.BTF, targetBTF)
+		core, err = spec.BTF.Fixups(targetBTF)
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf("CO-RE relocations: %w", err)
 			return nil, fmt.Errorf("CO-RE relocations: %w", err)
 		}
 		}
 
 
-		handle, err := handles.btfHandle(btf.ProgramSpec(spec.BTF))
+		handle, err := handles.btfHandle(spec.BTF.Spec())
 		btfDisabled = errors.Is(err, btf.ErrNotSupported)
 		btfDisabled = errors.Is(err, btf.ErrNotSupported)
 		if err != nil && !btfDisabled {
 		if err != nil && !btfDisabled {
 			return nil, fmt.Errorf("load BTF: %w", err)
 			return nil, fmt.Errorf("load BTF: %w", err)
 		}
 		}
 
 
 		if handle != nil {
 		if handle != nil {
-			attr.progBTFFd = uint32(handle.FD())
+			attr.ProgBTFFd = uint32(handle.FD())
 
 
-			recSize, bytes, err := btf.ProgramLineInfos(spec.BTF)
+			recSize, bytes, err := spec.BTF.LineInfos()
 			if err != nil {
 			if err != nil {
 				return nil, fmt.Errorf("get BTF line infos: %w", err)
 				return nil, fmt.Errorf("get BTF line infos: %w", err)
 			}
 			}
-			attr.lineInfoRecSize = recSize
-			attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
-			attr.lineInfo = internal.NewSlicePointer(bytes)
+			attr.LineInfoRecSize = recSize
+			attr.LineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
+			attr.LineInfo = internal.NewSlicePointer(bytes)
 
 
-			recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF)
+			recSize, bytes, err = spec.BTF.FuncInfos()
 			if err != nil {
 			if err != nil {
 				return nil, fmt.Errorf("get BTF function infos: %w", err)
 				return nil, fmt.Errorf("get BTF function infos: %w", err)
 			}
 			}
-			attr.funcInfoRecSize = recSize
-			attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
-			attr.funcInfo = internal.NewSlicePointer(bytes)
+			attr.FuncInfoRecSize = recSize
+			attr.FuncInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
+			attr.FuncInfo = internal.NewSlicePointer(bytes)
 		}
 		}
 	}
 	}
 
 
@@ -238,16 +243,41 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
 	}
 	}
 
 
 	bytecode := buf.Bytes()
 	bytecode := buf.Bytes()
-	attr.instructions = internal.NewSlicePointer(bytecode)
-	attr.insCount = uint32(len(bytecode) / asm.InstructionSize)
+	attr.Instructions = internal.NewSlicePointer(bytecode)
+	attr.InsCount = uint32(len(bytecode) / asm.InstructionSize)
 
 
 	if spec.AttachTo != "" {
 	if spec.AttachTo != "" {
+		if spec.AttachTarget != nil {
+			info, err := spec.AttachTarget.Info()
+			if err != nil {
+				return nil, fmt.Errorf("load target BTF: %w", err)
+			}
+
+			btfID, ok := info.BTFID()
+			if !ok {
+				return nil, fmt.Errorf("load target BTF: no BTF info available")
+			}
+			btfHandle, err := btf.NewHandleFromID(btfID)
+			if err != nil {
+				return nil, fmt.Errorf("load target BTF: %w", err)
+			}
+			defer btfHandle.Close()
+
+			targetBTF = btfHandle.Spec()
+			if err != nil {
+				return nil, fmt.Errorf("load target BTF: %w", err)
+			}
+		}
+
 		target, err := resolveBTFType(targetBTF, spec.AttachTo, spec.Type, spec.AttachType)
 		target, err := resolveBTFType(targetBTF, spec.AttachTo, spec.Type, spec.AttachType)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
 		if target != nil {
 		if target != nil {
-			attr.attachBTFID = target.ID()
+			attr.AttachBTFID = uint32(target.ID())
+		}
+		if spec.AttachTarget != nil {
+			attr.AttachProgFd = uint32(spec.AttachTarget.FD())
 		}
 		}
 	}
 	}
 
 
@@ -259,12 +289,12 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
 	var logBuf []byte
 	var logBuf []byte
 	if opts.LogLevel > 0 {
 	if opts.LogLevel > 0 {
 		logBuf = make([]byte, logSize)
 		logBuf = make([]byte, logSize)
-		attr.logLevel = opts.LogLevel
-		attr.logSize = uint32(len(logBuf))
-		attr.logBuf = internal.NewSlicePointer(logBuf)
+		attr.LogLevel = opts.LogLevel
+		attr.LogSize = uint32(len(logBuf))
+		attr.LogBuf = internal.NewSlicePointer(logBuf)
 	}
 	}
 
 
-	fd, err := bpfProgLoad(attr)
+	fd, err := internal.BPFProgLoad(attr)
 	if err == nil {
 	if err == nil {
 		return &Program{internal.CString(logBuf), fd, spec.Name, "", spec.Type}, nil
 		return &Program{internal.CString(logBuf), fd, spec.Name, "", spec.Type}, nil
 	}
 	}
@@ -273,17 +303,20 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
 	if opts.LogLevel == 0 && opts.LogSize >= 0 {
 	if opts.LogLevel == 0 && opts.LogSize >= 0 {
 		// Re-run with the verifier enabled to get better error messages.
 		// Re-run with the verifier enabled to get better error messages.
 		logBuf = make([]byte, logSize)
 		logBuf = make([]byte, logSize)
-		attr.logLevel = 1
-		attr.logSize = uint32(len(logBuf))
-		attr.logBuf = internal.NewSlicePointer(logBuf)
+		attr.LogLevel = 1
+		attr.LogSize = uint32(len(logBuf))
+		attr.LogBuf = internal.NewSlicePointer(logBuf)
 
 
-		_, logErr = bpfProgLoad(attr)
+		fd, logErr = internal.BPFProgLoad(attr)
+		if logErr == nil {
+			fd.Close()
+		}
 	}
 	}
 
 
 	if errors.Is(logErr, unix.EPERM) && logBuf[0] == 0 {
 	if errors.Is(logErr, unix.EPERM) && logBuf[0] == 0 {
 		// EPERM due to RLIMIT_MEMLOCK happens before the verifier, so we can
 		// EPERM due to RLIMIT_MEMLOCK happens before the verifier, so we can
 		// check that the log is empty to reduce false positives.
 		// check that the log is empty to reduce false positives.
-		return nil, fmt.Errorf("load program: RLIMIT_MEMLOCK may be too low: %w", logErr)
+		return nil, fmt.Errorf("load program: %w (MEMLOCK bay be too low, consider rlimit.RemoveMemlock)", logErr)
 	}
 	}
 
 
 	err = internal.ErrorWithLog(err, logBuf, logErr)
 	err = internal.ErrorWithLog(err, logBuf, logErr)
@@ -310,7 +343,7 @@ func NewProgramFromFD(fd int) (*Program, error) {
 //
 //
 // Returns ErrNotExist, if there is no eBPF program with the given id.
 // Returns ErrNotExist, if there is no eBPF program with the given id.
 func NewProgramFromID(id ProgramID) (*Program, error) {
 func NewProgramFromID(id ProgramID) (*Program, error) {
-	fd, err := bpfObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id))
+	fd, err := internal.BPFObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id))
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("get program by id: %w", err)
 		return nil, fmt.Errorf("get program by id: %w", err)
 	}
 	}
@@ -677,45 +710,44 @@ func ProgramGetNextID(startID ProgramID) (ProgramID, error) {
 //
 //
 // Deprecated: use ProgramInfo.ID() instead.
 // Deprecated: use ProgramInfo.ID() instead.
 func (p *Program) ID() (ProgramID, error) {
 func (p *Program) ID() (ProgramID, error) {
-	info, err := bpfGetProgInfoByFD(p.fd)
+	info, err := bpfGetProgInfoByFD(p.fd, nil)
 	if err != nil {
 	if err != nil {
 		return ProgramID(0), err
 		return ProgramID(0), err
 	}
 	}
 	return ProgramID(info.id), nil
 	return ProgramID(info.id), nil
 }
 }
 
 
-func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
+func resolveBTFType(spec *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
 	type match struct {
 	type match struct {
 		p ProgramType
 		p ProgramType
 		a AttachType
 		a AttachType
 	}
 	}
 
 
-	var target btf.Type
 	var typeName, featureName string
 	var typeName, featureName string
 	switch (match{progType, attachType}) {
 	switch (match{progType, attachType}) {
 	case match{LSM, AttachLSMMac}:
 	case match{LSM, AttachLSMMac}:
-		target = new(btf.Func)
 		typeName = "bpf_lsm_" + name
 		typeName = "bpf_lsm_" + name
 		featureName = name + " LSM hook"
 		featureName = name + " LSM hook"
-
 	case match{Tracing, AttachTraceIter}:
 	case match{Tracing, AttachTraceIter}:
-		target = new(btf.Func)
 		typeName = "bpf_iter_" + name
 		typeName = "bpf_iter_" + name
 		featureName = name + " iterator"
 		featureName = name + " iterator"
-
+	case match{Extension, AttachNone}:
+		typeName = name
+		featureName = fmt.Sprintf("freplace %s", name)
 	default:
 	default:
 		return nil, nil
 		return nil, nil
 	}
 	}
 
 
-	if kernel == nil {
+	if spec == nil {
 		var err error
 		var err error
-		kernel, err = btf.LoadKernelSpec()
+		spec, err = btf.LoadKernelSpec()
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf("load kernel spec: %w", err)
 			return nil, fmt.Errorf("load kernel spec: %w", err)
 		}
 		}
 	}
 	}
 
 
-	err := kernel.FindType(typeName, target)
+	var target *btf.Func
+	err := spec.FindType(typeName, &target)
 	if errors.Is(err, btf.ErrNotFound) {
 	if errors.Is(err, btf.ErrNotFound) {
 		return nil, &internal.UnsupportedFeatureError{
 		return nil, &internal.UnsupportedFeatureError{
 			Name: featureName,
 			Name: featureName,
@@ -724,5 +756,6 @@ func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachT
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("resolve BTF for %s: %w", featureName, err)
 		return nil, fmt.Errorf("resolve BTF for %s: %w", featureName, err)
 	}
 	}
+
 	return target, nil
 	return target, nil
 }
 }

+ 12 - 10
vendor/github.com/cilium/ebpf/run-tests.sh

@@ -5,7 +5,7 @@
 #     Run all tests on a 5.4 kernel
 #     Run all tests on a 5.4 kernel
 #     $ ./run-tests.sh 5.4
 #     $ ./run-tests.sh 5.4
 #     Run a subset of tests:
 #     Run a subset of tests:
-#     $ ./run-tests.sh 5.4 go test ./link
+#     $ ./run-tests.sh 5.4 ./link
 
 
 set -euo pipefail
 set -euo pipefail
 
 
@@ -48,15 +48,17 @@ if [[ "${1:-}" = "--exec-vm" ]]; then
     rm "${output}/fake-stdin"
     rm "${output}/fake-stdin"
   fi
   fi
 
 
-  $sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \
-  --rwdir="${testdir}=${testdir}" \
-  --rodir=/run/input="${input}" \
-  --rwdir=/run/output="${output}" \
-  --script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \
-  --qemu-opts -smp 2 # need at least two CPUs for some tests
+  if ! $sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \
+    --rwdir="${testdir}=${testdir}" \
+    --rodir=/run/input="${input}" \
+    --rwdir=/run/output="${output}" \
+    --script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \
+    --kopt possible_cpus=2; then # need at least two CPUs for some tests
+    exit 23
+  fi
 
 
   if [[ ! -e "${output}/success" ]]; then
   if [[ ! -e "${output}/success" ]]; then
-    exit 1
+    exit 42
   fi
   fi
 
 
   $sudo rm -r "$output"
   $sudo rm -r "$output"
@@ -74,7 +76,7 @@ elif [[ "${1:-}" = "--exec-test" ]]; then
   dmesg -C
   dmesg -C
   if ! "$@"; then
   if ! "$@"; then
     dmesg
     dmesg
-    exit 1
+    exit 1 # this return code is "swallowed" by qemu
   fi
   fi
   touch "/run/output/success"
   touch "/run/output/success"
   exit 0
   exit 0
@@ -108,7 +110,7 @@ else
   echo "No selftests found, disabling"
   echo "No selftests found, disabling"
 fi
 fi
 
 
-args=(-v -short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...)
+args=(-short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...)
 if (( $# > 0 )); then
 if (( $# > 0 )); then
   args=("$@")
   args=("$@")
 fi
 fi

+ 39 - 55
vendor/github.com/cilium/ebpf/syscalls.go

@@ -1,13 +1,14 @@
 package ebpf
 package ebpf
 
 
 import (
 import (
+	"bytes"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 	"unsafe"
 	"unsafe"
 
 
+	"github.com/cilium/ebpf/asm"
 	"github.com/cilium/ebpf/internal"
 	"github.com/cilium/ebpf/internal"
-	"github.com/cilium/ebpf/internal/btf"
 	"github.com/cilium/ebpf/internal/unix"
 	"github.com/cilium/ebpf/internal/unix"
 )
 )
 
 
@@ -73,30 +74,6 @@ type bpfMapInfo struct {
 	btf_value_type_id         uint32
 	btf_value_type_id         uint32
 }
 }
 
 
-type bpfProgLoadAttr struct {
-	progType           ProgramType
-	insCount           uint32
-	instructions       internal.Pointer
-	license            internal.Pointer
-	logLevel           uint32
-	logSize            uint32
-	logBuf             internal.Pointer
-	kernelVersion      uint32              // since 4.1  2541517c32be
-	progFlags          uint32              // since 4.11 e07b98d9bffe
-	progName           internal.BPFObjName // since 4.15 067cae47771c
-	progIfIndex        uint32              // since 4.15 1f6f4cb7ba21
-	expectedAttachType AttachType          // since 4.17 5e43f899b03a
-	progBTFFd          uint32
-	funcInfoRecSize    uint32
-	funcInfo           internal.Pointer
-	funcInfoCnt        uint32
-	lineInfoRecSize    uint32
-	lineInfo           internal.Pointer
-	lineInfoCnt        uint32
-	attachBTFID        btf.TypeID
-	attachProgFd       uint32
-}
-
 type bpfProgInfo struct {
 type bpfProgInfo struct {
 	prog_type                uint32
 	prog_type                uint32
 	id                       uint32
 	id                       uint32
@@ -107,7 +84,7 @@ type bpfProgInfo struct {
 	xlated_prog_insns        internal.Pointer
 	xlated_prog_insns        internal.Pointer
 	load_time                uint64 // since 4.15 cb4d2b3f03d8
 	load_time                uint64 // since 4.15 cb4d2b3f03d8
 	created_by_uid           uint32
 	created_by_uid           uint32
-	nr_map_ids               uint32
+	nr_map_ids               uint32 // since 4.15 cb4d2b3f03d8
 	map_ids                  internal.Pointer
 	map_ids                  internal.Pointer
 	name                     internal.BPFObjName // since 4.15 067cae47771c
 	name                     internal.BPFObjName // since 4.15 067cae47771c
 	ifindex                  uint32
 	ifindex                  uint32
@@ -145,11 +122,6 @@ type bpfProgTestRunAttr struct {
 	duration    uint32
 	duration    uint32
 }
 }
 
 
-type bpfGetFDByIDAttr struct {
-	id   uint32
-	next uint32
-}
-
 type bpfMapFreezeAttr struct {
 type bpfMapFreezeAttr struct {
 	mapFd uint32
 	mapFd uint32
 }
 }
@@ -160,23 +132,6 @@ type bpfObjGetNextIDAttr struct {
 	openFlags uint32
 	openFlags uint32
 }
 }
 
 
-func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
-	for {
-		fd, err := internal.BPF(internal.BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
-		// As of ~4.20 the verifier can be interrupted by a signal,
-		// and returns EAGAIN in that case.
-		if errors.Is(err, unix.EAGAIN) {
-			continue
-		}
-
-		if err != nil {
-			return nil, err
-		}
-
-		return internal.NewFD(uint32(fd)), nil
-	}
-}
-
 func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
 func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
 	_, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 	_, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 	return err
 	return err
@@ -372,6 +327,10 @@ func wrapMapError(err error) error {
 		return internal.SyscallError(ErrNotSupported, unix.ENOTSUPP)
 		return internal.SyscallError(ErrNotSupported, unix.ENOTSUPP)
 	}
 	}
 
 
+	if errors.Is(err, unix.E2BIG) {
+		return fmt.Errorf("key too big for map: %w", err)
+	}
+
 	return err
 	return err
 }
 }
 
 
@@ -388,8 +347,13 @@ func bpfMapFreeze(m *internal.FD) error {
 	return err
 	return err
 }
 }
 
 
-func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) {
+func bpfGetProgInfoByFD(fd *internal.FD, ids []MapID) (*bpfProgInfo, error) {
 	var info bpfProgInfo
 	var info bpfProgInfo
+	if len(ids) > 0 {
+		info.nr_map_ids = uint32(len(ids))
+		info.map_ids = internal.NewPointer(unsafe.Pointer(&ids[0]))
+	}
+
 	if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
 	if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
 		return nil, fmt.Errorf("can't get program info: %w", err)
 		return nil, fmt.Errorf("can't get program info: %w", err)
 	}
 	}
@@ -471,10 +435,30 @@ var haveBatchAPI = internal.FeatureTest("map batch api", "5.6", func() error {
 	return nil
 	return nil
 })
 })
 
 
-func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) {
-	attr := bpfGetFDByIDAttr{
-		id: id,
+var haveProbeReadKernel = internal.FeatureTest("bpf_probe_read_kernel", "5.5", func() error {
+	insns := asm.Instructions{
+		asm.Mov.Reg(asm.R1, asm.R10),
+		asm.Add.Imm(asm.R1, -8),
+		asm.Mov.Imm(asm.R2, 8),
+		asm.Mov.Imm(asm.R3, 0),
+		asm.FnProbeReadKernel.Call(),
+		asm.Return(),
+	}
+	buf := bytes.NewBuffer(make([]byte, 0, len(insns)*asm.InstructionSize))
+	if err := insns.Marshal(buf, internal.NativeEndian); err != nil {
+		return err
 	}
 	}
-	ptr, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
-	return internal.NewFD(uint32(ptr)), err
-}
+	bytecode := buf.Bytes()
+
+	fd, err := internal.BPFProgLoad(&internal.BPFProgLoadAttr{
+		ProgType:     uint32(Kprobe),
+		License:      internal.NewStringPointer("GPL"),
+		Instructions: internal.NewSlicePointer(bytecode),
+		InsCount:     uint32(len(bytecode) / asm.InstructionSize),
+	})
+	if err != nil {
+		return internal.ErrNotSupported
+	}
+	_ = fd.Close()
+	return nil
+})

+ 33 - 3
vendor/github.com/cilium/ebpf/types.go

@@ -4,12 +4,17 @@ import (
 	"github.com/cilium/ebpf/internal/unix"
 	"github.com/cilium/ebpf/internal/unix"
 )
 )
 
 
-//go:generate stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType
+//go:generate stringer -output types_string.go -type=MapType,ProgramType,PinType
 
 
 // MapType indicates the type map structure
 // MapType indicates the type map structure
 // that will be initialized in the kernel.
 // that will be initialized in the kernel.
 type MapType uint32
 type MapType uint32
 
 
+// Max returns the latest supported MapType.
+func (_ MapType) Max() MapType {
+	return maxMapType - 1
+}
+
 // All the various map types that can be created
 // All the various map types that can be created
 const (
 const (
 	UnspecifiedMap MapType = iota
 	UnspecifiedMap MapType = iota
@@ -85,15 +90,28 @@ const (
 	SkStorage
 	SkStorage
 	// DevMapHash - Hash-based indexing scheme for references to network devices.
 	// DevMapHash - Hash-based indexing scheme for references to network devices.
 	DevMapHash
 	DevMapHash
-	StructOpts
+	// StructOpsMap - This map holds a kernel struct with its function pointer implemented in a BPF
+	// program.
+	StructOpsMap
+	// RingBuf - Similar to PerfEventArray, but shared across all CPUs.
 	RingBuf
 	RingBuf
+	// InodeStorage - Specialized local storage map for inodes.
 	InodeStorage
 	InodeStorage
+	// TaskStorage - Specialized local storage map for task_struct.
 	TaskStorage
 	TaskStorage
+	// maxMapType - Bound enum of MapTypes, has to be last in enum.
+	maxMapType
 )
 )
 
 
+// Deprecated: StructOpts was a typo, use StructOpsMap instead.
+//
+// Declared as a variable to prevent stringer from picking it up
+// as an enum value.
+var StructOpts MapType = StructOpsMap
+
 // hasPerCPUValue returns true if the Map stores a value per CPU.
 // hasPerCPUValue returns true if the Map stores a value per CPU.
 func (mt MapType) hasPerCPUValue() bool {
 func (mt MapType) hasPerCPUValue() bool {
-	return mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash
+	return mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash || mt == PerCPUCGroupStorage
 }
 }
 
 
 // canStoreMap returns true if the map type accepts a map fd
 // canStoreMap returns true if the map type accepts a map fd
@@ -111,6 +129,11 @@ func (mt MapType) canStoreProgram() bool {
 // ProgramType of the eBPF program
 // ProgramType of the eBPF program
 type ProgramType uint32
 type ProgramType uint32
 
 
+// Max return the latest supported ProgramType.
+func (_ ProgramType) Max() ProgramType {
+	return maxProgramType - 1
+}
+
 // eBPF program types
 // eBPF program types
 const (
 const (
 	UnspecifiedProgram ProgramType = iota
 	UnspecifiedProgram ProgramType = iota
@@ -144,6 +167,7 @@ const (
 	Extension
 	Extension
 	LSM
 	LSM
 	SkLookup
 	SkLookup
+	maxProgramType
 )
 )
 
 
 // AttachType of the eBPF program, needed to differentiate allowed context accesses in
 // AttachType of the eBPF program, needed to differentiate allowed context accesses in
@@ -151,6 +175,8 @@ const (
 // Will cause invalid argument (EINVAL) at program load time if set incorrectly.
 // Will cause invalid argument (EINVAL) at program load time if set incorrectly.
 type AttachType uint32
 type AttachType uint32
 
 
+//go:generate stringer -type AttachType -trimprefix Attach
+
 // AttachNone is an alias for AttachCGroupInetIngress for readability reasons.
 // AttachNone is an alias for AttachCGroupInetIngress for readability reasons.
 const AttachNone AttachType = 0
 const AttachNone AttachType = 0
 
 
@@ -193,6 +219,10 @@ const (
 	AttachXDPCPUMap
 	AttachXDPCPUMap
 	AttachSkLookup
 	AttachSkLookup
 	AttachXDP
 	AttachXDP
+	AttachSkSKBVerdict
+	AttachSkReuseportSelect
+	AttachSkReuseportSelectOrMigrate
+	AttachPerfEvent
 )
 )
 
 
 // AttachFlags of the eBPF program used in BPF_PROG_ATTACH command
 // AttachFlags of the eBPF program used in BPF_PROG_ATTACH command

+ 8 - 61
vendor/github.com/cilium/ebpf/types_string.go

@@ -1,4 +1,4 @@
-// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType"; DO NOT EDIT.
+// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,PinType"; DO NOT EDIT.
 
 
 package ebpf
 package ebpf
 
 
@@ -34,15 +34,16 @@ func _() {
 	_ = x[Stack-23]
 	_ = x[Stack-23]
 	_ = x[SkStorage-24]
 	_ = x[SkStorage-24]
 	_ = x[DevMapHash-25]
 	_ = x[DevMapHash-25]
-	_ = x[StructOpts-26]
+	_ = x[StructOpsMap-26]
 	_ = x[RingBuf-27]
 	_ = x[RingBuf-27]
 	_ = x[InodeStorage-28]
 	_ = x[InodeStorage-28]
 	_ = x[TaskStorage-29]
 	_ = x[TaskStorage-29]
+	_ = x[maxMapType-30]
 }
 }
 
 
-const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOptsRingBufInodeStorageTaskStorage"
+const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOpsMapRingBufInodeStorageTaskStoragemaxMapType"
 
 
-var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 258, 265, 277, 288}
+var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 260, 267, 279, 290, 300}
 
 
 func (i MapType) String() string {
 func (i MapType) String() string {
 	if i >= MapType(len(_MapType_index)-1) {
 	if i >= MapType(len(_MapType_index)-1) {
@@ -85,11 +86,12 @@ func _() {
 	_ = x[Extension-28]
 	_ = x[Extension-28]
 	_ = x[LSM-29]
 	_ = x[LSM-29]
 	_ = x[SkLookup-30]
 	_ = x[SkLookup-30]
+	_ = x[maxProgramType-31]
 }
 }
 
 
-const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracingStructOpsExtensionLSMSkLookup"
+const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracingStructOpsExtensionLSMSkLookupmaxProgramType"
 
 
-var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258, 265, 274, 283, 286, 294}
+var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258, 265, 274, 283, 286, 294, 308}
 
 
 func (i ProgramType) String() string {
 func (i ProgramType) String() string {
 	if i >= ProgramType(len(_ProgramType_index)-1) {
 	if i >= ProgramType(len(_ProgramType_index)-1) {
@@ -97,61 +99,6 @@ func (i ProgramType) String() string {
 	}
 	}
 	return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]]
 	return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]]
 }
 }
-func _() {
-	// An "invalid array index" compiler error signifies that the constant values have changed.
-	// Re-run the stringer command to generate them again.
-	var x [1]struct{}
-	_ = x[AttachNone-0]
-	_ = x[AttachCGroupInetIngress-0]
-	_ = x[AttachCGroupInetEgress-1]
-	_ = x[AttachCGroupInetSockCreate-2]
-	_ = x[AttachCGroupSockOps-3]
-	_ = x[AttachSkSKBStreamParser-4]
-	_ = x[AttachSkSKBStreamVerdict-5]
-	_ = x[AttachCGroupDevice-6]
-	_ = x[AttachSkMsgVerdict-7]
-	_ = x[AttachCGroupInet4Bind-8]
-	_ = x[AttachCGroupInet6Bind-9]
-	_ = x[AttachCGroupInet4Connect-10]
-	_ = x[AttachCGroupInet6Connect-11]
-	_ = x[AttachCGroupInet4PostBind-12]
-	_ = x[AttachCGroupInet6PostBind-13]
-	_ = x[AttachCGroupUDP4Sendmsg-14]
-	_ = x[AttachCGroupUDP6Sendmsg-15]
-	_ = x[AttachLircMode2-16]
-	_ = x[AttachFlowDissector-17]
-	_ = x[AttachCGroupSysctl-18]
-	_ = x[AttachCGroupUDP4Recvmsg-19]
-	_ = x[AttachCGroupUDP6Recvmsg-20]
-	_ = x[AttachCGroupGetsockopt-21]
-	_ = x[AttachCGroupSetsockopt-22]
-	_ = x[AttachTraceRawTp-23]
-	_ = x[AttachTraceFEntry-24]
-	_ = x[AttachTraceFExit-25]
-	_ = x[AttachModifyReturn-26]
-	_ = x[AttachLSMMac-27]
-	_ = x[AttachTraceIter-28]
-	_ = x[AttachCgroupInet4GetPeername-29]
-	_ = x[AttachCgroupInet6GetPeername-30]
-	_ = x[AttachCgroupInet4GetSockname-31]
-	_ = x[AttachCgroupInet6GetSockname-32]
-	_ = x[AttachXDPDevMap-33]
-	_ = x[AttachCgroupInetSockRelease-34]
-	_ = x[AttachXDPCPUMap-35]
-	_ = x[AttachSkLookup-36]
-	_ = x[AttachXDP-37]
-}
-
-const _AttachType_name = "AttachNoneAttachCGroupInetEgressAttachCGroupInetSockCreateAttachCGroupSockOpsAttachSkSKBStreamParserAttachSkSKBStreamVerdictAttachCGroupDeviceAttachSkMsgVerdictAttachCGroupInet4BindAttachCGroupInet6BindAttachCGroupInet4ConnectAttachCGroupInet6ConnectAttachCGroupInet4PostBindAttachCGroupInet6PostBindAttachCGroupUDP4SendmsgAttachCGroupUDP6SendmsgAttachLircMode2AttachFlowDissectorAttachCGroupSysctlAttachCGroupUDP4RecvmsgAttachCGroupUDP6RecvmsgAttachCGroupGetsockoptAttachCGroupSetsockoptAttachTraceRawTpAttachTraceFEntryAttachTraceFExitAttachModifyReturnAttachLSMMacAttachTraceIterAttachCgroupInet4GetPeernameAttachCgroupInet6GetPeernameAttachCgroupInet4GetSocknameAttachCgroupInet6GetSocknameAttachXDPDevMapAttachCgroupInetSockReleaseAttachXDPCPUMapAttachSkLookupAttachXDP"
-
-var _AttachType_index = [...]uint16{0, 10, 32, 58, 77, 100, 124, 142, 160, 181, 202, 226, 250, 275, 300, 323, 346, 361, 380, 398, 421, 444, 466, 488, 504, 521, 537, 555, 567, 582, 610, 638, 666, 694, 709, 736, 751, 765, 774}
-
-func (i AttachType) String() string {
-	if i >= AttachType(len(_AttachType_index)-1) {
-		return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")"
-	}
-	return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]]
-}
 func _() {
 func _() {
 	// An "invalid array index" compiler error signifies that the constant values have changed.
 	// An "invalid array index" compiler error signifies that the constant values have changed.
 	// Re-run the stringer command to generate them again.
 	// Re-run the stringer command to generate them again.

+ 5 - 5
vendor/github.com/containerd/console/console_windows.go

@@ -17,10 +17,10 @@
 package console
 package console
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 
 
-	"github.com/pkg/errors"
 	"golang.org/x/sys/windows"
 	"golang.org/x/sys/windows"
 )
 )
 
 
@@ -103,7 +103,7 @@ func (m *master) Reset() error {
 		{m.err, m.errMode},
 		{m.err, m.errMode},
 	} {
 	} {
 		if err := windows.SetConsoleMode(s.fd, s.mode); err != nil {
 		if err := windows.SetConsoleMode(s.fd, s.mode); err != nil {
-			return errors.Wrap(err, "unable to restore console mode")
+			return fmt.Errorf("unable to restore console mode: %w", err)
 		}
 		}
 	}
 	}
 
 
@@ -114,7 +114,7 @@ func (m *master) Size() (WinSize, error) {
 	var info windows.ConsoleScreenBufferInfo
 	var info windows.ConsoleScreenBufferInfo
 	err := windows.GetConsoleScreenBufferInfo(m.out, &info)
 	err := windows.GetConsoleScreenBufferInfo(m.out, &info)
 	if err != nil {
 	if err != nil {
-		return WinSize{}, errors.Wrap(err, "unable to get console info")
+		return WinSize{}, fmt.Errorf("unable to get console info: %w", err)
 	}
 	}
 
 
 	winsize := WinSize{
 	winsize := WinSize{
@@ -139,7 +139,7 @@ func (m *master) DisableEcho() error {
 	mode |= windows.ENABLE_LINE_INPUT
 	mode |= windows.ENABLE_LINE_INPUT
 
 
 	if err := windows.SetConsoleMode(m.in, mode); err != nil {
 	if err := windows.SetConsoleMode(m.in, mode); err != nil {
-		return errors.Wrap(err, "unable to set console to disable echo")
+		return fmt.Errorf("unable to set console to disable echo: %w", err)
 	}
 	}
 
 
 	return nil
 	return nil
@@ -192,7 +192,7 @@ func makeInputRaw(fd windows.Handle, mode uint32) error {
 	}
 	}
 
 
 	if err := windows.SetConsoleMode(fd, mode); err != nil {
 	if err := windows.SetConsoleMode(fd, mode); err != nil {
-		return errors.Wrap(err, "unable to set console to raw mode")
+		return fmt.Errorf("unable to set console to raw mode: %w", err)
 	}
 	}
 
 
 	return nil
 	return nil

+ 163 - 0
vendor/github.com/containerd/console/console_zos.go

@@ -0,0 +1,163 @@
+// +build zos
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package console
+
+import (
+	"fmt"
+	"os"
+
+	"golang.org/x/sys/unix"
+)
+
+// NewPty creates a new pty pair
+// The master is returned as the first console and a string
+// with the path to the pty slave is returned as the second
+func NewPty() (Console, string, error) {
+	var f File
+	var err error
+	var slave string
+	for i := 0;; i++ {
+		ptyp := fmt.Sprintf("/dev/ptyp%04d", i)
+		f, err = os.OpenFile(ptyp, os.O_RDWR, 0600)
+		if err == nil {
+			slave = fmt.Sprintf("/dev/ttyp%04d", i)
+			break
+		}
+		if os.IsNotExist(err) {
+			return nil, "", err
+		}
+		// else probably Resource Busy
+	}
+	m, err := newMaster(f)
+	if err != nil {
+		return nil, "", err
+	}
+	return m, slave, nil
+}
+
+type master struct {
+	f        File
+	original *unix.Termios
+}
+
+func (m *master) Read(b []byte) (int, error) {
+	return m.f.Read(b)
+}
+
+func (m *master) Write(b []byte) (int, error) {
+	return m.f.Write(b)
+}
+
+func (m *master) Close() error {
+	return m.f.Close()
+}
+
+func (m *master) Resize(ws WinSize) error {
+	return tcswinsz(m.f.Fd(), ws)
+}
+
+func (m *master) ResizeFrom(c Console) error {
+	ws, err := c.Size()
+	if err != nil {
+		return err
+	}
+	return m.Resize(ws)
+}
+
+func (m *master) Reset() error {
+	if m.original == nil {
+		return nil
+	}
+	return tcset(m.f.Fd(), m.original)
+}
+
+func (m *master) getCurrent() (unix.Termios, error) {
+	var termios unix.Termios
+	if err := tcget(m.f.Fd(), &termios); err != nil {
+		return unix.Termios{}, err
+	}
+	return termios, nil
+}
+
+func (m *master) SetRaw() error {
+	rawState, err := m.getCurrent()
+	if err != nil {
+		return err
+	}
+	rawState = cfmakeraw(rawState)
+	rawState.Oflag = rawState.Oflag | unix.OPOST
+	return tcset(m.f.Fd(), &rawState)
+}
+
+func (m *master) DisableEcho() error {
+	rawState, err := m.getCurrent()
+	if err != nil {
+		return err
+	}
+	rawState.Lflag = rawState.Lflag &^ unix.ECHO
+	return tcset(m.f.Fd(), &rawState)
+}
+
+func (m *master) Size() (WinSize, error) {
+	return tcgwinsz(m.f.Fd())
+}
+
+func (m *master) Fd() uintptr {
+	return m.f.Fd()
+}
+
+func (m *master) Name() string {
+	return m.f.Name()
+}
+
+// checkConsole checks if the provided file is a console
+func checkConsole(f File) error {
+	var termios unix.Termios
+	if tcget(f.Fd(), &termios) != nil {
+		return ErrNotAConsole
+	}
+	return nil
+}
+
+func newMaster(f File) (Console, error) {
+	m := &master{
+		f: f,
+	}
+	t, err := m.getCurrent()
+	if err != nil {
+		return nil, err
+	}
+	m.original = &t
+	return m, nil
+}
+
+// ClearONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
+// created by us acts normally. In particular, a not-very-well-known default of
+// Linux unix98 ptys is that they have +onlcr by default. While this isn't a
+// problem for terminal emulators, because we relay data from the terminal we
+// also relay that funky line discipline.
+func ClearONLCR(fd uintptr) error {
+	return setONLCR(fd, false)
+}
+
+// SetONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
+// created by us acts as intended for a terminal emulator.
+func SetONLCR(fd uintptr) error {
+	return setONLCR(fd, true)
+}

+ 1 - 1
vendor/github.com/containerd/console/tc_unix.go

@@ -1,4 +1,4 @@
-// +build darwin freebsd linux netbsd openbsd solaris
+// +build darwin freebsd linux netbsd openbsd solaris zos
 
 
 /*
 /*
    Copyright The containerd Authors.
    Copyright The containerd Authors.

+ 26 - 0
vendor/github.com/containerd/console/tc_zos.go

@@ -0,0 +1,26 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package console
+
+import (
+	"golang.org/x/sys/unix"
+)
+
+const (
+	cmdTcGet = unix.TCGETS
+	cmdTcSet = unix.TCSETS
+)

+ 5 - 3
vendor/github.com/cyphar/filepath-securejoin/.travis.yml

@@ -4,10 +4,12 @@
 
 
 language: go
 language: go
 go:
 go:
-    - 1.7.x
-    - 1.8.x
+    - 1.13.x
+    - 1.16.x
     - tip
     - tip
-
+arch:
+    - AMD64
+    - ppc64le
 os:
 os:
     - linux
     - linux
     - osx
     - osx

+ 17 - 3
vendor/github.com/cyphar/filepath-securejoin/README.md

@@ -7,6 +7,19 @@ standard library][go#20126]. The purpose of this function is to be a "secure"
 alternative to `filepath.Join`, and in particular it provides certain
 alternative to `filepath.Join`, and in particular it provides certain
 guarantees that are not provided by `filepath.Join`.
 guarantees that are not provided by `filepath.Join`.
 
 
+> **NOTE**: This code is *only* safe if you are not at risk of other processes
+> modifying path components after you've used `SecureJoin`. If it is possible
+> for a malicious process to modify path components of the resolved path, then
+> you will be vulnerable to some fairly trivial TOCTOU race conditions. [There
+> are some Linux kernel patches I'm working on which might allow for a better
+> solution.][lwn-obeneath]
+>
+> In addition, with a slightly modified API it might be possible to use
+> `O_PATH` and verify that the opened path is actually the resolved one -- but
+> I have not done that yet. I might add it in the future as a helper function
+> to help users verify the path (we can't just return `/proc/self/fd/<foo>`
+> because that doesn't always work transparently for all users).
+
 This is the function prototype:
 This is the function prototype:
 
 
 ```go
 ```go
@@ -16,8 +29,8 @@ func SecureJoin(root, unsafePath string) (string, error)
 This library **guarantees** the following:
 This library **guarantees** the following:
 
 
 * If no error is set, the resulting string **must** be a child path of
 * If no error is set, the resulting string **must** be a child path of
-  `SecureJoin` and will not contain any symlink path components (they will all
-  be expanded).
+  `root` and will not contain any symlink path components (they will all be
+  expanded).
 
 
 * When expanding symlinks, all symlink path components **must** be resolved
 * When expanding symlinks, all symlink path components **must** be resolved
   relative to the provided root. In particular, this can be considered a
   relative to the provided root. In particular, this can be considered a
@@ -25,7 +38,7 @@ This library **guarantees** the following:
   these symlinks will **not** be expanded lexically (`filepath.Clean` is not
   these symlinks will **not** be expanded lexically (`filepath.Clean` is not
   called on the input before processing).
   called on the input before processing).
 
 
-* Non-existant path components are unaffected by `SecureJoin` (similar to
+* Non-existent path components are unaffected by `SecureJoin` (similar to
   `filepath.EvalSymlinks`'s semantics).
   `filepath.EvalSymlinks`'s semantics).
 
 
 * The returned path will always be `filepath.Clean`ed and thus not contain any
 * The returned path will always be `filepath.Clean`ed and thus not contain any
@@ -57,6 +70,7 @@ func SecureJoin(root, unsafePath string) (string, error) {
 }
 }
 ```
 ```
 
 
+[lwn-obeneath]: https://lwn.net/Articles/767547/
 [go#20126]: https://github.com/golang/go/issues/20126
 [go#20126]: https://github.com/golang/go/issues/20126
 
 
 ### License ###
 ### License ###

+ 1 - 1
vendor/github.com/cyphar/filepath-securejoin/VERSION

@@ -1 +1 @@
-0.2.2
+0.2.3

+ 3 - 22
vendor/github.com/cyphar/filepath-securejoin/join.go

@@ -12,39 +12,20 @@ package securejoin
 
 
 import (
 import (
 	"bytes"
 	"bytes"
+	"errors"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"strings"
 	"strings"
 	"syscall"
 	"syscall"
-
-	"github.com/pkg/errors"
 )
 )
 
 
-// ErrSymlinkLoop is returned by SecureJoinVFS when too many symlinks have been
-// evaluated in attempting to securely join the two given paths.
-var ErrSymlinkLoop = errors.Wrap(syscall.ELOOP, "secure join")
-
 // IsNotExist tells you if err is an error that implies that either the path
 // IsNotExist tells you if err is an error that implies that either the path
 // accessed does not exist (or path components don't exist). This is
 // accessed does not exist (or path components don't exist). This is
 // effectively a more broad version of os.IsNotExist.
 // effectively a more broad version of os.IsNotExist.
 func IsNotExist(err error) bool {
 func IsNotExist(err error) bool {
-	// If it's a bone-fide ENOENT just bail.
-	if os.IsNotExist(errors.Cause(err)) {
-		return true
-	}
-
 	// Check that it's not actually an ENOTDIR, which in some cases is a more
 	// Check that it's not actually an ENOTDIR, which in some cases is a more
 	// convoluted case of ENOENT (usually involving weird paths).
 	// convoluted case of ENOENT (usually involving weird paths).
-	var errno error
-	switch err := errors.Cause(err).(type) {
-	case *os.PathError:
-		errno = err.Err
-	case *os.LinkError:
-		errno = err.Err
-	case *os.SyscallError:
-		errno = err.Err
-	}
-	return errno == syscall.ENOTDIR || errno == syscall.ENOENT
+	return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT)
 }
 }
 
 
 // SecureJoinVFS joins the two given path components (similar to Join) except
 // SecureJoinVFS joins the two given path components (similar to Join) except
@@ -68,7 +49,7 @@ func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) {
 	n := 0
 	n := 0
 	for unsafePath != "" {
 	for unsafePath != "" {
 		if n > 255 {
 		if n > 255 {
-			return "", ErrSymlinkLoop
+			return "", &os.PathError{Op: "SecureJoin", Path: root + "/" + unsafePath, Err: syscall.ELOOP}
 		}
 		}
 
 
 		// Next path component, p.
 		// Next path component, p.

+ 0 - 1
vendor/github.com/cyphar/filepath-securejoin/vendor.conf

@@ -1 +0,0 @@
-github.com/pkg/errors v0.8.0

+ 6 - 6
vendor/github.com/godbus/dbus/v5/README.markdown → vendor/github.com/godbus/dbus/v5/README.md

@@ -14,14 +14,12 @@ D-Bus message bus system.
 
 
 ### Installation
 ### Installation
 
 
-This packages requires Go 1.7. If you installed it and set up your GOPATH, just run:
+This packages requires Go 1.12 or later. It can be installed by running the command below:
 
 
 ```
 ```
-go get github.com/godbus/dbus
+go get github.com/godbus/dbus/v5
 ```
 ```
 
 
-If you want to use the subpackages, you can install them the same way.
-
 ### Usage
 ### Usage
 
 
 The complete package documentation and some simple examples are available at
 The complete package documentation and some simple examples are available at
@@ -30,10 +28,12 @@ The complete package documentation and some simple examples are available at
 gives a short overview over the basic usage. 
 gives a short overview over the basic usage. 
 
 
 #### Projects using godbus
 #### Projects using godbus
-- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
+- [fyne](https://github.com/fyne-io/fyne) a cross platform GUI in Go inspired by Material Design.
+- [fynedesk](https://github.com/fyne-io/fynedesk) a full desktop environment for Linux/Unix using Fyne.
 - [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
 - [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
-- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
 - [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
 - [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
+- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
+- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
 
 
 Please note that the API is considered unstable for now and may change without
 Please note that the API is considered unstable for now and may change without
 further notice.
 further notice.

+ 9 - 6
vendor/github.com/godbus/dbus/v5/auth.go

@@ -53,7 +53,7 @@ type Auth interface {
 // bus. Auth must not be called on shared connections.
 // bus. Auth must not be called on shared connections.
 func (conn *Conn) Auth(methods []Auth) error {
 func (conn *Conn) Auth(methods []Auth) error {
 	if methods == nil {
 	if methods == nil {
-		uid := strconv.Itoa(os.Getuid())
+		uid := strconv.Itoa(os.Geteuid())
 		methods = []Auth{AuthExternal(uid), AuthCookieSha1(uid, getHomeDir())}
 		methods = []Auth{AuthExternal(uid), AuthCookieSha1(uid, getHomeDir())}
 	}
 	}
 	in := bufio.NewReader(conn.transport)
 	in := bufio.NewReader(conn.transport)
@@ -75,9 +75,9 @@ func (conn *Conn) Auth(methods []Auth) error {
 	s = s[1:]
 	s = s[1:]
 	for _, v := range s {
 	for _, v := range s {
 		for _, m := range methods {
 		for _, m := range methods {
-			if name, data, status := m.FirstData(); bytes.Equal(v, name) {
+			if name, _, status := m.FirstData(); bytes.Equal(v, name) {
 				var ok bool
 				var ok bool
-				err = authWriteLine(conn.transport, []byte("AUTH"), v, data)
+				err = authWriteLine(conn.transport, []byte("AUTH"), v)
 				if err != nil {
 				if err != nil {
 					return err
 					return err
 				}
 				}
@@ -194,11 +194,14 @@ func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, boo
 			}
 			}
 			conn.uuid = string(s[1])
 			conn.uuid = string(s[1])
 			return nil, true
 			return nil, true
+		case state == waitingForOk && string(s[0]) == "DATA":
+			err = authWriteLine(conn.transport, []byte("DATA"))
+			if err != nil {
+				return err, false
+			}
 		case state == waitingForOk && string(s[0]) == "REJECTED":
 		case state == waitingForOk && string(s[0]) == "REJECTED":
 			return nil, false
 			return nil, false
-		case state == waitingForOk && (string(s[0]) == "DATA" ||
-			string(s[0]) == "ERROR"):
-
+		case state == waitingForOk && string(s[0]) == "ERROR":
 			err = authWriteLine(conn.transport, []byte("CANCEL"))
 			err = authWriteLine(conn.transport, []byte("CANCEL"))
 			if err != nil {
 			if err != nil {
 				return err, false
 				return err, false

+ 30 - 6
vendor/github.com/godbus/dbus/v5/conn.go

@@ -73,7 +73,7 @@ func SessionBus() (conn *Conn, err error) {
 	return
 	return
 }
 }
 
 
-func getSessionBusAddress() (string, error) {
+func getSessionBusAddress(autolaunch bool) (string, error) {
 	if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" {
 	if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" {
 		return address, nil
 		return address, nil
 
 
@@ -81,12 +81,26 @@ func getSessionBusAddress() (string, error) {
 		os.Setenv("DBUS_SESSION_BUS_ADDRESS", address)
 		os.Setenv("DBUS_SESSION_BUS_ADDRESS", address)
 		return address, nil
 		return address, nil
 	}
 	}
+	if !autolaunch {
+		return "", errors.New("dbus: couldn't determine address of session bus")
+	}
 	return getSessionBusPlatformAddress()
 	return getSessionBusPlatformAddress()
 }
 }
 
 
 // SessionBusPrivate returns a new private connection to the session bus.
 // SessionBusPrivate returns a new private connection to the session bus.
 func SessionBusPrivate(opts ...ConnOption) (*Conn, error) {
 func SessionBusPrivate(opts ...ConnOption) (*Conn, error) {
-	address, err := getSessionBusAddress()
+	address, err := getSessionBusAddress(true)
+	if err != nil {
+		return nil, err
+	}
+
+	return Dial(address, opts...)
+}
+
+// SessionBusPrivate returns a new private connection to the session bus.  If
+// the session bus is not already open, do not attempt to launch it.
+func SessionBusPrivateNoAutoStartup(opts ...ConnOption) (*Conn, error) {
+	address, err := getSessionBusAddress(false)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -121,7 +135,7 @@ func SystemBus() (conn *Conn, err error) {
 
 
 // ConnectSessionBus connects to the session bus.
 // ConnectSessionBus connects to the session bus.
 func ConnectSessionBus(opts ...ConnOption) (*Conn, error) {
 func ConnectSessionBus(opts ...ConnOption) (*Conn, error) {
-	address, err := getSessionBusAddress()
+	address, err := getSessionBusAddress(true)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -180,7 +194,7 @@ func Dial(address string, opts ...ConnOption) (*Conn, error) {
 //
 //
 // Deprecated: use Dial with options instead.
 // Deprecated: use Dial with options instead.
 func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) {
 func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) {
-	return Dial(address, WithSignalHandler(signalHandler))
+	return Dial(address, WithHandler(handler), WithSignalHandler(signalHandler))
 }
 }
 
 
 // ConnOption is a connection option.
 // ConnOption is a connection option.
@@ -478,14 +492,24 @@ func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
 		conn.outInt(msg)
 		conn.outInt(msg)
 	}
 	}
 	err := conn.outHandler.sendAndIfClosed(msg, ifClosed)
 	err := conn.outHandler.sendAndIfClosed(msg, ifClosed)
-	conn.calls.handleSendError(msg, err)
 	if err != nil {
 	if err != nil {
-		conn.serialGen.RetireSerial(msg.serial)
+		conn.handleSendError(msg, err)
 	} else if msg.Type != TypeMethodCall {
 	} else if msg.Type != TypeMethodCall {
 		conn.serialGen.RetireSerial(msg.serial)
 		conn.serialGen.RetireSerial(msg.serial)
 	}
 	}
 }
 }
 
 
+func (conn *Conn) handleSendError(msg *Message, err error) {
+	if msg.Type == TypeMethodCall {
+		conn.calls.handleSendError(msg, err)
+	} else if msg.Type == TypeMethodReply {
+		if _, ok := err.(FormatError); ok {
+			conn.sendError(err, msg.Headers[FieldDestination].value.(string), msg.Headers[FieldReplySerial].value.(uint32))
+		}
+	}
+	conn.serialGen.RetireSerial(msg.serial)
+}
+
 // Send sends the given message to the message bus. You usually don't need to
 // Send sends the given message to the message bus. You usually don't need to
 // use this; use the higher-level equivalents (Call / Go, Emit and Export)
 // use this; use the higher-level equivalents (Call / Go, Emit and Export)
 // instead. If msg is a method call and NoReplyExpected is not set, a non-nil
 // instead. If msg is a method call and NoReplyExpected is not set, a non-nil

+ 11 - 5
vendor/github.com/godbus/dbus/v5/decoder.go

@@ -10,14 +10,16 @@ type decoder struct {
 	in    io.Reader
 	in    io.Reader
 	order binary.ByteOrder
 	order binary.ByteOrder
 	pos   int
 	pos   int
+	fds   []int
 }
 }
 
 
 // newDecoder returns a new decoder that reads values from in. The input is
 // newDecoder returns a new decoder that reads values from in. The input is
 // expected to be in the given byte order.
 // expected to be in the given byte order.
-func newDecoder(in io.Reader, order binary.ByteOrder) *decoder {
+func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder {
 	dec := new(decoder)
 	dec := new(decoder)
 	dec.in = in
 	dec.in = in
 	dec.order = order
 	dec.order = order
+	dec.fds = fds
 	return dec
 	return dec
 }
 }
 
 
@@ -53,7 +55,7 @@ func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
 	vs = make([]interface{}, 0)
 	vs = make([]interface{}, 0)
 	s := sig.str
 	s := sig.str
 	for s != "" {
 	for s != "" {
-		err, rem := validSingle(s, 0)
+		err, rem := validSingle(s, &depthCounter{})
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -150,7 +152,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
 		if len(sig.str) == 0 {
 		if len(sig.str) == 0 {
 			panic(FormatError("variant signature is empty"))
 			panic(FormatError("variant signature is empty"))
 		}
 		}
-		err, rem := validSingle(sig.str, 0)
+		err, rem := validSingle(sig.str, &depthCounter{})
 		if err != nil {
 		if err != nil {
 			panic(err)
 			panic(err)
 		}
 		}
@@ -161,7 +163,11 @@ func (dec *decoder) decode(s string, depth int) interface{} {
 		variant.value = dec.decode(sig.str, depth+1)
 		variant.value = dec.decode(sig.str, depth+1)
 		return variant
 		return variant
 	case 'h':
 	case 'h':
-		return UnixFDIndex(dec.decode("u", depth).(uint32))
+		idx := dec.decode("u", depth).(uint32)
+		if int(idx) < len(dec.fds) {
+			return UnixFD(dec.fds[idx])
+		}
+		return UnixFDIndex(idx)
 	case 'a':
 	case 'a':
 		if len(s) > 1 && s[1] == '{' {
 		if len(s) > 1 && s[1] == '{' {
 			ksig := s[2:3]
 			ksig := s[2:3]
@@ -219,7 +225,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
 		v := make([]interface{}, 0)
 		v := make([]interface{}, 0)
 		s = s[1 : len(s)-1]
 		s = s[1 : len(s)-1]
 		for s != "" {
 		for s != "" {
-			err, rem := validSingle(s, 0)
+			err, rem := validSingle(s, &depthCounter{})
 			if err != nil {
 			if err != nil {
 				panic(err)
 				panic(err)
 			}
 			}

+ 43 - 18
vendor/github.com/godbus/dbus/v5/encoder.go

@@ -5,28 +5,33 @@ import (
 	"encoding/binary"
 	"encoding/binary"
 	"io"
 	"io"
 	"reflect"
 	"reflect"
+	"strings"
+	"unicode/utf8"
 )
 )
 
 
 // An encoder encodes values to the D-Bus wire format.
 // An encoder encodes values to the D-Bus wire format.
 type encoder struct {
 type encoder struct {
 	out   io.Writer
 	out   io.Writer
+	fds   []int
 	order binary.ByteOrder
 	order binary.ByteOrder
 	pos   int
 	pos   int
 }
 }
 
 
 // NewEncoder returns a new encoder that writes to out in the given byte order.
 // NewEncoder returns a new encoder that writes to out in the given byte order.
-func newEncoder(out io.Writer, order binary.ByteOrder) *encoder {
-	return newEncoderAtOffset(out, 0, order)
+func newEncoder(out io.Writer, order binary.ByteOrder, fds []int) *encoder {
+	enc := newEncoderAtOffset(out, 0, order, fds)
+	return enc
 }
 }
 
 
 // newEncoderAtOffset returns a new encoder that writes to out in the given
 // newEncoderAtOffset returns a new encoder that writes to out in the given
 // byte order. Specify the offset to initialize pos for proper alignment
 // byte order. Specify the offset to initialize pos for proper alignment
 // computation.
 // computation.
-func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder) *encoder {
+func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder, fds []int) *encoder {
 	enc := new(encoder)
 	enc := new(encoder)
 	enc.out = out
 	enc.out = out
 	enc.order = order
 	enc.order = order
 	enc.pos = offset
 	enc.pos = offset
+	enc.fds = fds
 	return enc
 	return enc
 }
 }
 
 
@@ -75,6 +80,9 @@ func (enc *encoder) Encode(vs ...interface{}) (err error) {
 // encode encodes the given value to the writer and panics on error. depth holds
 // encode encodes the given value to the writer and panics on error. depth holds
 // the depth of the container nesting.
 // the depth of the container nesting.
 func (enc *encoder) encode(v reflect.Value, depth int) {
 func (enc *encoder) encode(v reflect.Value, depth int) {
+	if depth > 64 {
+		panic(FormatError("input exceeds depth limitation"))
+	}
 	enc.align(alignment(v.Type()))
 	enc.align(alignment(v.Type()))
 	switch v.Kind() {
 	switch v.Kind() {
 	case reflect.Uint8:
 	case reflect.Uint8:
@@ -97,7 +105,14 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 		enc.binwrite(uint16(v.Uint()))
 		enc.binwrite(uint16(v.Uint()))
 		enc.pos += 2
 		enc.pos += 2
 	case reflect.Int, reflect.Int32:
 	case reflect.Int, reflect.Int32:
-		enc.binwrite(int32(v.Int()))
+		if v.Type() == unixFDType {
+			fd := v.Int()
+			idx := len(enc.fds)
+			enc.fds = append(enc.fds, int(fd))
+			enc.binwrite(uint32(idx))
+		} else {
+			enc.binwrite(int32(v.Int()))
+		}
 		enc.pos += 4
 		enc.pos += 4
 	case reflect.Uint, reflect.Uint32:
 	case reflect.Uint, reflect.Uint32:
 		enc.binwrite(uint32(v.Uint()))
 		enc.binwrite(uint32(v.Uint()))
@@ -112,9 +127,21 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 		enc.binwrite(v.Float())
 		enc.binwrite(v.Float())
 		enc.pos += 8
 		enc.pos += 8
 	case reflect.String:
 	case reflect.String:
-		enc.encode(reflect.ValueOf(uint32(len(v.String()))), depth)
+		str := v.String()
+		if !utf8.ValidString(str) {
+			panic(FormatError("input has a not-utf8 char in string"))
+		}
+		if strings.IndexByte(str, byte(0)) != -1 {
+			panic(FormatError("input has a null char('\\000') in string"))
+		}
+		if v.Type() == objectPathType {
+			if !ObjectPath(str).IsValid() {
+				panic(FormatError("invalid object path"))
+			}
+		}
+		enc.encode(reflect.ValueOf(uint32(len(str))), depth)
 		b := make([]byte, v.Len()+1)
 		b := make([]byte, v.Len()+1)
-		copy(b, v.String())
+		copy(b, str)
 		b[len(b)-1] = 0
 		b[len(b)-1] = 0
 		n, err := enc.out.Write(b)
 		n, err := enc.out.Write(b)
 		if err != nil {
 		if err != nil {
@@ -124,20 +151,23 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 	case reflect.Ptr:
 	case reflect.Ptr:
 		enc.encode(v.Elem(), depth)
 		enc.encode(v.Elem(), depth)
 	case reflect.Slice, reflect.Array:
 	case reflect.Slice, reflect.Array:
-		if depth >= 64 {
-			panic(FormatError("input exceeds container depth limit"))
-		}
 		// Lookahead offset: 4 bytes for uint32 length (with alignment),
 		// Lookahead offset: 4 bytes for uint32 length (with alignment),
 		// plus alignment for elements.
 		// plus alignment for elements.
 		n := enc.padding(0, 4) + 4
 		n := enc.padding(0, 4) + 4
 		offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
 		offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
 
 
 		var buf bytes.Buffer
 		var buf bytes.Buffer
-		bufenc := newEncoderAtOffset(&buf, offset, enc.order)
+		bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
 
 
 		for i := 0; i < v.Len(); i++ {
 		for i := 0; i < v.Len(); i++ {
 			bufenc.encode(v.Index(i), depth+1)
 			bufenc.encode(v.Index(i), depth+1)
 		}
 		}
+
+		if buf.Len() > 1<<26 {
+			panic(FormatError("input exceeds array size limitation"))
+		}
+
+		enc.fds = bufenc.fds
 		enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
 		enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
 		length := buf.Len()
 		length := buf.Len()
 		enc.align(alignment(v.Type().Elem()))
 		enc.align(alignment(v.Type().Elem()))
@@ -146,13 +176,10 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 		}
 		}
 		enc.pos += length
 		enc.pos += length
 	case reflect.Struct:
 	case reflect.Struct:
-		if depth >= 64 && v.Type() != signatureType {
-			panic(FormatError("input exceeds container depth limit"))
-		}
 		switch t := v.Type(); t {
 		switch t := v.Type(); t {
 		case signatureType:
 		case signatureType:
 			str := v.Field(0)
 			str := v.Field(0)
-			enc.encode(reflect.ValueOf(byte(str.Len())), depth+1)
+			enc.encode(reflect.ValueOf(byte(str.Len())), depth)
 			b := make([]byte, str.Len()+1)
 			b := make([]byte, str.Len()+1)
 			copy(b, str.String())
 			copy(b, str.String())
 			b[len(b)-1] = 0
 			b[len(b)-1] = 0
@@ -176,9 +203,6 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 	case reflect.Map:
 	case reflect.Map:
 		// Maps are arrays of structures, so they actually increase the depth by
 		// Maps are arrays of structures, so they actually increase the depth by
 		// 2.
 		// 2.
-		if depth >= 63 {
-			panic(FormatError("input exceeds container depth limit"))
-		}
 		if !isKeyType(v.Type().Key()) {
 		if !isKeyType(v.Type().Key()) {
 			panic(InvalidTypeError{v.Type()})
 			panic(InvalidTypeError{v.Type()})
 		}
 		}
@@ -189,12 +213,13 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 		offset := enc.pos + n + enc.padding(n, 8)
 		offset := enc.pos + n + enc.padding(n, 8)
 
 
 		var buf bytes.Buffer
 		var buf bytes.Buffer
-		bufenc := newEncoderAtOffset(&buf, offset, enc.order)
+		bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
 		for _, k := range keys {
 		for _, k := range keys {
 			bufenc.align(8)
 			bufenc.align(8)
 			bufenc.encode(k, depth+2)
 			bufenc.encode(k, depth+2)
 			bufenc.encode(v.MapIndex(k), depth+2)
 			bufenc.encode(v.MapIndex(k), depth+2)
 		}
 		}
+		enc.fds = bufenc.fds
 		enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
 		enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
 		length := buf.Len()
 		length := buf.Len()
 		enc.align(8)
 		enc.align(8)

+ 30 - 7
vendor/github.com/godbus/dbus/v5/export.go

@@ -26,6 +26,27 @@ var (
 	}
 	}
 )
 )
 
 
+func MakeNoObjectError(path ObjectPath) Error {
+	return Error{
+		"org.freedesktop.DBus.Error.NoSuchObject",
+		[]interface{}{fmt.Sprintf("No such object '%s'", string(path))},
+	}
+}
+
+func MakeUnknownMethodError(methodName string) Error {
+	return Error{
+		"org.freedesktop.DBus.Error.UnknownMethod",
+		[]interface{}{fmt.Sprintf("Unknown / invalid method '%s'", methodName)},
+	}
+}
+
+func MakeUnknownInterfaceError(ifaceName string) Error {
+	return Error{
+		"org.freedesktop.DBus.Error.UnknownInterface",
+		[]interface{}{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)},
+	}
+}
+
 func MakeFailedError(err error) *Error {
 func MakeFailedError(err error) *Error {
 	return &Error{
 	return &Error{
 		"org.freedesktop.DBus.Error.Failed",
 		"org.freedesktop.DBus.Error.Failed",
@@ -128,6 +149,11 @@ func (conn *Conn) handleCall(msg *Message) {
 	ifaceName, _ := msg.Headers[FieldInterface].value.(string)
 	ifaceName, _ := msg.Headers[FieldInterface].value.(string)
 	sender, hasSender := msg.Headers[FieldSender].value.(string)
 	sender, hasSender := msg.Headers[FieldSender].value.(string)
 	serial := msg.serial
 	serial := msg.serial
+
+	if len(name) == 0 {
+		conn.sendError(ErrMsgUnknownMethod, sender, serial)
+	}
+
 	if ifaceName == "org.freedesktop.DBus.Peer" {
 	if ifaceName == "org.freedesktop.DBus.Peer" {
 		switch name {
 		switch name {
 		case "Ping":
 		case "Ping":
@@ -135,29 +161,26 @@ func (conn *Conn) handleCall(msg *Message) {
 		case "GetMachineId":
 		case "GetMachineId":
 			conn.sendReply(sender, serial, conn.uuid)
 			conn.sendReply(sender, serial, conn.uuid)
 		default:
 		default:
-			conn.sendError(ErrMsgUnknownMethod, sender, serial)
+			conn.sendError(MakeUnknownMethodError(name), sender, serial)
 		}
 		}
 		return
 		return
 	}
 	}
-	if len(name) == 0 {
-		conn.sendError(ErrMsgUnknownMethod, sender, serial)
-	}
 
 
 	object, ok := conn.handler.LookupObject(path)
 	object, ok := conn.handler.LookupObject(path)
 	if !ok {
 	if !ok {
-		conn.sendError(ErrMsgNoObject, sender, serial)
+		conn.sendError(MakeNoObjectError(path), sender, serial)
 		return
 		return
 	}
 	}
 
 
 	iface, exists := object.LookupInterface(ifaceName)
 	iface, exists := object.LookupInterface(ifaceName)
 	if !exists {
 	if !exists {
-		conn.sendError(ErrMsgUnknownInterface, sender, serial)
+		conn.sendError(MakeUnknownInterfaceError(ifaceName), sender, serial)
 		return
 		return
 	}
 	}
 
 
 	m, exists := iface.LookupMethod(name)
 	m, exists := iface.LookupMethod(name)
 	if !exists {
 	if !exists {
-		conn.sendError(ErrMsgUnknownMethod, sender, serial)
+		conn.sendError(MakeUnknownMethodError(name), sender, serial)
 		return
 		return
 	}
 	}
 	args, err := conn.decodeArguments(m, sender, msg)
 	args, err := conn.decodeArguments(m, sender, msg)

+ 52 - 21
vendor/github.com/godbus/dbus/v5/message.go

@@ -118,11 +118,7 @@ type header struct {
 	Variant
 	Variant
 }
 }
 
 
-// DecodeMessage tries to decode a single message in the D-Bus wire format
-// from the given reader. The byte order is figured out from the first byte.
-// The possibly returned error can be an error of the underlying reader, an
-// InvalidMessageError or a FormatError.
-func DecodeMessage(rd io.Reader) (msg *Message, err error) {
+func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) {
 	var order binary.ByteOrder
 	var order binary.ByteOrder
 	var hlength, length uint32
 	var hlength, length uint32
 	var typ, flags, proto byte
 	var typ, flags, proto byte
@@ -142,7 +138,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
 		return nil, InvalidMessageError("invalid byte order")
 		return nil, InvalidMessageError("invalid byte order")
 	}
 	}
 
 
-	dec := newDecoder(rd, order)
+	dec := newDecoder(rd, order, fds)
 	dec.pos = 1
 	dec.pos = 1
 
 
 	msg = new(Message)
 	msg = new(Message)
@@ -166,7 +162,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
 	if hlength+length+16 > 1<<27 {
 	if hlength+length+16 > 1<<27 {
 		return nil, InvalidMessageError("message is too long")
 		return nil, InvalidMessageError("message is too long")
 	}
 	}
-	dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order)
+	dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order, fds)
 	dec.pos = 12
 	dec.pos = 12
 	vs, err = dec.Decode(Signature{"a(yv)"})
 	vs, err = dec.Decode(Signature{"a(yv)"})
 	if err != nil {
 	if err != nil {
@@ -196,7 +192,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
 	sig, _ := msg.Headers[FieldSignature].value.(Signature)
 	sig, _ := msg.Headers[FieldSignature].value.(Signature)
 	if sig.str != "" {
 	if sig.str != "" {
 		buf := bytes.NewBuffer(body)
 		buf := bytes.NewBuffer(body)
-		dec = newDecoder(buf, order)
+		dec = newDecoder(buf, order, fds)
 		vs, err := dec.Decode(sig)
 		vs, err := dec.Decode(sig)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
@@ -207,12 +203,32 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
 	return
 	return
 }
 }
 
 
-// EncodeTo encodes and sends a message to the given writer. The byte order must
-// be either binary.LittleEndian or binary.BigEndian. If the message is not
-// valid or an error occurs when writing, an error is returned.
-func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
+// DecodeMessage tries to decode a single message in the D-Bus wire format
+// from the given reader. The byte order is figured out from the first byte.
+// The possibly returned error can be an error of the underlying reader, an
+// InvalidMessageError or a FormatError.
+func DecodeMessage(rd io.Reader) (msg *Message, err error) {
+	return DecodeMessageWithFDs(rd, make([]int, 0));
+}
+
+type nullwriter struct{}
+
+func (nullwriter) Write(p []byte) (cnt int, err error) {
+	return len(p), nil
+}
+
+func (msg *Message) CountFds() (int, error) {
+	if len(msg.Body) == 0 {
+		return 0, nil
+	}
+	enc := newEncoder(nullwriter{}, nativeEndian, make([]int, 0))
+	err := enc.Encode(msg.Body...)
+	return len(enc.fds), err
+}
+
+func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds []int, err error) {
 	if err := msg.IsValid(); err != nil {
 	if err := msg.IsValid(); err != nil {
-		return err
+		return make([]int, 0), err
 	}
 	}
 	var vs [7]interface{}
 	var vs [7]interface{}
 	switch order {
 	switch order {
@@ -221,12 +237,16 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
 	case binary.BigEndian:
 	case binary.BigEndian:
 		vs[0] = byte('B')
 		vs[0] = byte('B')
 	default:
 	default:
-		return errors.New("dbus: invalid byte order")
+		return make([]int, 0), errors.New("dbus: invalid byte order")
 	}
 	}
 	body := new(bytes.Buffer)
 	body := new(bytes.Buffer)
-	enc := newEncoder(body, order)
+	fds = make([]int, 0)
+	enc := newEncoder(body, order, fds)
 	if len(msg.Body) != 0 {
 	if len(msg.Body) != 0 {
-		enc.Encode(msg.Body...)
+		err = enc.Encode(msg.Body...)
+		if err != nil {
+			return
+		}
 	}
 	}
 	vs[1] = msg.Type
 	vs[1] = msg.Type
 	vs[2] = msg.Flags
 	vs[2] = msg.Flags
@@ -239,17 +259,28 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
 	}
 	}
 	vs[6] = headers
 	vs[6] = headers
 	var buf bytes.Buffer
 	var buf bytes.Buffer
-	enc = newEncoder(&buf, order)
-	enc.Encode(vs[:]...)
+	enc = newEncoder(&buf, order, enc.fds)
+	err = enc.Encode(vs[:]...)
+	if err != nil {
+		return
+	}
 	enc.align(8)
 	enc.align(8)
 	body.WriteTo(&buf)
 	body.WriteTo(&buf)
 	if buf.Len() > 1<<27 {
 	if buf.Len() > 1<<27 {
-		return InvalidMessageError("message is too long")
+		return make([]int, 0), InvalidMessageError("message is too long")
 	}
 	}
 	if _, err := buf.WriteTo(out); err != nil {
 	if _, err := buf.WriteTo(out); err != nil {
-		return err
+		return make([]int, 0), err
 	}
 	}
-	return nil
+	return enc.fds, nil
+}
+
+// EncodeTo encodes and sends a message to the given writer. The byte order must
+// be either binary.LittleEndian or binary.BigEndian. If the message is not
+// valid or an error occurs when writing, an error is returned.
+func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error) {
+	_, err = msg.EncodeToWithFDs(out, order)
+	return err
 }
 }
 
 
 // IsValid checks whether msg is a valid message and returns an
 // IsValid checks whether msg is a valid message and returns an

+ 50 - 16
vendor/github.com/godbus/dbus/v5/sig.go

@@ -34,7 +34,7 @@ type Signature struct {
 func SignatureOf(vs ...interface{}) Signature {
 func SignatureOf(vs ...interface{}) Signature {
 	var s string
 	var s string
 	for _, v := range vs {
 	for _, v := range vs {
-		s += getSignature(reflect.TypeOf(v))
+		s += getSignature(reflect.TypeOf(v), &depthCounter{})
 	}
 	}
 	return Signature{s}
 	return Signature{s}
 }
 }
@@ -42,11 +42,19 @@ func SignatureOf(vs ...interface{}) Signature {
 // SignatureOfType returns the signature of the given type. It panics if the
 // SignatureOfType returns the signature of the given type. It panics if the
 // type is not representable in D-Bus.
 // type is not representable in D-Bus.
 func SignatureOfType(t reflect.Type) Signature {
 func SignatureOfType(t reflect.Type) Signature {
-	return Signature{getSignature(t)}
+	return Signature{getSignature(t, &depthCounter{})}
 }
 }
 
 
 // getSignature returns the signature of the given type and panics on unknown types.
 // getSignature returns the signature of the given type and panics on unknown types.
-func getSignature(t reflect.Type) string {
+func getSignature(t reflect.Type, depth *depthCounter) (sig string) {
+	if !depth.Valid() {
+		panic("container nesting too deep")
+	}
+	defer func() {
+		if len(sig) > 255 {
+			panic("signature exceeds the length limitation")
+		}
+	}()
 	// handle simple types first
 	// handle simple types first
 	switch t.Kind() {
 	switch t.Kind() {
 	case reflect.Uint8:
 	case reflect.Uint8:
@@ -74,7 +82,7 @@ func getSignature(t reflect.Type) string {
 	case reflect.Float64:
 	case reflect.Float64:
 		return "d"
 		return "d"
 	case reflect.Ptr:
 	case reflect.Ptr:
-		return getSignature(t.Elem())
+		return getSignature(t.Elem(), depth)
 	case reflect.String:
 	case reflect.String:
 		if t == objectPathType {
 		if t == objectPathType {
 			return "o"
 			return "o"
@@ -90,17 +98,20 @@ func getSignature(t reflect.Type) string {
 		for i := 0; i < t.NumField(); i++ {
 		for i := 0; i < t.NumField(); i++ {
 			field := t.Field(i)
 			field := t.Field(i)
 			if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
 			if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
-				s += getSignature(t.Field(i).Type)
+				s += getSignature(t.Field(i).Type, depth.EnterStruct())
 			}
 			}
 		}
 		}
+		if len(s) == 0 {
+			panic("empty struct")
+		}
 		return "(" + s + ")"
 		return "(" + s + ")"
 	case reflect.Array, reflect.Slice:
 	case reflect.Array, reflect.Slice:
-		return "a" + getSignature(t.Elem())
+		return "a" + getSignature(t.Elem(), depth.EnterArray())
 	case reflect.Map:
 	case reflect.Map:
 		if !isKeyType(t.Key()) {
 		if !isKeyType(t.Key()) {
 			panic(InvalidTypeError{t})
 			panic(InvalidTypeError{t})
 		}
 		}
-		return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
+		return "a{" + getSignature(t.Key(), depth.EnterArray().EnterDictEntry()) + getSignature(t.Elem(), depth.EnterArray().EnterDictEntry()) + "}"
 	case reflect.Interface:
 	case reflect.Interface:
 		return "v"
 		return "v"
 	}
 	}
@@ -118,7 +129,7 @@ func ParseSignature(s string) (sig Signature, err error) {
 	}
 	}
 	sig.str = s
 	sig.str = s
 	for err == nil && len(s) != 0 {
 	for err == nil && len(s) != 0 {
-		err, s = validSingle(s, 0)
+		err, s = validSingle(s, &depthCounter{})
 	}
 	}
 	if err != nil {
 	if err != nil {
 		sig = Signature{""}
 		sig = Signature{""}
@@ -144,7 +155,7 @@ func (s Signature) Empty() bool {
 
 
 // Single returns whether the signature represents a single, complete type.
 // Single returns whether the signature represents a single, complete type.
 func (s Signature) Single() bool {
 func (s Signature) Single() bool {
-	err, r := validSingle(s.str, 0)
+	err, r := validSingle(s.str, &depthCounter{})
 	return err != nil && r == ""
 	return err != nil && r == ""
 }
 }
 
 
@@ -164,15 +175,38 @@ func (e SignatureError) Error() string {
 	return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
 	return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
 }
 }
 
 
+type depthCounter struct {
+	arrayDepth, structDepth, dictEntryDepth int
+}
+
+func (cnt *depthCounter) Valid() bool {
+	return cnt.arrayDepth <= 32 && cnt.structDepth <= 32 && cnt.dictEntryDepth <= 32
+}
+
+func (cnt depthCounter) EnterArray() *depthCounter {
+	cnt.arrayDepth++
+	return &cnt
+}
+
+func (cnt depthCounter) EnterStruct() *depthCounter {
+	cnt.structDepth++
+	return &cnt
+}
+
+func (cnt depthCounter) EnterDictEntry() *depthCounter {
+	cnt.dictEntryDepth++
+	return &cnt
+}
+
 // Try to read a single type from this string. If it was successful, err is nil
 // Try to read a single type from this string. If it was successful, err is nil
 // and rem is the remaining unparsed part. Otherwise, err is a non-nil
 // and rem is the remaining unparsed part. Otherwise, err is a non-nil
 // SignatureError and rem is "". depth is the current recursion depth which may
 // SignatureError and rem is "". depth is the current recursion depth which may
 // not be greater than 64 and should be given as 0 on the first call.
 // not be greater than 64 and should be given as 0 on the first call.
-func validSingle(s string, depth int) (err error, rem string) {
+func validSingle(s string, depth *depthCounter) (err error, rem string) {
 	if s == "" {
 	if s == "" {
 		return SignatureError{Sig: s, Reason: "empty signature"}, ""
 		return SignatureError{Sig: s, Reason: "empty signature"}, ""
 	}
 	}
-	if depth > 64 {
+	if !depth.Valid() {
 		return SignatureError{Sig: s, Reason: "container nesting too deep"}, ""
 		return SignatureError{Sig: s, Reason: "container nesting too deep"}, ""
 	}
 	}
 	switch s[0] {
 	switch s[0] {
@@ -187,10 +221,10 @@ func validSingle(s string, depth int) (err error, rem string) {
 			i++
 			i++
 			rem = s[i+1:]
 			rem = s[i+1:]
 			s = s[2:i]
 			s = s[2:i]
-			if err, _ = validSingle(s[:1], depth+1); err != nil {
+			if err, _ = validSingle(s[:1], depth.EnterArray().EnterDictEntry()); err != nil {
 				return err, ""
 				return err, ""
 			}
 			}
-			err, nr := validSingle(s[1:], depth+1)
+			err, nr := validSingle(s[1:], depth.EnterArray().EnterDictEntry())
 			if err != nil {
 			if err != nil {
 				return err, ""
 				return err, ""
 			}
 			}
@@ -199,7 +233,7 @@ func validSingle(s string, depth int) (err error, rem string) {
 			}
 			}
 			return nil, rem
 			return nil, rem
 		}
 		}
-		return validSingle(s[1:], depth+1)
+		return validSingle(s[1:], depth.EnterArray())
 	case '(':
 	case '(':
 		i := findMatching(s, '(', ')')
 		i := findMatching(s, '(', ')')
 		if i == -1 {
 		if i == -1 {
@@ -208,7 +242,7 @@ func validSingle(s string, depth int) (err error, rem string) {
 		rem = s[i+1:]
 		rem = s[i+1:]
 		s = s[1:i]
 		s = s[1:i]
 		for err == nil && s != "" {
 		for err == nil && s != "" {
-			err, s = validSingle(s, depth+1)
+			err, s = validSingle(s, depth.EnterStruct())
 		}
 		}
 		if err != nil {
 		if err != nil {
 			rem = ""
 			rem = ""
@@ -236,7 +270,7 @@ func findMatching(s string, left, right rune) int {
 // typeFor returns the type of the given signature. It ignores any left over
 // typeFor returns the type of the given signature. It ignores any left over
 // characters and panics if s doesn't start with a valid type signature.
 // characters and panics if s doesn't start with a valid type signature.
 func typeFor(s string) (t reflect.Type) {
 func typeFor(s string) (t reflect.Type) {
-	err, _ := validSingle(s, 0)
+	err, _ := validSingle(s, &depthCounter{})
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)
 	}
 	}

+ 6 - 4
vendor/github.com/godbus/dbus/v5/transport_generic.go

@@ -41,10 +41,12 @@ func (t genericTransport) ReadMessage() (*Message, error) {
 }
 }
 
 
 func (t genericTransport) SendMessage(msg *Message) error {
 func (t genericTransport) SendMessage(msg *Message) error {
-	for _, v := range msg.Body {
-		if _, ok := v.(UnixFD); ok {
-			return errors.New("dbus: unix fd passing not enabled")
-		}
+	fds, err := msg.CountFds()
+	if err != nil {
+		return err
+	}
+	if fds != 0 {
+		return errors.New("dbus: unix fd passing not enabled")
 	}
 	}
 	return msg.EncodeTo(t, nativeEndian)
 	return msg.EncodeTo(t, nativeEndian)
 }
 }

+ 12 - 12
vendor/github.com/godbus/dbus/v5/transport_unix.go

@@ -113,7 +113,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
 	if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil {
 	if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	dec := newDecoder(bytes.NewBuffer(headerdata), order)
+	dec := newDecoder(bytes.NewBuffer(headerdata), order, make([]int, 0))
 	dec.pos = 12
 	dec.pos = 12
 	vs, err := dec.Decode(Signature{"a(yv)"})
 	vs, err := dec.Decode(Signature{"a(yv)"})
 	if err != nil {
 	if err != nil {
@@ -147,7 +147,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
-		msg, err := DecodeMessage(bytes.NewBuffer(all))
+		msg, err := DecodeMessageWithFDs(bytes.NewBuffer(all), fds)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -179,21 +179,21 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
 }
 }
 
 
 func (t *unixTransport) SendMessage(msg *Message) error {
 func (t *unixTransport) SendMessage(msg *Message) error {
-	fds := make([]int, 0)
-	for i, v := range msg.Body {
-		if fd, ok := v.(UnixFD); ok {
-			msg.Body[i] = UnixFDIndex(len(fds))
-			fds = append(fds, int(fd))
-		}
+	fdcnt, err := msg.CountFds()
+	if err != nil {
+		return err
 	}
 	}
-	if len(fds) != 0 {
+	if fdcnt != 0 {
 		if !t.hasUnixFDs {
 		if !t.hasUnixFDs {
 			return errors.New("dbus: unix fd passing not enabled")
 			return errors.New("dbus: unix fd passing not enabled")
 		}
 		}
-		msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds)))
-		oob := syscall.UnixRights(fds...)
+		msg.Headers[FieldUnixFDs] = MakeVariant(uint32(fdcnt))
 		buf := new(bytes.Buffer)
 		buf := new(bytes.Buffer)
-		msg.EncodeTo(buf, nativeEndian)
+		fds, err := msg.EncodeToWithFDs(buf, nativeEndian)
+		if err != nil {
+			return err
+		}
+		oob := syscall.UnixRights(fds...)
 		n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
 		n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
 		if err != nil {
 		if err != nil {
 			return err
 			return err

+ 14 - 0
vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go

@@ -0,0 +1,14 @@
+package dbus
+
+import "io"
+
+func (t *unixTransport) SendNullByte() error {
+	n, _, err := t.UnixConn.WriteMsgUnix([]byte{0}, nil, nil)
+	if err != nil {
+		return err
+	}
+	if n != 1 {
+		return io.ErrShortWrite
+	}
+	return nil
+}

+ 0 - 2
vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go

@@ -1,5 +1,3 @@
-// +build linux
-
 package cgroups
 package cgroups
 
 
 import (
 import (

+ 0 - 3
vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go

@@ -1,3 +0,0 @@
-// +build !linux
-
-package cgroups

+ 42 - 18
vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go

@@ -2,20 +2,27 @@ package cgroups
 
 
 import (
 import (
 	"bytes"
 	"bytes"
+	"errors"
+	"fmt"
 	"os"
 	"os"
+	"path"
+	"strconv"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 
 
-	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/sys/unix"
 	"golang.org/x/sys/unix"
 )
 )
 
 
 // OpenFile opens a cgroup file in a given dir with given flags.
 // OpenFile opens a cgroup file in a given dir with given flags.
-// It is supposed to be used for cgroup files only.
+// It is supposed to be used for cgroup files only, and returns
+// an error if the file is not a cgroup file.
+//
+// Arguments dir and file are joined together to form an absolute path
+// to a file being opened.
 func OpenFile(dir, file string, flags int) (*os.File, error) {
 func OpenFile(dir, file string, flags int) (*os.File, error) {
 	if dir == "" {
 	if dir == "" {
-		return nil, errors.Errorf("no directory specified for %s", file)
+		return nil, fmt.Errorf("no directory specified for %s", file)
 	}
 	}
 	return openFile(dir, file, flags)
 	return openFile(dir, file, flags)
 }
 }
@@ -43,7 +50,8 @@ func WriteFile(dir, file, data string) error {
 	}
 	}
 	defer fd.Close()
 	defer fd.Close()
 	if err := retryingWriteFile(fd, data); err != nil {
 	if err := retryingWriteFile(fd, data); err != nil {
-		return errors.Wrapf(err, "failed to write %q", data)
+		// Having data in the error message helps in debugging.
+		return fmt.Errorf("failed to write %q: %w", data, err)
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -81,7 +89,7 @@ func prepareOpenat2() error {
 		})
 		})
 		if err != nil {
 		if err != nil {
 			prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
 			prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
-			if err != unix.ENOSYS {
+			if err != unix.ENOSYS { //nolint:errorlint // unix errors are bare
 				logrus.Warnf("falling back to securejoin: %s", prepErr)
 				logrus.Warnf("falling back to securejoin: %s", prepErr)
 			} else {
 			} else {
 				logrus.Debug("openat2 not available, falling back to securejoin")
 				logrus.Debug("openat2 not available, falling back to securejoin")
@@ -107,8 +115,6 @@ func prepareOpenat2() error {
 	return prepErr
 	return prepErr
 }
 }
 
 
-// OpenFile opens a cgroup file in a given dir with given flags.
-// It is supposed to be used for cgroup files only.
 func openFile(dir, file string, flags int) (*os.File, error) {
 func openFile(dir, file string, flags int) (*os.File, error) {
 	mode := os.FileMode(0)
 	mode := os.FileMode(0)
 	if TestMode && flags&os.O_WRONLY != 0 {
 	if TestMode && flags&os.O_WRONLY != 0 {
@@ -116,34 +122,52 @@ func openFile(dir, file string, flags int) (*os.File, error) {
 		flags |= os.O_TRUNC | os.O_CREATE
 		flags |= os.O_TRUNC | os.O_CREATE
 		mode = 0o600
 		mode = 0o600
 	}
 	}
+	path := path.Join(dir, file)
 	if prepareOpenat2() != nil {
 	if prepareOpenat2() != nil {
-		return openFallback(dir, file, flags, mode)
+		return openFallback(path, flags, mode)
 	}
 	}
-	reldir := strings.TrimPrefix(dir, cgroupfsPrefix)
-	if len(reldir) == len(dir) { // non-standard path, old system?
-		return openFallback(dir, file, flags, mode)
+	relPath := strings.TrimPrefix(path, cgroupfsPrefix)
+	if len(relPath) == len(path) { // non-standard path, old system?
+		return openFallback(path, flags, mode)
 	}
 	}
 
 
-	relname := reldir + "/" + file
-	fd, err := unix.Openat2(cgroupFd, relname,
+	fd, err := unix.Openat2(cgroupFd, relPath,
 		&unix.OpenHow{
 		&unix.OpenHow{
 			Resolve: resolveFlags,
 			Resolve: resolveFlags,
 			Flags:   uint64(flags) | unix.O_CLOEXEC,
 			Flags:   uint64(flags) | unix.O_CLOEXEC,
 			Mode:    uint64(mode),
 			Mode:    uint64(mode),
 		})
 		})
 	if err != nil {
 	if err != nil {
-		return nil, &os.PathError{Op: "openat2", Path: dir + "/" + file, Err: err}
+		err = &os.PathError{Op: "openat2", Path: path, Err: err}
+		// Check if cgroupFd is still opened to cgroupfsDir
+		// (happens when this package is incorrectly used
+		// across the chroot/pivot_root/mntns boundary, or
+		// when /sys/fs/cgroup is remounted).
+		//
+		// TODO: if such usage will ever be common, amend this
+		// to reopen cgroupFd and retry openat2.
+		fdStr := strconv.Itoa(cgroupFd)
+		fdDest, _ := os.Readlink("/proc/self/fd/" + fdStr)
+		if fdDest != cgroupfsDir {
+			// Wrap the error so it is clear that cgroupFd
+			// is opened to an unexpected/wrong directory.
+			err = fmt.Errorf("cgroupFd %s unexpectedly opened to %s != %s: %w",
+				fdStr, fdDest, cgroupfsDir, err)
+		}
+		return nil, err
 	}
 	}
 
 
-	return os.NewFile(uintptr(fd), cgroupfsPrefix+relname), nil
+	return os.NewFile(uintptr(fd), path), nil
 }
 }
 
 
 var errNotCgroupfs = errors.New("not a cgroup file")
 var errNotCgroupfs = errors.New("not a cgroup file")
 
 
-// openFallback is used when openat2(2) is not available. It checks the opened
+// Can be changed by unit tests.
+var openFallback = openAndCheck
+
+// openAndCheck is used when openat2(2) is not available. It checks the opened
 // file is on cgroupfs, returning an error otherwise.
 // file is on cgroupfs, returning an error otherwise.
-func openFallback(dir, file string, flags int, mode os.FileMode) (*os.File, error) {
-	path := dir + "/" + file
+func openAndCheck(path string, flags int, mode os.FileMode) (*os.File, error) {
 	fd, err := os.OpenFile(path, flags, mode)
 	fd, err := os.OpenFile(path, flags, mode)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err

+ 27 - 0
vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go

@@ -0,0 +1,27 @@
+package cgroups
+
+import (
+	"io/fs"
+	"path/filepath"
+)
+
+// GetAllPids returns all pids from the cgroup identified by path, and all its
+// sub-cgroups.
+func GetAllPids(path string) ([]int, error) {
+	var pids []int
+	err := filepath.WalkDir(path, func(p string, d fs.DirEntry, iErr error) error {
+		if iErr != nil {
+			return iErr
+		}
+		if !d.IsDir() {
+			return nil
+		}
+		cPids, err := readProcsFile(p)
+		if err != nil {
+			return err
+		}
+		pids = append(pids, cPids...)
+		return nil
+	})
+	return pids, err
+}

+ 13 - 3
vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go

@@ -1,5 +1,3 @@
-// +build linux
-
 package cgroups
 package cgroups
 
 
 type ThrottlingData struct {
 type ThrottlingData struct {
@@ -126,7 +124,7 @@ type BlkioStatEntry struct {
 }
 }
 
 
 type BlkioStats struct {
 type BlkioStats struct {
-	// number of bytes tranferred to and from the block device
+	// number of bytes transferred to and from the block device
 	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
 	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
 	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
 	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
 	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
 	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
@@ -146,6 +144,17 @@ type HugetlbStats struct {
 	Failcnt uint64 `json:"failcnt"`
 	Failcnt uint64 `json:"failcnt"`
 }
 }
 
 
+type RdmaEntry struct {
+	Device     string `json:"device,omitempty"`
+	HcaHandles uint32 `json:"hca_handles,omitempty"`
+	HcaObjects uint32 `json:"hca_objects,omitempty"`
+}
+
+type RdmaStats struct {
+	RdmaLimit   []RdmaEntry `json:"rdma_limit,omitempty"`
+	RdmaCurrent []RdmaEntry `json:"rdma_current,omitempty"`
+}
+
 type Stats struct {
 type Stats struct {
 	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
 	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
 	CPUSetStats CPUSetStats `json:"cpuset_stats,omitempty"`
 	CPUSetStats CPUSetStats `json:"cpuset_stats,omitempty"`
@@ -154,6 +163,7 @@ type Stats struct {
 	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
 	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
 	// the map is in the format "size of hugepage: stats of the hugepage"
 	// the map is in the format "size of hugepage: stats of the hugepage"
 	HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitempty"`
 	HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitempty"`
+	RdmaStats    RdmaStats               `json:"rdma_stats,omitempty"`
 }
 }
 
 
 func NewStats() *Stats {
 func NewStats() *Stats {

+ 66 - 49
vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go

@@ -1,5 +1,3 @@
-// +build linux
-
 package cgroups
 package cgroups
 
 
 import (
 import (
@@ -7,7 +5,6 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
-	"io/ioutil"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"strconv"
 	"strconv"
@@ -23,11 +20,14 @@ import (
 const (
 const (
 	CgroupProcesses   = "cgroup.procs"
 	CgroupProcesses   = "cgroup.procs"
 	unifiedMountpoint = "/sys/fs/cgroup"
 	unifiedMountpoint = "/sys/fs/cgroup"
+	hybridMountpoint  = "/sys/fs/cgroup/unified"
 )
 )
 
 
 var (
 var (
 	isUnifiedOnce sync.Once
 	isUnifiedOnce sync.Once
 	isUnified     bool
 	isUnified     bool
+	isHybridOnce  sync.Once
+	isHybrid      bool
 )
 )
 
 
 // IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
 // IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
@@ -49,6 +49,24 @@ func IsCgroup2UnifiedMode() bool {
 	return isUnified
 	return isUnified
 }
 }
 
 
+// IsCgroup2HybridMode returns whether we are running in cgroup v2 hybrid mode.
+func IsCgroup2HybridMode() bool {
+	isHybridOnce.Do(func() {
+		var st unix.Statfs_t
+		err := unix.Statfs(hybridMountpoint, &st)
+		if err != nil {
+			if os.IsNotExist(err) {
+				// ignore the "not found" error
+				isHybrid = false
+				return
+			}
+			panic(fmt.Sprintf("cannot statfs cgroup root: %s", err))
+		}
+		isHybrid = st.Type == unix.CGROUP2_SUPER_MAGIC
+	})
+	return isHybrid
+}
+
 type Mount struct {
 type Mount struct {
 	Mountpoint string
 	Mountpoint string
 	Root       string
 	Root       string
@@ -118,8 +136,8 @@ func GetAllSubsystems() ([]string, error) {
 	return subsystems, nil
 	return subsystems, nil
 }
 }
 
 
-func readProcsFile(file string) ([]int, error) {
-	f, err := os.Open(file)
+func readProcsFile(dir string) ([]int, error) {
+	f, err := OpenFile(dir, CgroupProcesses, os.O_RDONLY)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -210,7 +228,7 @@ func EnterPid(cgroupPaths map[string]string, pid int) error {
 
 
 func rmdir(path string) error {
 func rmdir(path string) error {
 	err := unix.Rmdir(path)
 	err := unix.Rmdir(path)
-	if err == nil || err == unix.ENOENT {
+	if err == nil || err == unix.ENOENT { //nolint:errorlint // unix errors are bare
 		return nil
 		return nil
 	}
 	}
 	return &os.PathError{Op: "rmdir", Path: path, Err: err}
 	return &os.PathError{Op: "rmdir", Path: path, Err: err}
@@ -224,7 +242,7 @@ func RemovePath(path string) error {
 		return nil
 		return nil
 	}
 	}
 
 
-	infos, err := ioutil.ReadDir(path)
+	infos, err := os.ReadDir(path)
 	if err != nil {
 	if err != nil {
 		if os.IsNotExist(err) {
 		if os.IsNotExist(err) {
 			err = nil
 			err = nil
@@ -284,40 +302,61 @@ func RemovePaths(paths map[string]string) (err error) {
 	return fmt.Errorf("Failed to remove paths: %v", paths)
 	return fmt.Errorf("Failed to remove paths: %v", paths)
 }
 }
 
 
-func GetHugePageSize() ([]string, error) {
-	dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
-	if err != nil {
-		return nil, err
-	}
-	files, err := dir.Readdirnames(0)
-	dir.Close()
-	if err != nil {
-		return nil, err
-	}
+var (
+	hugePageSizes []string
+	initHPSOnce   sync.Once
+)
 
 
-	return getHugePageSizeFromFilenames(files)
+func HugePageSizes() []string {
+	initHPSOnce.Do(func() {
+		dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
+		if err != nil {
+			return
+		}
+		files, err := dir.Readdirnames(0)
+		dir.Close()
+		if err != nil {
+			return
+		}
+
+		hugePageSizes, err = getHugePageSizeFromFilenames(files)
+		if err != nil {
+			logrus.Warn("HugePageSizes: ", err)
+		}
+	})
+
+	return hugePageSizes
 }
 }
 
 
 func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
 func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
 	pageSizes := make([]string, 0, len(fileNames))
 	pageSizes := make([]string, 0, len(fileNames))
+	var warn error
 
 
 	for _, file := range fileNames {
 	for _, file := range fileNames {
 		// example: hugepages-1048576kB
 		// example: hugepages-1048576kB
 		val := strings.TrimPrefix(file, "hugepages-")
 		val := strings.TrimPrefix(file, "hugepages-")
 		if len(val) == len(file) {
 		if len(val) == len(file) {
-			// unexpected file name: no prefix found
+			// Unexpected file name: no prefix found, ignore it.
 			continue
 			continue
 		}
 		}
-		// The suffix is always "kB" (as of Linux 5.9)
+		// The suffix is always "kB" (as of Linux 5.13). If we find
+		// something else, produce an error but keep going.
 		eLen := len(val) - 2
 		eLen := len(val) - 2
 		val = strings.TrimSuffix(val, "kB")
 		val = strings.TrimSuffix(val, "kB")
 		if len(val) != eLen {
 		if len(val) != eLen {
-			logrus.Warnf("GetHugePageSize: %s: invalid filename suffix (expected \"kB\")", file)
+			// Highly unlikely.
+			if warn == nil {
+				warn = errors.New(file + `: invalid suffix (expected "kB")`)
+			}
 			continue
 			continue
 		}
 		}
 		size, err := strconv.Atoi(val)
 		size, err := strconv.Atoi(val)
 		if err != nil {
 		if err != nil {
-			return nil, err
+			// Highly unlikely.
+			if warn == nil {
+				warn = fmt.Errorf("%s: %w", file, err)
+			}
+			continue
 		}
 		}
 		// Model after https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/hugetlb_cgroup.c?id=eff48ddeab782e35e58ccc8853f7386bbae9dec4#n574
 		// Model after https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/hugetlb_cgroup.c?id=eff48ddeab782e35e58ccc8853f7386bbae9dec4#n574
 		// but in our case the size is in KB already.
 		// but in our case the size is in KB already.
@@ -331,34 +370,12 @@ func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
 		pageSizes = append(pageSizes, val)
 		pageSizes = append(pageSizes, val)
 	}
 	}
 
 
-	return pageSizes, nil
+	return pageSizes, warn
 }
 }
 
 
 // GetPids returns all pids, that were added to cgroup at path.
 // GetPids returns all pids, that were added to cgroup at path.
 func GetPids(dir string) ([]int, error) {
 func GetPids(dir string) ([]int, error) {
-	return readProcsFile(filepath.Join(dir, CgroupProcesses))
-}
-
-// GetAllPids returns all pids, that were added to cgroup at path and to all its
-// subcgroups.
-func GetAllPids(path string) ([]int, error) {
-	var pids []int
-	// collect pids from all sub-cgroups
-	err := filepath.Walk(path, func(p string, info os.FileInfo, iErr error) error {
-		if iErr != nil {
-			return iErr
-		}
-		if info.IsDir() || info.Name() != CgroupProcesses {
-			return nil
-		}
-		cPids, err := readProcsFile(p)
-		if err != nil {
-			return err
-		}
-		pids = append(pids, cPids...)
-		return nil
-	})
-	return pids, err
+	return readProcsFile(dir)
 }
 }
 
 
 // WriteCgroupProc writes the specified pid into the cgroup's cgroup.procs file
 // WriteCgroupProc writes the specified pid into the cgroup's cgroup.procs file
@@ -376,7 +393,7 @@ func WriteCgroupProc(dir string, pid int) error {
 
 
 	file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY)
 	file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY)
 	if err != nil {
 	if err != nil {
-		return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
+		return fmt.Errorf("failed to write %v: %w", pid, err)
 	}
 	}
 	defer file.Close()
 	defer file.Close()
 
 
@@ -393,7 +410,7 @@ func WriteCgroupProc(dir string, pid int) error {
 			continue
 			continue
 		}
 		}
 
 
-		return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
+		return fmt.Errorf("failed to write %v: %w", pid, err)
 	}
 	}
 	return err
 	return err
 }
 }
@@ -446,5 +463,5 @@ func ConvertBlkIOToIOWeightValue(blkIoWeight uint16) uint64 {
 	if blkIoWeight == 0 {
 	if blkIoWeight == 0 {
 		return 0
 		return 0
 	}
 	}
-	return uint64(1 + (uint64(blkIoWeight)-10)*9999/990)
+	return 1 + (uint64(blkIoWeight)-10)*9999/990
 }
 }

+ 13 - 6
vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go

@@ -46,11 +46,8 @@ func NewNotFoundError(sub string) error {
 }
 }
 
 
 func IsNotFound(err error) bool {
 func IsNotFound(err error) bool {
-	if err == nil {
-		return false
-	}
-	_, ok := err.(*NotFoundError)
-	return ok
+	var nfErr *NotFoundError
+	return errors.As(err, &nfErr)
 }
 }
 
 
 func tryDefaultPath(cgroupPath, subsystem string) string {
 func tryDefaultPath(cgroupPath, subsystem string) string {
@@ -116,6 +113,11 @@ func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
 		return "", errUnified
 		return "", errUnified
 	}
 	}
 
 
+	// If subsystem is empty, we look for the cgroupv2 hybrid path.
+	if len(subsystem) == 0 {
+		return hybridMountpoint, nil
+	}
+
 	// Avoid parsing mountinfo by trying the default path first, if possible.
 	// Avoid parsing mountinfo by trying the default path first, if possible.
 	if path := tryDefaultPath(cgroupPath, subsystem); path != "" {
 	if path := tryDefaultPath(cgroupPath, subsystem); path != "" {
 		return path, nil
 		return path, nil
@@ -154,7 +156,7 @@ func findCgroupMountpointAndRootFromMI(mounts []*mountinfo.Info, cgroupPath, sub
 
 
 func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
 func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
 	if len(m.Subsystems) == 0 {
 	if len(m.Subsystems) == 0 {
-		return "", fmt.Errorf("no subsystem for mount")
+		return "", errors.New("no subsystem for mount")
 	}
 	}
 
 
 	return getControllerPath(m.Subsystems[0], cgroups)
 	return getControllerPath(m.Subsystems[0], cgroups)
@@ -226,6 +228,11 @@ func GetOwnCgroupPath(subsystem string) (string, error) {
 		return "", err
 		return "", err
 	}
 	}
 
 
+	// If subsystem is empty, we look for the cgroupv2 hybrid path.
+	if len(subsystem) == 0 {
+		return hybridMountpoint, nil
+	}
+
 	return getCgroupPathHelper(subsystem, cgroup)
 	return getCgroupPathHelper(subsystem, cgroup)
 }
 }
 
 

+ 16 - 4
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go

@@ -28,17 +28,26 @@ type Cgroup struct {
 	// ScopePrefix describes prefix for the scope name
 	// ScopePrefix describes prefix for the scope name
 	ScopePrefix string `json:"scope_prefix"`
 	ScopePrefix string `json:"scope_prefix"`
 
 
-	// Paths represent the absolute cgroups paths to join.
-	// This takes precedence over Path.
-	Paths map[string]string
-
 	// Resources contains various cgroups settings to apply
 	// Resources contains various cgroups settings to apply
 	*Resources
 	*Resources
 
 
+	// Systemd tells if systemd should be used to manage cgroups.
+	Systemd bool
+
 	// SystemdProps are any additional properties for systemd,
 	// SystemdProps are any additional properties for systemd,
 	// derived from org.systemd.property.xxx annotations.
 	// derived from org.systemd.property.xxx annotations.
 	// Ignored unless systemd is used for managing cgroups.
 	// Ignored unless systemd is used for managing cgroups.
 	SystemdProps []systemdDbus.Property `json:"-"`
 	SystemdProps []systemdDbus.Property `json:"-"`
+
+	// Rootless tells if rootless cgroups should be used.
+	Rootless bool
+
+	// The host UID that should own the cgroup, or nil to accept
+	// the default ownership.  This should only be set when the
+	// cgroupfs is to be mounted read/write.
+	// Not all cgroup manager implementations support changing
+	// the ownership.
+	OwnerUID *int `json:"owner_uid,omitempty"`
 }
 }
 
 
 type Resources struct {
 type Resources struct {
@@ -117,6 +126,9 @@ type Resources struct {
 	// Set class identifier for container's network packets
 	// Set class identifier for container's network packets
 	NetClsClassid uint32 `json:"net_cls_classid_u"`
 	NetClsClassid uint32 `json:"net_cls_classid_u"`
 
 
+	// Rdma resource restriction configuration
+	Rdma map[string]LinuxRdma `json:"rdma"`
+
 	// Used on cgroups v2:
 	// Used on cgroups v2:
 
 
 	// CpuWeight sets a proportional bandwidth limit.
 	// CpuWeight sets a proportional bandwidth limit.

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go

@@ -1,3 +1,4 @@
+//go:build !linux
 // +build !linux
 // +build !linux
 
 
 package configs
 package configs

+ 26 - 8
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go

@@ -7,10 +7,10 @@ import (
 	"os/exec"
 	"os/exec"
 	"time"
 	"time"
 
 
+	"github.com/sirupsen/logrus"
+
 	"github.com/opencontainers/runc/libcontainer/devices"
 	"github.com/opencontainers/runc/libcontainer/devices"
 	"github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/opencontainers/runtime-spec/specs-go"
-	"github.com/pkg/errors"
-	"github.com/sirupsen/logrus"
 )
 )
 
 
 type Rlimit struct {
 type Rlimit struct {
@@ -31,10 +31,12 @@ type IDMap struct {
 // for syscalls. Additional architectures can be added by specifying them in
 // for syscalls. Additional architectures can be added by specifying them in
 // Architectures.
 // Architectures.
 type Seccomp struct {
 type Seccomp struct {
-	DefaultAction   Action     `json:"default_action"`
-	Architectures   []string   `json:"architectures"`
-	Syscalls        []*Syscall `json:"syscalls"`
-	DefaultErrnoRet *uint      `json:"default_errno_ret"`
+	DefaultAction    Action     `json:"default_action"`
+	Architectures    []string   `json:"architectures"`
+	Syscalls         []*Syscall `json:"syscalls"`
+	DefaultErrnoRet  *uint      `json:"default_errno_ret"`
+	ListenerPath     string     `json:"listener_path,omitempty"`
+	ListenerMetadata string     `json:"listener_metadata,omitempty"`
 }
 }
 
 
 // Action is taken upon rule match in Seccomp
 // Action is taken upon rule match in Seccomp
@@ -47,6 +49,9 @@ const (
 	Allow
 	Allow
 	Trace
 	Trace
 	Log
 	Log
+	Notify
+	KillThread
+	KillProcess
 )
 )
 
 
 // Operator is a comparison operator to be used when matching syscall arguments in Seccomp
 // Operator is a comparison operator to be used when matching syscall arguments in Seccomp
@@ -246,6 +251,19 @@ const (
 	Poststop HookName = "poststop"
 	Poststop HookName = "poststop"
 )
 )
 
 
+// KnownHookNames returns the known hook names.
+// Used by `runc features`.
+func KnownHookNames() []string {
+	return []string{
+		string(Prestart), // deprecated
+		string(CreateRuntime),
+		string(CreateContainer),
+		string(StartContainer),
+		string(Poststart),
+		string(Poststop),
+	}
+}
+
 type Capabilities struct {
 type Capabilities struct {
 	// Bounding is the set of capabilities checked by the kernel.
 	// Bounding is the set of capabilities checked by the kernel.
 	Bounding []string
 	Bounding []string
@@ -262,7 +280,7 @@ type Capabilities struct {
 func (hooks HookList) RunHooks(state *specs.State) error {
 func (hooks HookList) RunHooks(state *specs.State) error {
 	for i, h := range hooks {
 	for i, h := range hooks {
 		if err := h.Run(state); err != nil {
 		if err := h.Run(state); err != nil {
-			return errors.Wrapf(err, "Running hook #%d:", i)
+			return fmt.Errorf("error running hook #%d: %w", i, err)
 		}
 		}
 	}
 	}
 
 
@@ -375,7 +393,7 @@ func (c Command) Run(s *specs.State) error {
 	go func() {
 	go func() {
 		err := cmd.Wait()
 		err := cmd.Wait()
 		if err != nil {
 		if err != nil {
-			err = fmt.Errorf("error running hook: %v, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
+			err = fmt.Errorf("error running hook: %w, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
 		}
 		}
 		errC <- err
 		errC <- err
 	}()
 	}()

+ 12 - 5
vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go

@@ -1,17 +1,24 @@
 package configs
 package configs
 
 
-import "fmt"
+import "errors"
+
+var (
+	errNoUIDMap   = errors.New("User namespaces enabled, but no uid mappings found.")
+	errNoUserMap  = errors.New("User namespaces enabled, but no user mapping found.")
+	errNoGIDMap   = errors.New("User namespaces enabled, but no gid mappings found.")
+	errNoGroupMap = errors.New("User namespaces enabled, but no group mapping found.")
+)
 
 
 // HostUID gets the translated uid for the process on host which could be
 // HostUID gets the translated uid for the process on host which could be
 // different when user namespaces are enabled.
 // different when user namespaces are enabled.
 func (c Config) HostUID(containerId int) (int, error) {
 func (c Config) HostUID(containerId int) (int, error) {
 	if c.Namespaces.Contains(NEWUSER) {
 	if c.Namespaces.Contains(NEWUSER) {
 		if c.UidMappings == nil {
 		if c.UidMappings == nil {
-			return -1, fmt.Errorf("User namespaces enabled, but no uid mappings found.")
+			return -1, errNoUIDMap
 		}
 		}
 		id, found := c.hostIDFromMapping(containerId, c.UidMappings)
 		id, found := c.hostIDFromMapping(containerId, c.UidMappings)
 		if !found {
 		if !found {
-			return -1, fmt.Errorf("User namespaces enabled, but no user mapping found.")
+			return -1, errNoUserMap
 		}
 		}
 		return id, nil
 		return id, nil
 	}
 	}
@@ -30,11 +37,11 @@ func (c Config) HostRootUID() (int, error) {
 func (c Config) HostGID(containerId int) (int, error) {
 func (c Config) HostGID(containerId int) (int, error) {
 	if c.Namespaces.Contains(NEWUSER) {
 	if c.Namespaces.Contains(NEWUSER) {
 		if c.GidMappings == nil {
 		if c.GidMappings == nil {
-			return -1, fmt.Errorf("User namespaces enabled, but no gid mappings found.")
+			return -1, errNoGIDMap
 		}
 		}
 		id, found := c.hostIDFromMapping(containerId, c.GidMappings)
 		id, found := c.hostIDFromMapping(containerId, c.GidMappings)
 		if !found {
 		if !found {
-			return -1, fmt.Errorf("User namespaces enabled, but no group mapping found.")
+			return -1, errNoGroupMap
 		}
 		}
 		return id, nil
 		return id, nil
 	}
 	}

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go

@@ -1,3 +1,4 @@
+//go:build gofuzz
 // +build gofuzz
 // +build gofuzz
 
 
 package configs
 package configs

+ 3 - 0
vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go

@@ -1,6 +1,9 @@
 package configs
 package configs
 
 
 type IntelRdt struct {
 type IntelRdt struct {
+	// The identity for RDT Class of Service
+	ClosID string `json:"closID,omitempty"`
+
 	// The schema for L3 cache id and capacity bitmask (CBM)
 	// The schema for L3 cache id and capacity bitmask (CBM)
 	// Format: "L3:<cache_id0>=<cbm0>;<cache_id1>=<cbm1>;..."
 	// Format: "L3:<cache_id0>=<cbm0>;<cache_id1>=<cbm1>;..."
 	L3CacheSchema string `json:"l3_cache_schema,omitempty"`
 	L3CacheSchema string `json:"l3_cache_schema,omitempty"`

+ 9 - 0
vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go

@@ -1,5 +1,7 @@
 package configs
 package configs
 
 
+import "golang.org/x/sys/unix"
+
 const (
 const (
 	// EXT_COPYUP is a directive to copy up the contents of a directory when
 	// EXT_COPYUP is a directive to copy up the contents of a directory when
 	// a tmpfs is mounted over it.
 	// a tmpfs is mounted over it.
@@ -28,6 +30,9 @@ type Mount struct {
 	// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
 	// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
 	Relabel string `json:"relabel"`
 	Relabel string `json:"relabel"`
 
 
+	// RecAttr represents mount properties to be applied recursively (AT_RECURSIVE), see mount_setattr(2).
+	RecAttr *unix.MountAttr `json:"rec_attr"`
+
 	// Extensions are additional flags that are specific to runc.
 	// Extensions are additional flags that are specific to runc.
 	Extensions int `json:"extensions"`
 	Extensions int `json:"extensions"`
 
 
@@ -37,3 +42,7 @@ type Mount struct {
 	// Optional Command to be run after Source is mounted.
 	// Optional Command to be run after Source is mounted.
 	PostmountCmds []Command `json:"postmount_cmds"`
 	PostmountCmds []Command `json:"postmount_cmds"`
 }
 }
+
+func (m *Mount) IsBind() bool {
+	return m.Flags&unix.MS_BIND != 0
+}

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go

@@ -1,3 +1,4 @@
+//go:build linux
 // +build linux
 // +build linux
 
 
 package configs
 package configs

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go

@@ -1,3 +1,4 @@
+//go:build !linux && !windows
 // +build !linux,!windows
 // +build !linux,!windows
 
 
 package configs
 package configs

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go

@@ -1,3 +1,4 @@
+//go:build !linux
 // +build !linux
 // +build !linux
 
 
 package configs
 package configs

+ 9 - 0
vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go

@@ -0,0 +1,9 @@
+package configs
+
+// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11)
+type LinuxRdma struct {
+	// Maximum number of HCA handles that can be opened. Default is "no limit".
+	HcaHandles *uint32 `json:"hca_handles,omitempty"`
+	// Maximum number of HCA objects that can be created. Default is "no limit".
+	HcaObjects *uint32 `json:"hca_objects,omitempty"`
+}

+ 6 - 6
vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go

@@ -1,10 +1,10 @@
+//go:build !windows
 // +build !windows
 // +build !windows
 
 
 package devices
 package devices
 
 
 import (
 import (
 	"errors"
 	"errors"
-	"io/ioutil"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 
 
@@ -16,8 +16,8 @@ var ErrNotADevice = errors.New("not a device node")
 
 
 // Testing dependencies
 // Testing dependencies
 var (
 var (
-	unixLstat     = unix.Lstat
-	ioutilReadDir = ioutil.ReadDir
+	unixLstat = unix.Lstat
+	osReadDir = os.ReadDir
 )
 )
 
 
 func mkDev(d *Rule) (uint64, error) {
 func mkDev(d *Rule) (uint64, error) {
@@ -40,7 +40,7 @@ func DeviceFromPath(path, permissions string) (*Device, error) {
 	var (
 	var (
 		devType   Type
 		devType   Type
 		mode      = stat.Mode
 		mode      = stat.Mode
-		devNumber = uint64(stat.Rdev)
+		devNumber = uint64(stat.Rdev) //nolint:unconvert // Rdev is uint32 on e.g. MIPS.
 		major     = unix.Major(devNumber)
 		major     = unix.Major(devNumber)
 		minor     = unix.Minor(devNumber)
 		minor     = unix.Minor(devNumber)
 	)
 	)
@@ -76,7 +76,7 @@ func HostDevices() ([]*Device, error) {
 // GetDevices recursively traverses a directory specified by path
 // GetDevices recursively traverses a directory specified by path
 // and returns all devices found there.
 // and returns all devices found there.
 func GetDevices(path string) ([]*Device, error) {
 func GetDevices(path string) ([]*Device, error) {
-	files, err := ioutilReadDir(path)
+	files, err := osReadDir(path)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -103,7 +103,7 @@ func GetDevices(path string) ([]*Device, error) {
 		}
 		}
 		device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
 		device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
 		if err != nil {
 		if err != nil {
-			if err == ErrNotADevice {
+			if errors.Is(err, ErrNotADevice) {
 				continue
 				continue
 			}
 			}
 			if os.IsNotExist(err) {
 			if os.IsNotExist(err) {

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go

@@ -1,3 +1,4 @@
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 
 package user
 package user

+ 11 - 10
vendor/github.com/opencontainers/runc/libcontainer/user/user.go

@@ -120,7 +120,7 @@ func ParsePasswdFileFilter(path string, filter func(User) bool) ([]User, error)
 
 
 func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
 func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
 	if r == nil {
 	if r == nil {
-		return nil, fmt.Errorf("nil source for passwd-formatted data")
+		return nil, errors.New("nil source for passwd-formatted data")
 	}
 	}
 
 
 	var (
 	var (
@@ -178,7 +178,7 @@ func ParseGroupFileFilter(path string, filter func(Group) bool) ([]Group, error)
 
 
 func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
 func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
 	if r == nil {
 	if r == nil {
-		return nil, fmt.Errorf("nil source for group-formatted data")
+		return nil, errors.New("nil source for group-formatted data")
 	}
 	}
 	rd := bufio.NewReader(r)
 	rd := bufio.NewReader(r)
 	out := []Group{}
 	out := []Group{}
@@ -339,7 +339,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
 		if userArg == "" {
 		if userArg == "" {
 			userArg = strconv.Itoa(user.Uid)
 			userArg = strconv.Itoa(user.Uid)
 		}
 		}
-		return nil, fmt.Errorf("unable to find user %s: %v", userArg, err)
+		return nil, fmt.Errorf("unable to find user %s: %w", userArg, err)
 	}
 	}
 
 
 	var matchedUserName string
 	var matchedUserName string
@@ -355,7 +355,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
 
 
 		if uidErr != nil {
 		if uidErr != nil {
 			// Not numeric.
 			// Not numeric.
-			return nil, fmt.Errorf("unable to find user %s: %v", userArg, ErrNoPasswdEntries)
+			return nil, fmt.Errorf("unable to find user %s: %w", userArg, ErrNoPasswdEntries)
 		}
 		}
 		user.Uid = uidArg
 		user.Uid = uidArg
 
 
@@ -390,7 +390,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
 			return g.Name == groupArg
 			return g.Name == groupArg
 		})
 		})
 		if err != nil && group != nil {
 		if err != nil && group != nil {
-			return nil, fmt.Errorf("unable to find groups for spec %v: %v", matchedUserName, err)
+			return nil, fmt.Errorf("unable to find groups for spec %v: %w", matchedUserName, err)
 		}
 		}
 
 
 		// Only start modifying user.Gid if it is in explicit form.
 		// Only start modifying user.Gid if it is in explicit form.
@@ -404,7 +404,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
 
 
 				if gidErr != nil {
 				if gidErr != nil {
 					// Not numeric.
 					// Not numeric.
-					return nil, fmt.Errorf("unable to find group %s: %v", groupArg, ErrNoGroupEntries)
+					return nil, fmt.Errorf("unable to find group %s: %w", groupArg, ErrNoGroupEntries)
 				}
 				}
 				user.Gid = gidArg
 				user.Gid = gidArg
 
 
@@ -445,7 +445,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
 			return false
 			return false
 		})
 		})
 		if err != nil {
 		if err != nil {
-			return nil, fmt.Errorf("Unable to find additional groups %v: %v", additionalGroups, err)
+			return nil, fmt.Errorf("Unable to find additional groups %v: %w", additionalGroups, err)
 		}
 		}
 	}
 	}
 
 
@@ -468,7 +468,8 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
 		if !found {
 		if !found {
 			gid, err := strconv.ParseInt(ag, 10, 64)
 			gid, err := strconv.ParseInt(ag, 10, 64)
 			if err != nil {
 			if err != nil {
-				return nil, fmt.Errorf("Unable to find group %s", ag)
+				// Not a numeric ID either.
+				return nil, fmt.Errorf("Unable to find group %s: %w", ag, ErrNoGroupEntries)
 			}
 			}
 			// Ensure gid is inside gid range.
 			// Ensure gid is inside gid range.
 			if gid < minID || gid > maxID {
 			if gid < minID || gid > maxID {
@@ -521,7 +522,7 @@ func ParseSubIDFileFilter(path string, filter func(SubID) bool) ([]SubID, error)
 
 
 func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
 func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
 	if r == nil {
 	if r == nil {
-		return nil, fmt.Errorf("nil source for subid-formatted data")
+		return nil, errors.New("nil source for subid-formatted data")
 	}
 	}
 
 
 	var (
 	var (
@@ -574,7 +575,7 @@ func ParseIDMapFileFilter(path string, filter func(IDMap) bool) ([]IDMap, error)
 
 
 func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
 func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
 	if r == nil {
 	if r == nil {
-		return nil, fmt.Errorf("nil source for idmap-formatted data")
+		return nil, errors.New("nil source for idmap-formatted data")
 	}
 	}
 
 
 	var (
 	var (

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go

@@ -1,3 +1,4 @@
+//go:build gofuzz
 // +build gofuzz
 // +build gofuzz
 
 
 package user
 package user

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go

@@ -1,3 +1,4 @@
+//go:build gofuzz
 // +build gofuzz
 // +build gofuzz
 
 
 package userns
 package userns

+ 1 - 0
vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go

@@ -1,3 +1,4 @@
+//go:build !linux
 // +build !linux
 // +build !linux
 
 
 package userns
 package userns

+ 16 - 2
vendor/github.com/opencontainers/selinux/go-selinux/selinux.go

@@ -61,16 +61,30 @@ func ClassIndex(class string) (int, error) {
 	return classIndex(class)
 	return classIndex(class)
 }
 }
 
 
-// SetFileLabel sets the SELinux label for this path or returns an error.
+// SetFileLabel sets the SELinux label for this path, following symlinks,
+// or returns an error.
 func SetFileLabel(fpath string, label string) error {
 func SetFileLabel(fpath string, label string) error {
 	return setFileLabel(fpath, label)
 	return setFileLabel(fpath, label)
 }
 }
 
 
-// FileLabel returns the SELinux label for this path or returns an error.
+// LsetFileLabel sets the SELinux label for this path, not following symlinks,
+// or returns an error.
+func LsetFileLabel(fpath string, label string) error {
+	return lSetFileLabel(fpath, label)
+}
+
+// FileLabel returns the SELinux label for this path, following symlinks,
+// or returns an error.
 func FileLabel(fpath string) (string, error) {
 func FileLabel(fpath string) (string, error) {
 	return fileLabel(fpath)
 	return fileLabel(fpath)
 }
 }
 
 
+// LfileLabel returns the SELinux label for this path, not following symlinks,
+// or returns an error.
+func LfileLabel(fpath string) (string, error) {
+	return lFileLabel(fpath)
+}
+
 // SetFSCreateLabel tells the kernel what label to use for all file system objects
 // SetFSCreateLabel tells the kernel what label to use for all file system objects
 // created by this task.
 // created by this task.
 // Set the label to an empty string to return to the default label. Calls to SetFSCreateLabel
 // Set the label to an empty string to return to the default label. Calls to SetFSCreateLabel

+ 42 - 3
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go

@@ -316,8 +316,9 @@ func classIndex(class string) (int, error) {
 	return index, nil
 	return index, nil
 }
 }
 
 
-// setFileLabel sets the SELinux label for this path or returns an error.
-func setFileLabel(fpath string, label string) error {
+// lSetFileLabel sets the SELinux label for this path, not following symlinks,
+// or returns an error.
+func lSetFileLabel(fpath string, label string) error {
 	if fpath == "" {
 	if fpath == "" {
 		return ErrEmptyPath
 		return ErrEmptyPath
 	}
 	}
@@ -334,12 +335,50 @@ func setFileLabel(fpath string, label string) error {
 	return nil
 	return nil
 }
 }
 
 
-// fileLabel returns the SELinux label for this path or returns an error.
+// setFileLabel sets the SELinux label for this path, following symlinks,
+// or returns an error.
+func setFileLabel(fpath string, label string) error {
+	if fpath == "" {
+		return ErrEmptyPath
+	}
+	for {
+		err := unix.Setxattr(fpath, xattrNameSelinux, []byte(label), 0)
+		if err == nil {
+			break
+		}
+		if err != unix.EINTR { //nolint:errorlint // unix errors are bare
+			return &os.PathError{Op: "setxattr", Path: fpath, Err: err}
+		}
+	}
+
+	return nil
+}
+
+// fileLabel returns the SELinux label for this path, following symlinks,
+// or returns an error.
 func fileLabel(fpath string) (string, error) {
 func fileLabel(fpath string) (string, error) {
 	if fpath == "" {
 	if fpath == "" {
 		return "", ErrEmptyPath
 		return "", ErrEmptyPath
 	}
 	}
 
 
+	label, err := getxattr(fpath, xattrNameSelinux)
+	if err != nil {
+		return "", &os.PathError{Op: "getxattr", Path: fpath, Err: err}
+	}
+	// Trim the NUL byte at the end of the byte buffer, if present.
+	if len(label) > 0 && label[len(label)-1] == '\x00' {
+		label = label[:len(label)-1]
+	}
+	return string(label), nil
+}
+
+// lFileLabel returns the SELinux label for this path, not following symlinks,
+// or returns an error.
+func lFileLabel(fpath string) (string, error) {
+	if fpath == "" {
+		return "", ErrEmptyPath
+	}
+
 	label, err := lgetxattr(fpath, xattrNameSelinux)
 	label, err := lgetxattr(fpath, xattrNameSelinux)
 	if err != nil {
 	if err != nil {
 		return "", &os.PathError{Op: "lgetxattr", Path: fpath, Err: err}
 		return "", &os.PathError{Op: "lgetxattr", Path: fpath, Err: err}

+ 8 - 0
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go

@@ -17,10 +17,18 @@ func setFileLabel(fpath string, label string) error {
 	return nil
 	return nil
 }
 }
 
 
+func lSetFileLabel(fpath string, label string) error {
+	return nil
+}
+
 func fileLabel(fpath string) (string, error) {
 func fileLabel(fpath string) (string, error) {
 	return "", nil
 	return "", nil
 }
 }
 
 
+func lFileLabel(fpath string) (string, error) {
+	return "", nil
+}
+
 func setFSCreateLabel(label string) error {
 func setFSCreateLabel(label string) error {
 	return nil
 	return nil
 }
 }

+ 33 - 0
vendor/github.com/opencontainers/selinux/go-selinux/xattrs_linux.go

@@ -36,3 +36,36 @@ func doLgetxattr(path, attr string, dest []byte) (int, error) {
 		}
 		}
 	}
 	}
 }
 }
+
+// getxattr returns a []byte slice containing the value of
+// an extended attribute attr set for path.
+func getxattr(path, attr string) ([]byte, error) {
+	// Start with a 128 length byte array
+	dest := make([]byte, 128)
+	sz, errno := dogetxattr(path, attr, dest)
+	for errno == unix.ERANGE { //nolint:errorlint // unix errors are bare
+		// Buffer too small, use zero-sized buffer to get the actual size
+		sz, errno = dogetxattr(path, attr, []byte{})
+		if errno != nil {
+			return nil, errno
+		}
+
+		dest = make([]byte, sz)
+		sz, errno = dogetxattr(path, attr, dest)
+	}
+	if errno != nil {
+		return nil, errno
+	}
+
+	return dest[:sz], nil
+}
+
+// dogetxattr is a wrapper that retries on EINTR
+func dogetxattr(path, attr string, dest []byte) (int, error) {
+	for {
+		sz, err := unix.Getxattr(path, attr, dest)
+		if err != unix.EINTR { //nolint:errorlint // unix errors are bare
+			return sz, err
+		}
+	}
+}

+ 0 - 4
vendor/golang.org/x/sys/cpu/cpu_gc_x86.go

@@ -15,7 +15,3 @@ func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
 // xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler
 // xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler
 // and in cpu_gccgo.c for gccgo.
 // and in cpu_gccgo.c for gccgo.
 func xgetbv() (eax, edx uint32)
 func xgetbv() (eax, edx uint32)
-
-// darwinSupportsAVX512 is implemented in cpu_x86.s for gc compiler
-// and in cpu_gccgo_x86.go for gccgo.
-func darwinSupportsAVX512() bool

+ 4 - 3
vendor/golang.org/x/sys/cpu/cpu_x86.go

@@ -90,9 +90,10 @@ func archInit() {
 		osSupportsAVX = isSet(1, eax) && isSet(2, eax)
 		osSupportsAVX = isSet(1, eax) && isSet(2, eax)
 
 
 		if runtime.GOOS == "darwin" {
 		if runtime.GOOS == "darwin" {
-			// Check darwin commpage for AVX512 support. Necessary because:
-			// https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/osfmk/i386/fpu.c#L175-L201
-			osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512()
+			// Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers.
+			// Since users can't rely on mask register contents, let's not advertise AVX-512 support.
+			// See issue 49233.
+			osSupportsAVX512 = false
 		} else {
 		} else {
 			// Check if OPMASK and ZMM registers have OS support.
 			// Check if OPMASK and ZMM registers have OS support.
 			osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)
 			osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)

Деякі файли не було показано, через те що забагато файлів було змінено