Pārlūkot izejas kodu

Merge pull request #43083 from AkihiroSuda/runc-1.1.0

update runc to v1.1.0
Sebastiaan van Stijn 3 gadi atpakaļ
vecāks
revīzija
af4babd657
100 mainītis faili ar 2481 papildinājumiem un 1117 dzēšanām
  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.
 #
 # When updating RUNC_VERSION, consider updating runc in vendor.mod accordingly
-: "${RUNC_VERSION:=v1.0.3}"
+: "${RUNC_VERSION:=v1.1.0}"
 
 install_runc() {
 	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/fluent/fluent-logger-golang v1.9.0
 	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/golang/gddo v0.0.0-20190904175337-72a348e765d2
 	github.com/google/go-cmp v0.5.5
@@ -62,9 +62,9 @@ require (
 	github.com/morikuni/aec v1.0.0
 	github.com/opencontainers/go-digest v1.0.0
 	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/selinux v1.9.1
+	github.com/opencontainers/selinux v1.10.0
 	github.com/pelletier/go-toml v1.9.1
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.11.0
@@ -79,7 +79,7 @@ require (
 	go.etcd.io/bbolt v1.3.6
 	golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
 	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
 	google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
 	google.golang.org/grpc v1.40.0
@@ -93,14 +93,14 @@ require (
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // 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/ttrpc v1.1.0 // indirect
 	github.com/coreos/etcd v3.3.27+incompatible // indirect
 	github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // 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/gofrs/flock v0.7.3 // 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/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
 github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
+github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
 github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
-github.com/cilium/ebpf v0.6.2 h1:iHsfF/t4aW4heW2YKfeHrVPGdtYTL4C4KocpM8KTSnI=
 github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k=
+github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
 github.com/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/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/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
 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.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/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
 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.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
 github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
+github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
+github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
 github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
 github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
 github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
@@ -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/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.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
+github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gofrs/flock v0.7.3 h1:I0EKY9l8HZCXTMYC4F80vwT6KNypV9uYKP3Alm/hjmQ=
 github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 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/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.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.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/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 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.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/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU=
 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/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.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/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=
@@ -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-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-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-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/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=

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

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

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

@@ -24,6 +24,5 @@ linters:
 
     # Could be enabled later:
     # - gocyclo
-    # - prealloc
     # - maligned
     # - 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
 enabled. There are multiple ways the library deals with that:
 
-* Fallback: older kernels don't allowing naming programs and maps. The library
+* Fallback: older kernels don't allow naming programs and maps. The library
   automatically detects support for names, and omits them during load if
   necessary. This works since name is primarily a debug aid.
 
@@ -68,7 +68,7 @@ enabled. There are multiple ways the library deals with that:
 Once program and map objects are loaded they expose the kernel's low-level API,
 e.g. `NextKey`. Often this API is awkward to use in Go, so there are safer
 wrappers on top of the low-level API, like `MapIterator`. The low-level API is
-useful as an out when our higher-level API doesn't support a particular use case.
+useful when our higher-level API doesn't support a particular use case.
 
 Links
 ---

+ 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.
 
 New features must be accompanied by tests. Before starting work on any large
-feature, please [join](https://cilium.herokuapp.com/) the
-[#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack to
+feature, please [join](https://ebpf.io/slack) the
+[#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack to
 discuss the design first.
 
 When submitting pull requests, consider writing details about what problem you

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

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

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

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

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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 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
 }
 
+// IsBuiltinCall returns true if the instruction is a built-in call, i.e. BPF helper call.
+func (ins *Instruction) IsBuiltinCall() bool {
+	return ins.OpCode.JumpOp() == Call && ins.Src == R0 && ins.Dst == R0
+}
+
 // IsConstantLoad returns true if the instruction loads a constant of the
 // given size.
 func (ins *Instruction) IsConstantLoad(size Size) bool {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 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
 
 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
 
 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
 

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 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 {
-	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) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -17,10 +17,10 @@
 package console
 
 import (
+	"errors"
 	"fmt"
 	"os"
 
-	"github.com/pkg/errors"
 	"golang.org/x/sys/windows"
 )
 
@@ -103,7 +103,7 @@ func (m *master) Reset() error {
 		{m.err, m.errMode},
 	} {
 		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
 	err := windows.GetConsoleScreenBufferInfo(m.out, &info)
 	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{
@@ -139,7 +139,7 @@ func (m *master) DisableEcho() error {
 	mode |= windows.ENABLE_LINE_INPUT
 
 	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
@@ -192,7 +192,7 @@ func makeInputRaw(fd windows.Handle, mode uint32) error {
 	}
 
 	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

+ 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.

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

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

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

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

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

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

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

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

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

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

+ 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 {
 	return &Error{
 		"org.freedesktop.DBus.Error.Failed",
@@ -128,6 +149,11 @@ func (conn *Conn) handleCall(msg *Message) {
 	ifaceName, _ := msg.Headers[FieldInterface].value.(string)
 	sender, hasSender := msg.Headers[FieldSender].value.(string)
 	serial := msg.serial
+
+	if len(name) == 0 {
+		conn.sendError(ErrMsgUnknownMethod, sender, serial)
+	}
+
 	if ifaceName == "org.freedesktop.DBus.Peer" {
 		switch name {
 		case "Ping":
@@ -135,29 +161,26 @@ func (conn *Conn) handleCall(msg *Message) {
 		case "GetMachineId":
 			conn.sendReply(sender, serial, conn.uuid)
 		default:
-			conn.sendError(ErrMsgUnknownMethod, sender, serial)
+			conn.sendError(MakeUnknownMethodError(name), sender, serial)
 		}
 		return
 	}
-	if len(name) == 0 {
-		conn.sendError(ErrMsgUnknownMethod, sender, serial)
-	}
 
 	object, ok := conn.handler.LookupObject(path)
 	if !ok {
-		conn.sendError(ErrMsgNoObject, sender, serial)
+		conn.sendError(MakeNoObjectError(path), sender, serial)
 		return
 	}
 
 	iface, exists := object.LookupInterface(ifaceName)
 	if !exists {
-		conn.sendError(ErrMsgUnknownInterface, sender, serial)
+		conn.sendError(MakeUnknownInterfaceError(ifaceName), sender, serial)
 		return
 	}
 
 	m, exists := iface.LookupMethod(name)
 	if !exists {
-		conn.sendError(ErrMsgUnknownMethod, sender, serial)
+		conn.sendError(MakeUnknownMethodError(name), sender, serial)
 		return
 	}
 	args, err := conn.decodeArguments(m, sender, msg)

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

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

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

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

+ 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 {
-	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)
 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -1,3 +1,4 @@
+//go:build linux
 // +build linux
 
 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
 
 package configs

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

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

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

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

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

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

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

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

@@ -1,3 +1,4 @@
+//go:build !linux
 // +build !linux
 
 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)
 }
 
-// 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 {
 	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) {
 	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
 // created by this task.
 // 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
 }
 
-// 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 == "" {
 		return ErrEmptyPath
 	}
@@ -334,12 +335,50 @@ func setFileLabel(fpath string, label string) error {
 	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) {
 	if fpath == "" {
 		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)
 	if err != nil {
 		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
 }
 
+func lSetFileLabel(fpath string, label string) error {
+	return nil
+}
+
 func fileLabel(fpath string) (string, error) {
 	return "", nil
 }
 
+func lFileLabel(fpath string) (string, error) {
+	return "", nil
+}
+
 func setFSCreateLabel(label string) error {
 	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
 // and in cpu_gccgo.c for gccgo.
 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)
 
 		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 {
 			// Check if OPMASK and ZMM registers have OS support.
 			osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels