State the ZAP wire of every urpc payload

urpc encodes with encoding/json, which walks the payload on every call: a
realistic control.ExecArgs costs 7084ns and 10 allocations to cross. ZAP
reads a field at a constant offset out of the buffer that arrived, so the
same payload is 740ns and one allocation -- but only if the offsets are
stated, and a stated offset that is wrong is silent corruption rather than
a compile error. So state them from the types themselves.

//tools/zap reflects over the payloads at build time and writes the wire
as Go source with the offsets as constants. It lives inside Bazel because
pkg/sentry/control cannot be imported from outside it: the *_go_proto
packages it depends on have no source in the tree.

Six payloads had no layout to state. A map, an interface and a type from
another module have no offsets, so each is answered in the type:

  SaveOpts.Metadata and StartContainerArgs.InitialCgroups/Limits cross as
  lists of pairs; boot.Route.Destination restates net.IPNet as Subnet;
  OpenMountArgs restates the OCI mount fields the call actually uses;
  StartArgs.Spec and SinkConfig.Config carry their documents as the bytes
  they arrived as; MetricsRegistrationResponse carries the protocol
  buffer the same way; and seccheck's session options become a type
  instead of a map of any.

ExecArgs and MetricsExportData still have none: ExecArgs holds live
kernel objects behind an interface, and MetricsExportData reaches a
prometheus snapshot whose labels are a map.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-09-22 23:10:33 -07:00
co-authored by Hanzo Dev
parent c814594092
commit 3da05638df
47 changed files with 6243 additions and 128 deletions
+1 -1
View File
@@ -216,6 +216,7 @@ use_repo(
"com_github_xeipuuv_gojsonreference",
"com_github_xeipuuv_gojsonschema",
"com_github_zap_proto_go",
"com_github_zap_proto_zip",
"com_google_cloud_go",
"com_google_cloud_go_auth",
"com_google_cloud_go_auth_oauth2adapt",
@@ -256,7 +257,6 @@ use_repo(
"org_uber_go_atomic",
"org_uber_go_multierr",
)
go_deps.module(
path = "cloud.google.com/go/auth",
sum = "h1:mFWNQ2FEVWAliEQWpAdH80omXFokmrnbDhUS9cBywsI=",
+5
View File
@@ -210,6 +210,11 @@ governance-check: governance-regen ## Checks that the files derived from governa
(echo "Generated governance files are out of sync. Please run \`make governance-regen\`." >&2; exit 1)
.PHONY: governance-check
zap: ## Regenerates the ZAP wire of every urpc payload.
@for f in $$(git ls-files '*/zap.go' | grep -v '^tools/zap/'); do sed -i '/^package /q' $$f; done
@$(call run,//tools/zap:zap)
.PHONY: zap
license-check: ## Checks that tools/licensecheck/dependencies.yaml has an entry for every dependency.
@$(call run,//tools/licensecheck/main:licensecheck,--mode=verify)
.PHONY: license-check
+45 -16
View File
@@ -1,6 +1,6 @@
module gvisor.dev/gvisor
go 1.26.3
go 1.26.8
require (
cloud.google.com/go/auth v0.20.0
@@ -26,7 +26,7 @@ require (
github.com/godbus/dbus/v5 v5.1.0
github.com/gofrs/flock v0.8.0
github.com/gogo/protobuf v1.3.2
github.com/google/btree v1.1.2
github.com/google/btree v1.1.3
github.com/google/subcommands v1.0.2-0.20190508160503-636abe8753b8
github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a
github.com/moby/sys/capability v0.4.0
@@ -35,12 +35,12 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8
github.com/zap-proto/go v1.8.0
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc
golang.org/x/mod v0.34.0
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90
golang.org/x/mod v0.36.0
golang.org/x/sync v0.20.0
golang.org/x/sys v0.43.0
golang.org/x/sys v0.45.0
golang.org/x/time v0.15.0
golang.org/x/tools v0.43.0
golang.org/x/tools v0.45.0
google.golang.org/api v0.274.0
google.golang.org/grpc v1.80.0
google.golang.org/protobuf v1.36.11
@@ -49,6 +49,34 @@ require (
k8s.io/client-go v0.32.3
)
require (
github.com/andybalholm/brotli v1.2.1 // indirect
github.com/cloudflare/circl v1.6.3 // indirect
github.com/gofiber/schema v1.7.1 // indirect
github.com/gofiber/utils/v2 v2.0.4 // indirect
github.com/gorilla/rpc v1.2.1 // indirect
github.com/grandcat/zeroconf v1.0.0 // indirect
github.com/klauspost/compress v1.18.6 // indirect
github.com/luxfi/accel v1.2.4 // indirect
github.com/luxfi/crypto v1.20.2 // indirect
github.com/luxfi/log v1.4.3 // indirect
github.com/luxfi/mdns v0.1.1 // indirect
github.com/luxfi/metric v1.10.0 // indirect
github.com/luxfi/zap v1.2.7 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.21 // indirect
github.com/miekg/dns v1.1.72 // indirect
github.com/philhofer/fwd v1.2.0 // indirect
github.com/tinylib/msgp v1.6.4 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.70.0 // indirect
github.com/zap-proto/fiber/v3 v3.2.1 // indirect
github.com/zap-proto/http v0.3.5 // indirect
github.com/zap-proto/mcp v1.0.5 // indirect
github.com/zap-proto/zip v1.36.47-0.20260911003408-2f5a38795b58 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
)
require (
cel.dev/expr v0.25.1 // indirect
cloud.google.com/go v0.123.0 // indirect
@@ -69,7 +97,7 @@ require (
github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect
github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
@@ -102,21 +130,22 @@ require (
github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect
github.com/vishvananda/netns v0.0.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/zap-proto/go v1.8.3
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect
go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect
go.opentelemetry.io/otel/sdk v1.43.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect
go.opentelemetry.io/otel/trace v1.43.0 // indirect
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.52.0 // indirect
go.opentelemetry.io/otel v1.44.0 // indirect
go.opentelemetry.io/otel/metric v1.44.0 // indirect
go.opentelemetry.io/otel/sdk v1.44.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.44.0 // indirect
go.opentelemetry.io/otel/trace v1.44.0 // indirect
golang.org/x/crypto v0.52.0 // indirect
golang.org/x/net v0.55.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/term v0.42.0 // indirect
golang.org/x/text v0.36.0 // indirect
golang.org/x/term v0.43.0 // indirect
golang.org/x/text v0.37.0 // indirect
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
+99 -12
View File
@@ -1,8 +1,8 @@
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA=
cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
@@ -28,14 +28,19 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro=
github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w=
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI=
@@ -67,9 +72,9 @@ github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -78,10 +83,10 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA=
github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g=
github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
@@ -91,6 +96,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ=
github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -112,6 +119,10 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofiber/schema v1.7.1 h1:oSJBKdgP8JeIME4TQSAqlNKTU2iBB+2RNmKi8Nsc+TI=
github.com/gofiber/schema v1.7.1/go.mod h1:A/X5Ffyru4p9eBdp99qu+nzviHzQiZ7odLT+TwxWhbk=
github.com/gofiber/utils/v2 v2.0.4 h1:WwAxUA7L4MW2DjdEHF234lfqvBqd2vYYuBtA9TJq2ec=
github.com/gofiber/utils/v2 v2.0.4/go.mod h1:GGERKU3Vhj5z6hS8YKvxL99A54DjOvTFZ0cjZnG4Lj4=
github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -123,8 +134,8 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
@@ -134,6 +145,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -161,6 +174,10 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA
github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
github.com/googleapis/gax-go/v2 v2.21.0 h1:h45NjjzEO3faG9Lg/cFrBh2PgegVVgzqKzuZl/wMbiI=
github.com/googleapis/gax-go/v2 v2.21.0/go.mod h1:But/NJU6TnZsrLai/xBAQLLz+Hc7fHZJt/hsCz3Fih4=
github.com/gorilla/rpc v1.2.1 h1:yC+LMV5esttgpVvNORL/xX4jvTTEUE30UZhZ5JF7K9k=
github.com/gorilla/rpc v1.2.1/go.mod h1:uNpOihAlF5xRFLuTYhfR0yfCTm0WTQSQttkMSptRfGk=
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
@@ -171,6 +188,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -178,16 +197,35 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/luxfi/accel v1.2.4 h1:5VbIHyEvvfobn2zBiTFODxDw1CeqxCepZOLlvkuf9yQ=
github.com/luxfi/accel v1.2.4/go.mod h1:ISIwAX+ZfsL/S5nsP2JvfldXN6Nc+QzoWf6Jtaq+xsQ=
github.com/luxfi/crypto v1.20.2 h1:L81WEsU/hs2A76F5PWBusG0yU74QqkDdUqqgexWUxh4=
github.com/luxfi/crypto v1.20.2/go.mod h1:qYHOM0lO4PRh7LEaObxFQUIMjmT1/paVm/WgZkobT1k=
github.com/luxfi/log v1.4.3 h1:xkUKRWvQ4ZwvlUC2e0/RTtHYZOYSMvSQ9W9lbjwBmiI=
github.com/luxfi/log v1.4.3/go.mod h1:myIkufyiQomSQH34K981kbz6cG4WUoerRUh7F4XhlQI=
github.com/luxfi/mdns v0.1.1 h1:g2eRr9AXcziPkkcd24M+Qu9ApEpoKKjfI79QSNqv0rQ=
github.com/luxfi/mdns v0.1.1/go.mod h1:dbp5f3h3aE7CGzwbaWzBM9cwdcekhmSrWhQevgYhhNA=
github.com/luxfi/metric v1.10.0 h1:Ca4N6HqukMoZ1JUx3t5BJ4cjyY3HL+HnF9kaGEAAUfA=
github.com/luxfi/metric v1.10.0/go.mod h1:JhVJPOM10FEpGSSaP8QrGLi7w0D3pjJ2kwWwmGi+9YI=
github.com/luxfi/zap v1.2.7 h1:LzYit+1xLoQRT0ahYsoYcdoDz5I5gc0ltLvBXRkPpwQ=
github.com/luxfi/zap v1.2.7/go.mod h1:cAoQ1g80iSxgWOhXj6YBrWfKJi771FjPe8HdQ2eOLZw=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a h1:+J2gw7Bw77w/fbK7wnNJJDKmw1IbWft2Ul5BzrG1Qm8=
github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
@@ -213,6 +251,8 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
@@ -234,13 +274,19 @@ github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xI
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ=
github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.70.0 h1:LAhMGcWk13QZWm85+eg8ZBNbrq5mnkWFGbHMUJHIdXA=
github.com/valyala/fasthttp v1.70.0/go.mod h1:oDZEHHkJ/Buyklg6uURmYs19442zFSnCIfX3j1FY3pE=
github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8 h1:Y4egeTrP7sccowz2GWTJVtHlwkZippgBTpUmMteFUWQ=
github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
@@ -250,8 +296,18 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zap-proto/fiber/v3 v3.2.1 h1:k45oKyTwySPtGt8sPz2Ao8OUHc7pDEhai8Np2Ym6Jbg=
github.com/zap-proto/fiber/v3 v3.2.1/go.mod h1:eDm2z+ufJrkuE4MeX0Mea4oc/p7/HpXiZjVB+BXCKOA=
github.com/zap-proto/go v1.8.0 h1:P+Asg0kCBde54wLlgPNkBr32km1Q/apfRj0aNQx5t4Q=
github.com/zap-proto/go v1.8.0/go.mod h1:dJ394C6tzk6sm67JmnAWVyPjvMZ3JvFz0ujxoy0wR4A=
github.com/zap-proto/go v1.8.3 h1:GWhb8y7ylgVcaVOR8XN/It56Xovm5Mkv+nQqiblnnoA=
github.com/zap-proto/go v1.8.3/go.mod h1:fbNeWcssRRbTkQEDCrmUmzqJA1gKcAlgi1z4QrtEFZg=
github.com/zap-proto/http v0.3.5 h1:ezSuUbF05jxFGpfmScBnzIVTeH1ZGhcDSm7d5yL8Byc=
github.com/zap-proto/http v0.3.5/go.mod h1:UYfGhDDCetgxs65XSev8Lpf65COg5vKQK+cWwZGh4zQ=
github.com/zap-proto/mcp v1.0.5 h1:1Hi0KNi4YlWW2zkQUMDK9n3jP3wZaRJ1rseMW9p9F0c=
github.com/zap-proto/mcp v1.0.5/go.mod h1:cYOsq+33NyW4X8nUVtIs/qtezVovYazw1s0V7mrQBYA=
github.com/zap-proto/zip v1.36.47-0.20260911003408-2f5a38795b58 h1:Wjd2qaTxOLswwovVmWYw/G6K7oykWDUSRuXRDXlMGP4=
github.com/zap-proto/zip v1.36.47-0.20260911003408-2f5a38795b58/go.mod h1:sjlwTZhK8yLnjLWreVhK9VZrf2M/doKtEaqgZzCx+I0=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
@@ -268,22 +324,32 @@ go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=
go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -291,24 +357,32 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc h1:TS73t7x3KarrNd5qAipmspBDS1rkMcgVG/fS1aRb4Rc=
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc=
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA=
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
@@ -316,6 +390,8 @@ golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
@@ -333,29 +409,36 @@ golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
@@ -372,6 +455,8 @@ golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -411,10 +496,10 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -422,6 +507,8 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+5 -1
View File
@@ -7,10 +7,14 @@ package(
go_library(
name = "fd",
srcs = ["fd.go"],
srcs = [
"fd.go",
"zap.go",
],
visibility = ["//visibility:public"],
deps = [
"//pkg/atomicbitops",
"@com_github_zap_proto_go//:go",
"@org_golang_x_sys//unix:go_default_library",
],
)
+64
View File
@@ -0,0 +1,64 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package fd
import (
"fmt"
zap "github.com/zap-proto/go"
)
// ---- FD ----------------------------------------------------------------
const (
fDReadWriterAt = 0
fDSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*FD)(nil)
// MarshalZAP writes FD from constant offsets.
func (x *FD) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(fDSize + 256)
ob := b.StartObject(fDSize)
{
eb := zap.NewBuilder(zap.HeaderSize)
eb.StartObject(0).FinishAsRoot()
ob.SetBytes(fDReadWriterAt, eb.Finish())
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads FD out of the buffer that arrived.
func (x *FD) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("FD: %w", err)
}
_ = m
return nil
}
+7 -1
View File
@@ -6,6 +6,12 @@ licenses(["notice"])
go_library(
name = "checkpoint",
srcs = ["checkpoint.go"],
srcs = [
"checkpoint.go",
"zap.go",
],
visibility = ["//pkg/sentry:internal"],
deps = [
"@com_github_zap_proto_go//:go",
],
)
+65
View File
@@ -0,0 +1,65 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package checkpoint
import (
"fmt"
"strings"
zap "github.com/zap-proto/go"
)
// ---- ResourceID --------------------------------------------------------
const (
resourceIDContainerNameAt = 0
resourceIDPathAt = 8
resourceIDSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*ResourceID)(nil)
// MarshalZAP writes ResourceID from constant offsets.
func (x *ResourceID) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(resourceIDSize + 256)
ob := b.StartObject(resourceIDSize)
ob.SetText(resourceIDContainerNameAt, string(x.ContainerName))
ob.SetText(resourceIDPathAt, string(x.Path))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads ResourceID out of the buffer that arrived.
func (x *ResourceID) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("ResourceID: %w", err)
}
o := m.Root()
x.ContainerName = string(strings.Clone(o.Text(resourceIDContainerNameAt)))
x.Path = string(strings.Clone(o.Text(resourceIDPathAt)))
return nil
}
+4 -2
View File
@@ -36,13 +36,12 @@ go_library(
"state_cuda.go",
"tpu_control.go",
"usage.go",
"zap.go",
],
visibility = [
"//:sandbox",
],
deps = [
":control_api_go_proto",
":tpu_control_proto_go_proto",
"//pkg/abi/linux",
"//pkg/bpf",
"//pkg/cleanup",
@@ -84,6 +83,9 @@ go_library(
"//pkg/urpc",
"//pkg/usermem",
"//pkg/waiter",
":control_api_go_proto",
":tpu_control_proto_go_proto",
"@com_github_zap_proto_go//:go",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/timestamppb",
"@org_golang_x_sys//unix:go_default_library",
+23 -10
View File
@@ -128,10 +128,10 @@ type StartContainerArgs struct {
ContainerID string `json:"container_id"`
// InitialCgroups is the set of cgroup controllers container needs to be initialised to.
InitialCgroups map[kernel.CgroupControllerType]string `json:"initial_cgroups"`
InitialCgroups []Controller `json:"initial_cgroups"`
// Limits is the limit set for the process being executed.
Limits map[string]limits.Limit `json:"limits"`
Limits []Rlimit `json:"limits"`
// If HOME environment variable is not provided, and this flag is set,
// then the HOME environment variable will be set inside the container
@@ -154,6 +154,19 @@ type StartContainerArgs struct {
urpc.FilePayload
}
// Controller names one cgroup controller and the path, relative to it, that
// the container starts in.
type Controller struct {
Name kernel.CgroupControllerType
Path string
}
// Rlimit is one resource limit, named as Linux names the resource.
type Rlimit struct {
Name string
Limit limits.Limit
}
// String formats the StartContainerArgs without the SecretEnvv field.
func (sca StartContainerArgs) String() string {
sca.SecretEnvv = make([]string, len(sca.SecretEnvv))
@@ -239,12 +252,12 @@ func (l *Lifecycle) StartContainer(args *StartContainerArgs, _ *uint32) error {
if err != nil {
return fmt.Errorf("error creating default limit set: %w", err)
}
for name, limit := range args.Limits {
lt, ok := limits.FromLinuxResourceName[name]
for _, r := range args.Limits {
lt, ok := limits.FromLinuxResourceName[r.Name]
if !ok {
return fmt.Errorf("unknown limit %q", name)
return fmt.Errorf("unknown limit %q", r.Name)
}
ls.SetUnchecked(lt, limit)
ls.SetUnchecked(lt, r.Limit)
}
initArgs := kernel.CreateProcessArgs{
@@ -328,15 +341,15 @@ func (l *Lifecycle) StartContainer(args *StartContainerArgs, _ *uint32) error {
initialCgroups := make(map[kernel.Cgroup]struct{}, len(args.InitialCgroups))
cgroupRegistry := l.Kernel.CgroupRegistry()
// path is relative to the container's cgroup controller of specified type.
for initialCgroupController, path := range args.InitialCgroups {
if !cgroupRegistry.IsControllerBound(initialCgroupController) && l.Kernel.Cgroup2FS().EverMounted() {
for _, c := range args.InitialCgroups {
if !cgroupRegistry.IsControllerBound(c.Name) && l.Kernel.Cgroup2FS().EverMounted() {
// We are in V2 mode and this controller is not bound to V1.
// This is expected as V1 mounts are suppressed.
continue
}
cg, err := cgroupRegistry.FindCgroup(ctx, initialCgroupController, path)
cg, err := cgroupRegistry.FindCgroup(ctx, c.Name, c.Path)
if err != nil {
return fmt.Errorf("FindCgroup can't locate cgroup controller: %v err: %v", initialCgroupController, err)
return fmt.Errorf("FindCgroup can't locate cgroup controller: %v err: %v", c.Name, err)
}
initialCgroups[cg] = struct{}{}
}
+8 -4
View File
@@ -18,8 +18,8 @@ import (
"fmt"
"regexp"
"google.golang.org/protobuf/proto"
"gvisor.dev/gvisor/pkg/metric"
pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
"gvisor.dev/gvisor/pkg/prometheus"
"gvisor.dev/gvisor/pkg/sync"
)
@@ -32,7 +32,11 @@ type GetRegisteredMetricsOpts struct{}
// MetricsRegistrationResponse contains metric registration data.
type MetricsRegistrationResponse struct {
RegisteredMetrics *pb.MetricRegistration
// Registration is a metric_go_proto.MetricRegistration as the protocol
// buffer states it. The RPC carries the bytes: a message generated by
// another tool declares its own wire, and re-stating it here would be a
// second answer to what those bytes are.
Registration []byte
}
// GetRegisteredMetrics sets `out` to the metric registration information.
@@ -45,8 +49,8 @@ func (u *Metrics) GetRegisteredMetrics(_ *GetRegisteredMetricsOpts, out *Metrics
if err != nil {
return err
}
out.RegisteredMetrics = registration
return nil
out.Registration, err = proto.Marshal(registration)
return err
}
// MetricsExportOpts contains metric exporting options.
+22 -2
View File
@@ -72,7 +72,7 @@ type SaveOpts struct {
Key []byte `json:"key"`
// Metadata is the set of metadata to prepend to the state file.
Metadata map[string]string `json:"metadata"`
Metadata []Pair `json:"metadata"`
// AppMFExcludeCommittedZeroPages is the value of
// pgalloc.SaveOpts.ExcludeCommittedZeroPages for the application memory
@@ -123,13 +123,33 @@ type SaveRestoreExecOpts struct {
ContainerID string
}
// Pair is one key and its value. A map is a set of them with no order and no
// offsets, so it crosses as a list and becomes a map again at the far end.
type Pair struct {
Key string
Value string
}
// Pairs restates a map as the list that crosses.
func Pairs(m map[string]string) []Pair {
ps := make([]Pair, 0, len(m))
for k, v := range m {
ps = append(ps, Pair{Key: k, Value: v})
}
return ps
}
// ConvertToStateSaveOpts converts a control.SaveOpts to a state.SaveOpts.
// state.SaveOpts.Close() must be called when the state.SaveOpts is no longer
// needed.
func ConvertToStateSaveOpts(o *SaveOpts) (*state.SaveOpts, error) {
metadata := make(map[string]string, len(o.Metadata))
for _, p := range o.Metadata {
metadata[p.Key] = p.Value
}
saveOpts := &state.SaveOpts{
Key: o.Key,
Metadata: o.Metadata,
Metadata: metadata,
AppMFExcludeCommittedZeroPages: o.AppMFExcludeCommittedZeroPages,
Resume: o.Resume,
CudaCheckpointPath: o.CudaCheckpointPath,
File diff suppressed because it is too large Load Diff
+2
View File
@@ -11,12 +11,14 @@ go_library(
"context.go",
"limits.go",
"linux.go",
"zap.go",
],
visibility = ["//:sandbox"],
deps = [
"//pkg/abi/linux",
"//pkg/context",
"//pkg/sync",
"@com_github_zap_proto_go//:go",
"@org_golang_x_sys//unix:go_default_library",
],
)
+64
View File
@@ -0,0 +1,64 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package limits
import (
"fmt"
zap "github.com/zap-proto/go"
)
// ---- Limit -------------------------------------------------------------
const (
limitCurAt = 0
limitMaxAt = 8
limitSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*Limit)(nil)
// MarshalZAP writes Limit from constant offsets.
func (x *Limit) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(limitSize + 256)
ob := b.StartObject(limitSize)
ob.SetUint64(limitCurAt, uint64(x.Cur))
ob.SetUint64(limitMaxAt, uint64(x.Max))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads Limit out of the buffer that arrived.
func (x *Limit) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("Limit: %w", err)
}
o := m.Root()
x.Cur = uint64(o.Uint64(limitCurAt))
x.Max = uint64(o.Uint64(limitMaxAt))
return nil
}
+2
View File
@@ -50,6 +50,7 @@ go_library(
"mapping_set.go",
"mapping_set_impl.go",
"memmap.go",
"zap.go",
],
visibility = ["//pkg/sentry:internal"],
deps = [
@@ -59,6 +60,7 @@ go_library(
"//pkg/log",
"//pkg/safemem",
"//pkg/usermem",
"@com_github_zap_proto_go//:go",
],
)
+64
View File
@@ -0,0 +1,64 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package memmap
import (
"fmt"
zap "github.com/zap-proto/go"
)
// ---- FileRange ---------------------------------------------------------
const (
fileRangeStartAt = 0
fileRangeEndAt = 8
fileRangeSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*FileRange)(nil)
// MarshalZAP writes FileRange from constant offsets.
func (x *FileRange) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(fileRangeSize + 256)
ob := b.StartObject(fileRangeSize)
ob.SetUint64(fileRangeStartAt, uint64(x.Start))
ob.SetUint64(fileRangeEndAt, uint64(x.End))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads FileRange out of the buffer that arrived.
func (x *FileRange) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("FileRange: %w", err)
}
o := m.Root()
x.Start = uint64(o.Uint64(fileRangeStartAt))
x.End = uint64(o.Uint64(fileRangeEndAt))
return nil
}
+2
View File
@@ -27,6 +27,7 @@ go_library(
"seccheck.go",
"seqatomic_sinkslice_unsafe.go",
"syscall.go",
"zap.go",
],
visibility = ["//:sandbox"],
deps = [
@@ -43,6 +44,7 @@ go_library(
"//pkg/sentry/ktime",
"//pkg/sentry/seccheck/points:points_go_proto",
"//pkg/sync",
"@com_github_zap_proto_go//:go",
"@org_golang_google_protobuf//proto:go_default_library",
],
)
+37 -11
View File
@@ -15,6 +15,7 @@
package seccheck
import (
"encoding/json"
"fmt"
"os"
"sync"
@@ -56,7 +57,7 @@ type SessionConfig struct {
// Sinks are the sinks that will process the points enabled above.
Sinks []SinkConfig `json:"sinks,omitempty"`
// Options holds session-level configuration options.
Options map[string]any `json:"options,omitempty"`
Options Options `json:"options,omitempty"`
}
// PointConfig describes a point to be enabled in a given session.
@@ -69,13 +70,21 @@ type PointConfig struct {
ContextFields []string `json:"context_fields,omitempty"`
}
// Options are the session-level settings a trace configuration may set.
type Options struct {
// ExecveHashCacheCapacity bounds the execve hash cache. Zero takes
// DefaultExecveHashCacheCapacity.
ExecveHashCacheCapacity int `json:"execve_hash_cache_capacity,omitempty"`
}
// SinkConfig describes the sink that will process the points in a given
// session.
type SinkConfig struct {
// Name is the sink to be created. The sink must exist in the system.
Name string `json:"name,omitempty"`
// Config is a opaque json object that is passed to the sink.
Config map[string]any `json:"config,omitempty"`
// Config is a opaque json object that is passed to the sink. It stays the
// bytes it arrived as: what they mean is the sink's to say.
Config json.RawMessage `json:"config,omitempty"`
// IgnoreSetupError makes errors during sink setup to be ignored. Otherwise,
// failures will prevent the container from starting.
IgnoreSetupError bool `json:"ignore_setup_error,omitempty"`
@@ -106,12 +115,8 @@ func Create(conf *SessionConfig, force bool) error {
state := &Global
capacity := DefaultExecveHashCacheCapacity
if val, ok := conf.Options["execve_hash_cache_capacity"]; ok {
if cnt, ok := val.(float64); ok {
capacity = int(cnt)
} else if cnt, ok := val.(int); ok {
capacity = cnt
}
if conf.Options.ExecveHashCacheCapacity > 0 {
capacity = conf.Options.ExecveHashCacheCapacity
}
var reqs []PointReq
for _, ptConfig := range conf.Points {
@@ -145,7 +150,11 @@ func Create(conf *SessionConfig, force bool) error {
if err != nil {
return err
}
sink, err := desc.New(sinkConfig.Config, sinkConfig.FD)
opts, err := sinkConfig.options()
if err != nil {
return err
}
sink, err := desc.New(opts, sinkConfig.FD)
if err != nil {
return fmt.Errorf("creating event sink: %w", err)
}
@@ -187,7 +196,24 @@ func setupSink(config SinkConfig) (*os.File, error) {
if sink.Setup == nil {
return nil, nil
}
return sink.Setup(config.Config)
opts, err := config.options()
if err != nil {
return nil, err
}
return sink.Setup(opts)
}
// options reads the sink's opaque object. What the keys mean is the sink's to
// say, so this is the one place the bytes become values.
func (c SinkConfig) options() (map[string]any, error) {
if len(c.Config) == 0 {
return nil, nil
}
var opts map[string]any
if err := json.Unmarshal(c.Config, &opts); err != nil {
return nil, fmt.Errorf("sink %q config: %w", c.Name, err)
}
return opts, nil
}
// Delete deletes an existing session.
+365
View File
@@ -0,0 +1,365 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package seccheck
import (
"encoding/binary"
"encoding/json"
"fmt"
"strings"
zap "github.com/zap-proto/go"
fd "gvisor.dev/gvisor/pkg/fd"
)
// ---- Options -----------------------------------------------------------
const (
optionsExecveHashCacheCapacityAt = 0
optionsSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*Options)(nil)
// MarshalZAP writes Options from constant offsets.
func (x *Options) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(optionsSize + 256)
ob := b.StartObject(optionsSize)
ob.SetInt64(optionsExecveHashCacheCapacityAt, int64(x.ExecveHashCacheCapacity))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads Options out of the buffer that arrived.
func (x *Options) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("Options: %w", err)
}
o := m.Root()
x.ExecveHashCacheCapacity = int(o.Int64(optionsExecveHashCacheCapacityAt))
return nil
}
// ---- PointConfig -------------------------------------------------------
const (
pointConfigNameAt = 0
pointConfigOptionalFieldsAt = 8
pointConfigContextFieldsAt = 16
pointConfigSize = 24
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*PointConfig)(nil)
// MarshalZAP writes PointConfig from constant offsets.
func (x *PointConfig) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(pointConfigSize + 256)
optionalFieldsAt, optionalFieldsN := 0, len(x.OptionalFields)
if optionalFieldsN > 0 {
var blob []byte
for i := range x.OptionalFields {
enc := []byte(x.OptionalFields[i])
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
optionalFieldsAt = b.WriteBytes(blob)
}
contextFieldsAt, contextFieldsN := 0, len(x.ContextFields)
if contextFieldsN > 0 {
var blob []byte
for i := range x.ContextFields {
enc := []byte(x.ContextFields[i])
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
contextFieldsAt = b.WriteBytes(blob)
}
ob := b.StartObject(pointConfigSize)
ob.SetText(pointConfigNameAt, string(x.Name))
if optionalFieldsN > 0 {
ob.SetList(pointConfigOptionalFieldsAt, optionalFieldsAt, optionalFieldsN)
}
if contextFieldsN > 0 {
ob.SetList(pointConfigContextFieldsAt, contextFieldsAt, contextFieldsN)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads PointConfig out of the buffer that arrived.
func (x *PointConfig) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("PointConfig: %w", err)
}
o := m.Root()
x.Name = string(strings.Clone(o.Text(pointConfigNameAt)))
if l := o.List(pointConfigOptionalFieldsAt); l.Len() > 0 {
rows := make([]string, l.Len())
for i := range rows {
rows[i] = string(l.BytesAt(i))
}
x.OptionalFields = rows
}
if l := o.List(pointConfigContextFieldsAt); l.Len() > 0 {
rows := make([]string, l.Len())
for i := range rows {
rows[i] = string(l.BytesAt(i))
}
x.ContextFields = rows
}
return nil
}
// ---- SessionConfig -----------------------------------------------------
const (
sessionConfigNameAt = 0
sessionConfigPointsAt = 8
sessionConfigIgnoreMissingAt = 16
sessionConfigSinksAt = 24
sessionConfigOptionsAt = 32
sessionConfigSize = 40
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*SessionConfig)(nil)
// MarshalZAP writes SessionConfig from constant offsets.
func (x *SessionConfig) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(sessionConfigSize + 256)
pointsAt, pointsN := 0, len(x.Points)
if pointsN > 0 {
var blob []byte
for i := range x.Points {
enc, err := x.Points[i].MarshalZAP()
if err != nil {
return nil, err
}
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
pointsAt = b.WriteBytes(blob)
}
sinksAt, sinksN := 0, len(x.Sinks)
if sinksN > 0 {
var blob []byte
for i := range x.Sinks {
enc, err := x.Sinks[i].MarshalZAP()
if err != nil {
return nil, err
}
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
sinksAt = b.WriteBytes(blob)
}
ob := b.StartObject(sessionConfigSize)
ob.SetText(sessionConfigNameAt, string(x.Name))
ob.SetBool(sessionConfigIgnoreMissingAt, bool(x.IgnoreMissing))
innerOptions, err := x.Options.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(sessionConfigOptionsAt, innerOptions)
if pointsN > 0 {
ob.SetList(sessionConfigPointsAt, pointsAt, pointsN)
}
if sinksN > 0 {
ob.SetList(sessionConfigSinksAt, sinksAt, sinksN)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads SessionConfig out of the buffer that arrived.
func (x *SessionConfig) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("SessionConfig: %w", err)
}
o := m.Root()
x.Name = string(strings.Clone(o.Text(sessionConfigNameAt)))
if l := o.List(sessionConfigPointsAt); l.Len() > 0 {
rows := make([]PointConfig, l.Len())
for i := range rows {
if err := rows[i].UnmarshalZAP(l.BytesAt(i)); err != nil {
return err
}
}
x.Points = rows
}
x.IgnoreMissing = bool(o.Bool(sessionConfigIgnoreMissingAt))
if l := o.List(sessionConfigSinksAt); l.Len() > 0 {
rows := make([]SinkConfig, l.Len())
for i := range rows {
if err := rows[i].UnmarshalZAP(l.BytesAt(i)); err != nil {
return err
}
}
x.Sinks = rows
}
if raw := o.Bytes(sessionConfigOptionsAt); len(raw) > 0 {
if err := x.Options.UnmarshalZAP(raw); err != nil {
return err
}
}
return nil
}
// ---- SinkConfig --------------------------------------------------------
const (
sinkConfigNameAt = 0
sinkConfigConfigAt = 8
sinkConfigIgnoreSetupErrorAt = 16
sinkConfigStatusAt = 24
sinkConfigFDAt = 32
sinkConfigSize = 40
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*SinkConfig)(nil)
// MarshalZAP writes SinkConfig from constant offsets.
func (x *SinkConfig) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(sinkConfigSize + 256)
ob := b.StartObject(sinkConfigSize)
ob.SetText(sinkConfigNameAt, string(x.Name))
ob.SetBytes(sinkConfigConfigAt, []byte(x.Config))
ob.SetBool(sinkConfigIgnoreSetupErrorAt, bool(x.IgnoreSetupError))
innerStatus, err := x.Status.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(sinkConfigStatusAt, innerStatus)
if x.FD != nil {
innerFD, err := x.FD.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(sinkConfigFDAt, innerFD)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads SinkConfig out of the buffer that arrived.
func (x *SinkConfig) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("SinkConfig: %w", err)
}
o := m.Root()
x.Name = string(strings.Clone(o.Text(sinkConfigNameAt)))
x.Config = json.RawMessage(append([]byte(nil), o.Bytes(sinkConfigConfigAt)...))
x.IgnoreSetupError = bool(o.Bool(sinkConfigIgnoreSetupErrorAt))
if raw := o.Bytes(sinkConfigStatusAt); len(raw) > 0 {
if err := x.Status.UnmarshalZAP(raw); err != nil {
return err
}
}
if raw := o.Bytes(sinkConfigFDAt); len(raw) > 0 {
var v fd.FD
if err := v.UnmarshalZAP(raw); err != nil {
return err
}
x.FD = &v
}
return nil
}
// ---- SinkStatus --------------------------------------------------------
const (
sinkStatusDroppedCountAt = 0
sinkStatusSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*SinkStatus)(nil)
// MarshalZAP writes SinkStatus from constant offsets.
func (x *SinkStatus) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(sinkStatusSize + 256)
ob := b.StartObject(sinkStatusSize)
ob.SetUint64(sinkStatusDroppedCountAt, uint64(x.DroppedCount))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads SinkStatus out of the buffer that arrived.
func (x *SinkStatus) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("SinkStatus: %w", err)
}
o := m.Root()
x.DroppedCount = uint64(o.Uint64(sinkStatusDroppedCountAt))
return nil
}
+2
View File
@@ -20,6 +20,7 @@ go_library(
"stateio_impl_util.go",
"stateio_util.go",
"stateio_util_unsafe.go",
"zap.go",
],
visibility = ["//pkg/sentry:internal"],
deps = [
@@ -32,6 +33,7 @@ go_library(
"//pkg/sentry/hostfd",
"//pkg/sentry/memmap",
"//pkg/sync",
"@com_github_zap_proto_go//:go",
"@org_golang_x_sys//unix:go_default_library",
],
)
+72
View File
@@ -0,0 +1,72 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package stateio
import (
"fmt"
zap "github.com/zap-proto/go"
)
// ---- ClientFileRangeSetting --------------------------------------------
const (
clientFileRangeSettingFileRangeAt = 0
clientFileRangeSettingPropertyAt = 8
clientFileRangeSettingSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*ClientFileRangeSetting)(nil)
// MarshalZAP writes ClientFileRangeSetting from constant offsets.
func (x *ClientFileRangeSetting) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(clientFileRangeSettingSize + 256)
ob := b.StartObject(clientFileRangeSettingSize)
innerFileRange, err := x.FileRange.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(clientFileRangeSettingFileRangeAt, innerFileRange)
ob.SetInt64(clientFileRangeSettingPropertyAt, int64(x.Property))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads ClientFileRangeSetting out of the buffer that arrived.
func (x *ClientFileRangeSetting) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("ClientFileRangeSetting: %w", err)
}
o := m.Root()
if raw := o.Bytes(clientFileRangeSettingFileRangeAt); len(raw) > 0 {
if err := x.FileRange.UnmarshalZAP(raw); err != nil {
return err
}
}
x.Property = ClientFileRangeProperty(o.Int64(clientFileRangeSettingPropertyAt))
return nil
}
+6 -1
View File
@@ -54,8 +54,12 @@ go_library(
"server.go",
"sourcefile_atomicptrmap_unsafe.go",
"stateipc.go",
"zap.go",
],
visibility = [
"//pkg/sentry:internal",
"//tools/zap:__pkg__",
],
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/atomicbitops",
"//pkg/cleanup",
@@ -69,6 +73,7 @@ go_library(
"//pkg/sentry/state/stateio",
"//pkg/sync",
"//pkg/urpc",
"@com_github_zap_proto_go//:go",
"@org_golang_x_sys//unix:go_default_library",
],
)
+325
View File
@@ -0,0 +1,325 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package stateipc
import (
"encoding/binary"
"fmt"
"strings"
zap "github.com/zap-proto/go"
stateio "gvisor.dev/gvisor/pkg/sentry/state/stateio"
)
// ---- CloseRequest ------------------------------------------------------
const (
closeRequestHandleAt = 0
closeRequestSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*CloseRequest)(nil)
// MarshalZAP writes CloseRequest from constant offsets.
func (x *CloseRequest) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(closeRequestSize + 256)
ob := b.StartObject(closeRequestSize)
ob.SetUint32(closeRequestHandleAt, uint32(x.Handle))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads CloseRequest out of the buffer that arrived.
func (x *CloseRequest) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("CloseRequest: %w", err)
}
o := m.Root()
x.Handle = uint32(o.Uint32(closeRequestHandleAt))
return nil
}
// ---- CloseResponse -----------------------------------------------------
const (
closeResponseSize = 0
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*CloseResponse)(nil)
// MarshalZAP writes CloseResponse from constant offsets.
func (x *CloseResponse) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(closeResponseSize + 256)
ob := b.StartObject(closeResponseSize)
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads CloseResponse out of the buffer that arrived.
func (x *CloseResponse) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("CloseResponse: %w", err)
}
_ = m
return nil
}
// ---- OpenRequest -------------------------------------------------------
const (
openRequestPathAt = 0
openRequestModeAt = 8
openRequestSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*OpenRequest)(nil)
// MarshalZAP writes OpenRequest from constant offsets.
func (x *OpenRequest) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(openRequestSize + 256)
ob := b.StartObject(openRequestSize)
ob.SetText(openRequestPathAt, string(x.Path))
ob.SetInt64(openRequestModeAt, int64(x.Mode))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads OpenRequest out of the buffer that arrived.
func (x *OpenRequest) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("OpenRequest: %w", err)
}
o := m.Root()
x.Path = string(strings.Clone(o.Text(openRequestPathAt)))
x.Mode = int(o.Int64(openRequestModeAt))
return nil
}
// ---- OpenResponse ------------------------------------------------------
const (
openResponseHandleAt = 0
openResponseMaxIOBytesAt = 4
openResponseMaxRangesAt = 8
openResponseMaxParallelAt = 12
openResponseFilePayloadAt = 16
openResponsePacketWindowOffsetAt = 24
openResponsePacketWindowLengthAt = 32
openResponseSize = 40
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*OpenResponse)(nil)
// MarshalZAP writes OpenResponse from constant offsets.
func (x *OpenResponse) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(openResponseSize + 256)
ob := b.StartObject(openResponseSize)
ob.SetUint32(openResponseHandleAt, uint32(x.Handle))
ob.SetUint32(openResponseMaxIOBytesAt, uint32(x.MaxIOBytes))
ob.SetUint32(openResponseMaxRangesAt, uint32(x.MaxRanges))
ob.SetUint32(openResponseMaxParallelAt, uint32(x.MaxParallel))
innerFilePayload, err := x.FilePayload.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(openResponseFilePayloadAt, innerFilePayload)
ob.SetInt64(openResponsePacketWindowOffsetAt, int64(x.PacketWindowOffset))
ob.SetInt64(openResponsePacketWindowLengthAt, int64(x.PacketWindowLength))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads OpenResponse out of the buffer that arrived.
func (x *OpenResponse) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("OpenResponse: %w", err)
}
o := m.Root()
x.Handle = uint32(o.Uint32(openResponseHandleAt))
x.MaxIOBytes = uint32(o.Uint32(openResponseMaxIOBytesAt))
x.MaxRanges = uint32(o.Uint32(openResponseMaxRangesAt))
x.MaxParallel = uint32(o.Uint32(openResponseMaxParallelAt))
if raw := o.Bytes(openResponseFilePayloadAt); len(raw) > 0 {
if err := x.FilePayload.UnmarshalZAP(raw); err != nil {
return err
}
}
x.PacketWindowOffset = int64(o.Int64(openResponsePacketWindowOffsetAt))
x.PacketWindowLength = int(o.Int64(openResponsePacketWindowLengthAt))
return nil
}
// ---- RegisterClientFileRequest -----------------------------------------
const (
registerClientFileRequestHandleAt = 0
registerClientFileRequestFilePayloadAt = 8
registerClientFileRequestSizeAt = 16
registerClientFileRequestWritableAt = 24
registerClientFileRequestSettingsAt = 32
registerClientFileRequestSize = 40
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*RegisterClientFileRequest)(nil)
// MarshalZAP writes RegisterClientFileRequest from constant offsets.
func (x *RegisterClientFileRequest) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(registerClientFileRequestSize + 256)
settingsAt, settingsN := 0, len(x.Settings)
if settingsN > 0 {
var blob []byte
for i := range x.Settings {
enc, err := x.Settings[i].MarshalZAP()
if err != nil {
return nil, err
}
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
settingsAt = b.WriteBytes(blob)
}
ob := b.StartObject(registerClientFileRequestSize)
ob.SetUint32(registerClientFileRequestHandleAt, uint32(x.Handle))
innerFilePayload, err := x.FilePayload.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(registerClientFileRequestFilePayloadAt, innerFilePayload)
ob.SetUint64(registerClientFileRequestSizeAt, uint64(x.Size))
ob.SetBool(registerClientFileRequestWritableAt, bool(x.Writable))
if settingsN > 0 {
ob.SetList(registerClientFileRequestSettingsAt, settingsAt, settingsN)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads RegisterClientFileRequest out of the buffer that arrived.
func (x *RegisterClientFileRequest) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("RegisterClientFileRequest: %w", err)
}
o := m.Root()
x.Handle = uint32(o.Uint32(registerClientFileRequestHandleAt))
if raw := o.Bytes(registerClientFileRequestFilePayloadAt); len(raw) > 0 {
if err := x.FilePayload.UnmarshalZAP(raw); err != nil {
return err
}
}
x.Size = uint64(o.Uint64(registerClientFileRequestSizeAt))
x.Writable = bool(o.Bool(registerClientFileRequestWritableAt))
if l := o.List(registerClientFileRequestSettingsAt); l.Len() > 0 {
rows := make([]stateio.ClientFileRangeSetting, l.Len())
for i := range rows {
if err := rows[i].UnmarshalZAP(l.BytesAt(i)); err != nil {
return err
}
}
x.Settings = rows
}
return nil
}
// ---- RegisterClientFileResponse ----------------------------------------
const (
registerClientFileResponseHandleAt = 0
registerClientFileResponseSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*RegisterClientFileResponse)(nil)
// MarshalZAP writes RegisterClientFileResponse from constant offsets.
func (x *RegisterClientFileResponse) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(registerClientFileResponseSize + 256)
ob := b.StartObject(registerClientFileResponseSize)
ob.SetUint32(registerClientFileResponseHandleAt, uint32(x.Handle))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads RegisterClientFileResponse out of the buffer that arrived.
func (x *RegisterClientFileResponse) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("RegisterClientFileResponse: %w", err)
}
o := m.Root()
x.Handle = uint32(o.Uint32(registerClientFileResponseHandleAt))
return nil
}
+5 -1
View File
@@ -7,13 +7,17 @@ package(
go_library(
name = "urpc",
srcs = ["urpc.go"],
srcs = [
"urpc.go",
"zap.go",
],
visibility = ["//:sandbox"],
deps = [
"//pkg/fd",
"//pkg/log",
"//pkg/sync",
"//pkg/unet",
"@com_github_zap_proto_go//:go",
],
)
+85
View File
@@ -0,0 +1,85 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package urpc
import (
"encoding/binary"
"fmt"
"os"
zap "github.com/zap-proto/go"
)
// ---- FilePayload -------------------------------------------------------
const (
filePayloadFilesAt = 0
filePayloadSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*FilePayload)(nil)
// MarshalZAP writes FilePayload from constant offsets.
func (x *FilePayload) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(filePayloadSize + 256)
filesAt, filesN := 0, len(x.Files)
if filesN > 0 {
var blob []byte
for range x.Files {
eb := zap.NewBuilder(zap.HeaderSize)
eb.StartObject(0).FinishAsRoot()
enc := eb.Finish()
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
filesAt = b.WriteBytes(blob)
}
ob := b.StartObject(filePayloadSize)
if filesN > 0 {
ob.SetList(filePayloadFilesAt, filesAt, filesN)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads FilePayload out of the buffer that arrived.
func (x *FilePayload) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("FilePayload: %w", err)
}
o := m.Root()
if l := o.List(filePayloadFilesAt); l.Len() > 0 {
rows := make([]*os.File, l.Len())
for i := range rows {
rows[i] = new(os.File)
}
x.Files = rows
}
return nil
}
+3
View File
@@ -27,11 +27,13 @@ go_library(
"strace.go",
"tpuproxy.go",
"vfs.go",
"zap.go",
],
visibility = [
"//pkg/test:__subpackages__",
"//runsc:__subpackages__",
"//test:__subpackages__",
"//tools/zap:__pkg__",
],
deps = [
"//pkg/abi",
@@ -162,6 +164,7 @@ go_library(
"//runsc/version",
"@com_github_moby_sys_capability//:go_default_library",
"@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_zap_proto_go//:go",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
+31 -14
View File
@@ -15,6 +15,7 @@
package boot
import (
"encoding/json"
"errors"
"fmt"
"io"
@@ -351,8 +352,10 @@ func (cm *containerManager) CreateSubcontainer(args *CreateArgs, _ *struct{}) er
// StartArgs contains arguments to the Start method.
type StartArgs struct {
// Spec is the spec of the container to start.
Spec *specs.Spec
// Spec is the OCI runtime spec of the container to start, as the bytes it
// was read from. The spec belongs to another module and cannot state its
// own wire; it is a document, and it crosses as itself.
Spec []byte
// Config is the runsc-specific configuration for the sandbox.
Conf *config.Config
@@ -383,6 +386,18 @@ type StartArgs struct {
urpc.FilePayload
}
// spec reads the OCI runtime spec the caller sent.
func (a *StartArgs) spec() (*specs.Spec, error) {
if len(a.Spec) == 0 {
return nil, errors.New("start arguments missing spec")
}
var spec specs.Spec
if err := json.Unmarshal(a.Spec, &spec); err != nil {
return nil, fmt.Errorf("reading spec: %w", err)
}
return &spec, nil
}
// StartSubcontainer runs a created container within a sandbox.
func (cm *containerManager) StartSubcontainer(args *StartArgs, _ *struct{}) error {
// Validate arguments.
@@ -390,8 +405,9 @@ func (cm *containerManager) StartSubcontainer(args *StartArgs, _ *struct{}) erro
return errors.New("start missing arguments")
}
log.Debugf("containerManager.StartSubcontainer, cid: %s, args: %+v", args.CID, args)
if args.Spec == nil {
return errors.New("start arguments missing spec")
spec, err := args.spec()
if err != nil {
return err
}
if args.Conf == nil {
return errors.New("start arguments missing config")
@@ -416,7 +432,7 @@ func (cm *containerManager) StartSubcontainer(args *StartArgs, _ *struct{}) erro
if args.IsDevIoFilePresent {
expectedFDs++
}
if !args.Spec.Process.Terminal {
if !spec.Process.Terminal {
expectedFDs += 3
}
if args.IsRootfsUpperTarFilePresent {
@@ -430,11 +446,11 @@ func (cm *containerManager) StartSubcontainer(args *StartArgs, _ *struct{}) erro
}
// All validation passed, logs the spec for debugging.
specutils.LogSpecDebug(args.Spec, args.Conf.OCISeccomp)
specutils.LogSpecDebug(spec, args.Conf.OCISeccomp)
goferFiles := args.Files
var stdios []*fd.FD
if !args.Spec.Process.Terminal {
if !spec.Process.Terminal {
// When not using a terminal, stdios come as the first 3 files in the
// payload.
var err error
@@ -497,7 +513,7 @@ func (cm *containerManager) StartSubcontainer(args *StartArgs, _ *struct{}) erro
}
}()
if err := cm.l.startSubcontainer(args.Spec, args.Conf, args.CID, stdios, goferFDs, goferFilestoreFDs, devGoferFD, args.GoferMountConfs, rootfsUpperTarFD); err != nil {
if err := cm.l.startSubcontainer(spec, args.Conf, args.CID, stdios, goferFDs, goferFilestoreFDs, devGoferFD, args.GoferMountConfs, rootfsUpperTarFD); err != nil {
log.Debugf("containerManager.StartSubcontainer failed, cid: %s, args: %+v, err: %v", args.CID, args, err)
return err
}
@@ -825,8 +841,9 @@ func (cm *containerManager) RestoreSubcontainer(args *StartArgs, _ *struct{}) (r
}()
// Validate arguments.
if args.Spec == nil {
return errors.New("start arguments missing spec")
spec, err := args.spec()
if err != nil {
return err
}
if args.Conf == nil {
return errors.New("start arguments missing config")
@@ -839,7 +856,7 @@ func (cm *containerManager) RestoreSubcontainer(args *StartArgs, _ *struct{}) (r
if args.IsDevIoFilePresent {
expectedFDs++
}
if !args.Spec.Process.Terminal {
if !spec.Process.Terminal {
expectedFDs += 3
}
if args.IsRootfsUpperTarFilePresent {
@@ -850,11 +867,11 @@ func (cm *containerManager) RestoreSubcontainer(args *StartArgs, _ *struct{}) (r
}
// All validation passed, logs the spec for debugging.
specutils.LogSpecDebug(args.Spec, args.Conf.OCISeccomp)
specutils.LogSpecDebug(spec, args.Conf.OCISeccomp)
goferFiles := args.Files
var stdios []*fd.FD
if !args.Spec.Process.Terminal {
if !spec.Process.Terminal {
// When not using a terminal, stdios come as the first 3 files in the
// payload.
var err error
@@ -890,7 +907,7 @@ func (cm *containerManager) RestoreSubcontainer(args *StartArgs, _ *struct{}) (r
return fmt.Errorf("error dup'ing gofer files: %w", err)
}
err = cm.restorer.restoreSubcontainer(args.Spec, args.Conf, cm.l, args.CID, stdios, goferFDs, goferFilestoreFDs, devGoferFD, args.GoferMountConfs)
err = cm.restorer.restoreSubcontainer(spec, args.Conf, cm.l, args.CID, stdios, goferFDs, goferFilestoreFDs, devGoferFD, args.GoferMountConfs)
if err != nil {
log.Debugf("containerManager.RestoreSubcontainer failed, cid: %s, args: %+v, err: %v", args.CID, args, err)
return err
+1 -1
View File
@@ -654,7 +654,7 @@ func TestNetworkConfig(t *testing.T) {
},
Routes: []Route{
{
Destination: net.IPNet{
Destination: Subnet{
IP: net.IP{127, 0, 0, 0},
Mask: net.IPMask{255, 0, 0, 0},
},
+11 -3
View File
@@ -53,13 +53,13 @@ var DefaultLoopbackLink = LoopbackLink{
},
Routes: []Route{
{
Destination: net.IPNet{
Destination: Subnet{
IP: net.IPv4(0x7f, 0, 0, 0),
Mask: net.IPv4Mask(0xff, 0, 0, 0),
},
},
{
Destination: net.IPNet{
Destination: Subnet{
IP: net.IPv6loopback,
Mask: net.IPMask(strings.Repeat("\xff", net.IPv6len)),
},
@@ -77,9 +77,17 @@ type Network struct {
PluginStack plugin.PluginStack
}
// Subnet is an address and the mask that selects its network. It restates
// net.IPNet, which the RPC cannot carry: a stdlib type cannot state its own
// wire, and a conversion between the two is legal in either direction.
type Subnet struct {
IP net.IP
Mask net.IPMask
}
// Route represents a route in the network stack.
type Route struct {
Destination net.IPNet
Destination Subnet
Gateway net.IP
MTU uint32
}
+1 -1
View File
@@ -191,7 +191,7 @@ func saveOptsFromSpec(spec *specs.Spec, fds []*fd.FD, useCheckpointGofer bool) (
FilePayload: urpc.FilePayload{
Files: files,
},
Metadata: comp.ToMetadata(),
Metadata: control.Pairs(comp.ToMetadata()),
HavePagesFile: len(files) > 1,
Resume: specutils.AnnotationToBool(spec, annotationCheckpointResume),
CudaCheckpointSequential: specutils.AnnotationToBool(spec, annotationCheckpointCudaCheckpointSequential),
+1486
View File
File diff suppressed because it is too large Load Diff
+14 -2
View File
@@ -554,8 +554,11 @@ func lisafsNeededForDirectFSSuppression(spec *specs.Spec, mountHints *boot.PodMo
func makeRPCMountOpener(goferToHostRPC *urpc.Client) sandboxsetup.MountOpener {
return func(m *specs.Mount, flags uint32) (*os.File, error) {
req := container.OpenMountArgs{
Mount: m,
Flags: flags,
Source: m.Source,
Options: m.Options,
UIDs: mappings(m.UIDMappings),
GIDs: mappings(m.GIDMappings),
Flags: flags,
}
var res container.OpenMountResult
if err := goferToHostRPC.Call("goferToHostRPC.OpenMount", &req, &res); err != nil {
@@ -565,6 +568,15 @@ func makeRPCMountOpener(goferToHostRPC *urpc.Client) sandboxsetup.MountOpener {
}
}
// mappings restates an OCI id map as the RPC carries it.
func mappings(ms []specs.LinuxIDMapping) []container.Mapping {
out := make([]container.Mapping, len(ms))
for i, m := range ms {
out[i] = container.Mapping{Container: m.ContainerID, Host: m.HostID, Size: m.Size}
}
return out
}
// setFlags sets sync FD flags on the given FlagSet.
func (g *goferSyncFDs) setFlags(f *flag.FlagSet) {
f.IntVar(&g.chrootFD, "sync-chroot-fd", -1, "file descriptor that the gofer waits on until container filesystem setup is done")
+2
View File
@@ -14,6 +14,7 @@ go_library(
"config_bundles.go",
"flags.go",
"flags_graveyard.go",
"zap.go",
],
visibility = ["//:sandbox"],
deps = [
@@ -23,6 +24,7 @@ go_library(
"//pkg/sync",
"//runsc/flag",
"//runsc/version",
"@com_github_zap_proto_go//:go",
],
)
+431
View File
@@ -0,0 +1,431 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package config
import (
"fmt"
"strings"
"time"
zap "github.com/zap-proto/go"
refs "gvisor.dev/gvisor/pkg/refs"
)
// ---- Config ------------------------------------------------------------
const (
configRootDirAt = 0
configTracebackAt = 8
configDebugAt = 16
configLogFilenameAt = 24
configLogFormatAt = 32
configDebugLogAt = 40
configDebugToUserLogAt = 48
configDebugCommandAt = 56
configPanicLogAt = 64
configCoverageReportAt = 72
configDebugLogFormatAt = 80
configFileAccessAt = 88
configFileAccessMountsAt = 96
configOverlayAt = 104
configOverlay2At = 112
configFSGoferHostUDSAt = 120
configHostUDSAt = 128
configHostFifoAt = 136
configCharacterDevicePolicyAt = 144
configHostSettingsAt = 152
configNetworkAt = 160
configGoferNetworkNamespaceAt = 168
configEnableRawAt = 176
configAllowPacketEndpointWriteAt = 177
configAllowLiveTCPMigrationAt = 178
configHostGSOAt = 179
configGVisorGSOAt = 180
configGVisorGROAt = 181
configTXChecksumOffloadAt = 182
configRXChecksumOffloadAt = 183
configQDiscAt = 184
configTBFRateAt = 192
configTBFBurstAt = 200
configLogPacketsAt = 208
configPCAPAt = 216
configPlatformAt = 224
configPlatformDevicePathAt = 232
configMetricServerAt = 240
configSidecarReleaseEnforcementPolicyAt = 248
configSidecarUsagePolicyAt = 256
configFinalMetricsLogAt = 264
configProfilingMetricsAt = 272
configProfilingMetricsLogAt = 280
configProfilingMetricsRateAt = 288
configStraceAt = 296
configStraceSyscallsAt = 304
configStraceLogSizeAt = 312
configStraceEventAt = 320
configDisableSeccompAt = 321
configEnableCoreTagsAt = 322
configWatchdogActionAt = 328
configPanicSignalAt = 336
configProfileEnableAt = 344
configProfileBlockAt = 352
configProfileCPUAt = 360
configProfileGCIntervalAt = 368
configProfileHeapAt = 376
configProfileMutexAt = 384
configTraceFileAt = 392
configNumNetworkChannelsAt = 400
configNetworkProcessorsPerChannelAt = 408
configRootlessAt = 416
configAlsoLogToStderrAt = 417
configReferenceLeakAt = 420
configCPUNumFromQuotaAt = 424
configAllowFlagOverrideAt = 425
configOCISeccompAt = 426
configIgnoreCgroupsAt = 427
configInSandboxCgroupAt = 432
configSystemdCgroupAt = 440
configPodInitConfigAt = 448
configXDPAt = 456
configAFXDPUseNeedWakeupAt = 464
configFDLimitAt = 472
configDCacheAt = 480
configIOUringAt = 488
configDirectFSAt = 489
configAppHugePagesAt = 490
configNVProxyAt = 491
configNVProxyDockerAt = 492
configNVProxyDriverVersionAt = 496
configNVProxyAllowedDriverCapabilitiesAt = 504
configNVProxyAllowUnsupportedDriverAt = 512
configTPUProxyAt = 513
configRDMAProxyAt = 514
configTestOnlyAllowRunAsCurrentUserWithoutChrootAt = 515
configTestOnlyTestNameEnvAt = 520
configTestOnlyAFSSyscallPanicAt = 528
configReproduceNATAt = 529
configReproduceNftablesAt = 530
configNetDisconnectOkAt = 531
configTestOnlyAutosaveImagePathAt = 536
configTestOnlyAutosaveResumeAt = 544
configRestoreSpecValidationAt = 552
configGVisorMarkerFileAt = 560
configOverrideProcsAt = 568
configSystrapDisableSyscallPatchingAt = 576
configSystrapDisableFastPathAt = 577
configNftablesAt = 578
configAllowSUIDAt = 579
configUseCPUNumsAt = 580
configPauseExternalNetworkingAt = 581
configAllowConnectedOnSaveAt = 582
configAllowRootfsTarAnnotationAt = 583
configControlRPCStopTimeoutAt = 584
configSharedRootDirAt = 592
configSize = 600
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*Config)(nil)
// MarshalZAP writes Config from constant offsets.
func (x *Config) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(configSize + 256)
ob := b.StartObject(configSize)
ob.SetText(configRootDirAt, string(x.RootDir))
ob.SetText(configTracebackAt, string(x.Traceback))
ob.SetBool(configDebugAt, bool(x.Debug))
ob.SetText(configLogFilenameAt, string(x.LogFilename))
ob.SetText(configLogFormatAt, string(x.LogFormat))
ob.SetText(configDebugLogAt, string(x.DebugLog))
ob.SetBool(configDebugToUserLogAt, bool(x.DebugToUserLog))
ob.SetText(configDebugCommandAt, string(x.DebugCommand))
ob.SetText(configPanicLogAt, string(x.PanicLog))
ob.SetText(configCoverageReportAt, string(x.CoverageReport))
ob.SetText(configDebugLogFormatAt, string(x.DebugLogFormat))
ob.SetInt64(configFileAccessAt, int64(x.FileAccess))
ob.SetInt64(configFileAccessMountsAt, int64(x.FileAccessMounts))
ob.SetBool(configOverlayAt, bool(x.Overlay))
{
eb := zap.NewBuilder(zap.HeaderSize)
eb.StartObject(0).FinishAsRoot()
ob.SetBytes(configOverlay2At, eb.Finish())
}
ob.SetBool(configFSGoferHostUDSAt, bool(x.FSGoferHostUDS))
ob.SetInt64(configHostUDSAt, int64(x.HostUDS))
ob.SetInt64(configHostFifoAt, int64(x.HostFifo))
ob.SetInt64(configCharacterDevicePolicyAt, int64(x.CharacterDevicePolicy))
ob.SetInt64(configHostSettingsAt, int64(x.HostSettings))
ob.SetInt64(configNetworkAt, int64(x.Network))
ob.SetText(configGoferNetworkNamespaceAt, string(x.GoferNetworkNamespace))
ob.SetBool(configEnableRawAt, bool(x.EnableRaw))
ob.SetBool(configAllowPacketEndpointWriteAt, bool(x.AllowPacketEndpointWrite))
ob.SetBool(configAllowLiveTCPMigrationAt, bool(x.AllowLiveTCPMigration))
ob.SetBool(configHostGSOAt, bool(x.HostGSO))
ob.SetBool(configGVisorGSOAt, bool(x.GVisorGSO))
ob.SetBool(configGVisorGROAt, bool(x.GVisorGRO))
ob.SetBool(configTXChecksumOffloadAt, bool(x.TXChecksumOffload))
ob.SetBool(configRXChecksumOffloadAt, bool(x.RXChecksumOffload))
ob.SetInt64(configQDiscAt, int64(x.QDisc))
ob.SetUint64(configTBFRateAt, uint64(x.TBFRate))
ob.SetUint64(configTBFBurstAt, uint64(x.TBFBurst))
ob.SetBool(configLogPacketsAt, bool(x.LogPackets))
ob.SetText(configPCAPAt, string(x.PCAP))
ob.SetText(configPlatformAt, string(x.Platform))
ob.SetText(configPlatformDevicePathAt, string(x.PlatformDevicePath))
ob.SetText(configMetricServerAt, string(x.MetricServer))
ob.SetText(configSidecarReleaseEnforcementPolicyAt, string(x.SidecarReleaseEnforcementPolicy))
ob.SetText(configSidecarUsagePolicyAt, string(x.SidecarUsagePolicy))
ob.SetText(configFinalMetricsLogAt, string(x.FinalMetricsLog))
ob.SetText(configProfilingMetricsAt, string(x.ProfilingMetrics))
ob.SetText(configProfilingMetricsLogAt, string(x.ProfilingMetricsLog))
ob.SetInt64(configProfilingMetricsRateAt, int64(x.ProfilingMetricsRate))
ob.SetBool(configStraceAt, bool(x.Strace))
ob.SetText(configStraceSyscallsAt, string(x.StraceSyscalls))
ob.SetUint64(configStraceLogSizeAt, uint64(x.StraceLogSize))
ob.SetBool(configStraceEventAt, bool(x.StraceEvent))
ob.SetBool(configDisableSeccompAt, bool(x.DisableSeccomp))
ob.SetBool(configEnableCoreTagsAt, bool(x.EnableCoreTags))
ob.SetText(configWatchdogActionAt, string(x.WatchdogAction))
ob.SetInt64(configPanicSignalAt, int64(x.PanicSignal))
ob.SetBool(configProfileEnableAt, bool(x.ProfileEnable))
ob.SetText(configProfileBlockAt, string(x.ProfileBlock))
ob.SetText(configProfileCPUAt, string(x.ProfileCPU))
ob.SetInt64(configProfileGCIntervalAt, int64(x.ProfileGCInterval))
ob.SetText(configProfileHeapAt, string(x.ProfileHeap))
ob.SetText(configProfileMutexAt, string(x.ProfileMutex))
ob.SetText(configTraceFileAt, string(x.TraceFile))
ob.SetInt64(configNumNetworkChannelsAt, int64(x.NumNetworkChannels))
ob.SetInt64(configNetworkProcessorsPerChannelAt, int64(x.NetworkProcessorsPerChannel))
ob.SetBool(configRootlessAt, bool(x.Rootless))
ob.SetBool(configAlsoLogToStderrAt, bool(x.AlsoLogToStderr))
ob.SetUint32(configReferenceLeakAt, uint32(x.ReferenceLeak))
ob.SetBool(configCPUNumFromQuotaAt, bool(x.CPUNumFromQuota))
ob.SetBool(configAllowFlagOverrideAt, bool(x.AllowFlagOverride))
ob.SetBool(configOCISeccompAt, bool(x.OCISeccomp))
ob.SetBool(configIgnoreCgroupsAt, bool(x.IgnoreCgroups))
ob.SetInt64(configInSandboxCgroupAt, int64(x.InSandboxCgroup))
ob.SetBool(configSystemdCgroupAt, bool(x.SystemdCgroup))
ob.SetText(configPodInitConfigAt, string(x.PodInitConfig))
innerXDP, err := x.XDP.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(configXDPAt, innerXDP)
ob.SetBool(configAFXDPUseNeedWakeupAt, bool(x.AFXDPUseNeedWakeup))
ob.SetInt64(configFDLimitAt, int64(x.FDLimit))
ob.SetInt64(configDCacheAt, int64(x.DCache))
ob.SetBool(configIOUringAt, bool(x.IOUring))
ob.SetBool(configDirectFSAt, bool(x.DirectFS))
ob.SetBool(configAppHugePagesAt, bool(x.AppHugePages))
ob.SetBool(configNVProxyAt, bool(x.NVProxy))
ob.SetBool(configNVProxyDockerAt, bool(x.NVProxyDocker))
ob.SetText(configNVProxyDriverVersionAt, string(x.NVProxyDriverVersion))
ob.SetText(configNVProxyAllowedDriverCapabilitiesAt, string(x.NVProxyAllowedDriverCapabilities))
ob.SetBool(configNVProxyAllowUnsupportedDriverAt, bool(x.NVProxyAllowUnsupportedDriver))
ob.SetBool(configTPUProxyAt, bool(x.TPUProxy))
ob.SetBool(configRDMAProxyAt, bool(x.RDMAProxy))
ob.SetBool(configTestOnlyAllowRunAsCurrentUserWithoutChrootAt, bool(x.TestOnlyAllowRunAsCurrentUserWithoutChroot))
ob.SetText(configTestOnlyTestNameEnvAt, string(x.TestOnlyTestNameEnv))
ob.SetBool(configTestOnlyAFSSyscallPanicAt, bool(x.TestOnlyAFSSyscallPanic))
ob.SetBool(configReproduceNATAt, bool(x.ReproduceNAT))
ob.SetBool(configReproduceNftablesAt, bool(x.ReproduceNftables))
ob.SetBool(configNetDisconnectOkAt, bool(x.NetDisconnectOk))
ob.SetText(configTestOnlyAutosaveImagePathAt, string(x.TestOnlyAutosaveImagePath))
ob.SetBool(configTestOnlyAutosaveResumeAt, bool(x.TestOnlyAutosaveResume))
ob.SetInt64(configRestoreSpecValidationAt, int64(x.RestoreSpecValidation))
ob.SetBool(configGVisorMarkerFileAt, bool(x.GVisorMarkerFile))
ob.SetText(configOverrideProcsAt, string(x.OverrideProcs))
ob.SetBool(configSystrapDisableSyscallPatchingAt, bool(x.SystrapDisableSyscallPatching))
ob.SetBool(configSystrapDisableFastPathAt, bool(x.SystrapDisableFastPath))
ob.SetBool(configNftablesAt, bool(x.Nftables))
ob.SetBool(configAllowSUIDAt, bool(x.AllowSUID))
ob.SetBool(configUseCPUNumsAt, bool(x.UseCPUNums))
ob.SetBool(configPauseExternalNetworkingAt, bool(x.PauseExternalNetworking))
ob.SetBool(configAllowConnectedOnSaveAt, bool(x.AllowConnectedOnSave))
ob.SetBool(configAllowRootfsTarAnnotationAt, bool(x.AllowRootfsTarAnnotation))
ob.SetInt64(configControlRPCStopTimeoutAt, int64(x.ControlRPCStopTimeout))
ob.SetText(configSharedRootDirAt, string(x.SharedRootDir))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads Config out of the buffer that arrived.
func (x *Config) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("Config: %w", err)
}
o := m.Root()
x.RootDir = string(strings.Clone(o.Text(configRootDirAt)))
x.Traceback = string(strings.Clone(o.Text(configTracebackAt)))
x.Debug = bool(o.Bool(configDebugAt))
x.LogFilename = string(strings.Clone(o.Text(configLogFilenameAt)))
x.LogFormat = string(strings.Clone(o.Text(configLogFormatAt)))
x.DebugLog = string(strings.Clone(o.Text(configDebugLogAt)))
x.DebugToUserLog = bool(o.Bool(configDebugToUserLogAt))
x.DebugCommand = string(strings.Clone(o.Text(configDebugCommandAt)))
x.PanicLog = string(strings.Clone(o.Text(configPanicLogAt)))
x.CoverageReport = string(strings.Clone(o.Text(configCoverageReportAt)))
x.DebugLogFormat = string(strings.Clone(o.Text(configDebugLogFormatAt)))
x.FileAccess = FileAccessType(o.Int64(configFileAccessAt))
x.FileAccessMounts = FileAccessType(o.Int64(configFileAccessMountsAt))
x.Overlay = bool(o.Bool(configOverlayAt))
x.FSGoferHostUDS = bool(o.Bool(configFSGoferHostUDSAt))
x.HostUDS = HostUDS(o.Int64(configHostUDSAt))
x.HostFifo = HostFifo(o.Int64(configHostFifoAt))
x.CharacterDevicePolicy = CharacterDevicePolicy(o.Int64(configCharacterDevicePolicyAt))
x.HostSettings = HostSettingsPolicy(o.Int64(configHostSettingsAt))
x.Network = NetworkType(o.Int64(configNetworkAt))
x.GoferNetworkNamespace = GoferNetworkNamespace(strings.Clone(o.Text(configGoferNetworkNamespaceAt)))
x.EnableRaw = bool(o.Bool(configEnableRawAt))
x.AllowPacketEndpointWrite = bool(o.Bool(configAllowPacketEndpointWriteAt))
x.AllowLiveTCPMigration = bool(o.Bool(configAllowLiveTCPMigrationAt))
x.HostGSO = bool(o.Bool(configHostGSOAt))
x.GVisorGSO = bool(o.Bool(configGVisorGSOAt))
x.GVisorGRO = bool(o.Bool(configGVisorGROAt))
x.TXChecksumOffload = bool(o.Bool(configTXChecksumOffloadAt))
x.RXChecksumOffload = bool(o.Bool(configRXChecksumOffloadAt))
x.QDisc = QueueingDiscipline(o.Int64(configQDiscAt))
x.TBFRate = uint64(o.Uint64(configTBFRateAt))
x.TBFBurst = uint64(o.Uint64(configTBFBurstAt))
x.LogPackets = bool(o.Bool(configLogPacketsAt))
x.PCAP = string(strings.Clone(o.Text(configPCAPAt)))
x.Platform = string(strings.Clone(o.Text(configPlatformAt)))
x.PlatformDevicePath = string(strings.Clone(o.Text(configPlatformDevicePathAt)))
x.MetricServer = string(strings.Clone(o.Text(configMetricServerAt)))
x.SidecarReleaseEnforcementPolicy = SidecarReleasePolicy(strings.Clone(o.Text(configSidecarReleaseEnforcementPolicyAt)))
x.SidecarUsagePolicy = SidecarUsagePolicy(strings.Clone(o.Text(configSidecarUsagePolicyAt)))
x.FinalMetricsLog = string(strings.Clone(o.Text(configFinalMetricsLogAt)))
x.ProfilingMetrics = string(strings.Clone(o.Text(configProfilingMetricsAt)))
x.ProfilingMetricsLog = string(strings.Clone(o.Text(configProfilingMetricsLogAt)))
x.ProfilingMetricsRate = int(o.Int64(configProfilingMetricsRateAt))
x.Strace = bool(o.Bool(configStraceAt))
x.StraceSyscalls = string(strings.Clone(o.Text(configStraceSyscallsAt)))
x.StraceLogSize = uint(o.Uint64(configStraceLogSizeAt))
x.StraceEvent = bool(o.Bool(configStraceEventAt))
x.DisableSeccomp = bool(o.Bool(configDisableSeccompAt))
x.EnableCoreTags = bool(o.Bool(configEnableCoreTagsAt))
x.WatchdogAction = string(strings.Clone(o.Text(configWatchdogActionAt)))
x.PanicSignal = int(o.Int64(configPanicSignalAt))
x.ProfileEnable = bool(o.Bool(configProfileEnableAt))
x.ProfileBlock = string(strings.Clone(o.Text(configProfileBlockAt)))
x.ProfileCPU = string(strings.Clone(o.Text(configProfileCPUAt)))
x.ProfileGCInterval = time.Duration(o.Int64(configProfileGCIntervalAt))
x.ProfileHeap = string(strings.Clone(o.Text(configProfileHeapAt)))
x.ProfileMutex = string(strings.Clone(o.Text(configProfileMutexAt)))
x.TraceFile = string(strings.Clone(o.Text(configTraceFileAt)))
x.NumNetworkChannels = int(o.Int64(configNumNetworkChannelsAt))
x.NetworkProcessorsPerChannel = int(o.Int64(configNetworkProcessorsPerChannelAt))
x.Rootless = bool(o.Bool(configRootlessAt))
x.AlsoLogToStderr = bool(o.Bool(configAlsoLogToStderrAt))
x.ReferenceLeak = refs.LeakMode(o.Uint32(configReferenceLeakAt))
x.CPUNumFromQuota = bool(o.Bool(configCPUNumFromQuotaAt))
x.AllowFlagOverride = bool(o.Bool(configAllowFlagOverrideAt))
x.OCISeccomp = bool(o.Bool(configOCISeccompAt))
x.IgnoreCgroups = bool(o.Bool(configIgnoreCgroupsAt))
x.InSandboxCgroup = InSandboxCgroupType(o.Int64(configInSandboxCgroupAt))
x.SystemdCgroup = bool(o.Bool(configSystemdCgroupAt))
x.PodInitConfig = string(strings.Clone(o.Text(configPodInitConfigAt)))
if raw := o.Bytes(configXDPAt); len(raw) > 0 {
if err := x.XDP.UnmarshalZAP(raw); err != nil {
return err
}
}
x.AFXDPUseNeedWakeup = bool(o.Bool(configAFXDPUseNeedWakeupAt))
x.FDLimit = int(o.Int64(configFDLimitAt))
x.DCache = int(o.Int64(configDCacheAt))
x.IOUring = bool(o.Bool(configIOUringAt))
x.DirectFS = bool(o.Bool(configDirectFSAt))
x.AppHugePages = bool(o.Bool(configAppHugePagesAt))
x.NVProxy = bool(o.Bool(configNVProxyAt))
x.NVProxyDocker = bool(o.Bool(configNVProxyDockerAt))
x.NVProxyDriverVersion = string(strings.Clone(o.Text(configNVProxyDriverVersionAt)))
x.NVProxyAllowedDriverCapabilities = string(strings.Clone(o.Text(configNVProxyAllowedDriverCapabilitiesAt)))
x.NVProxyAllowUnsupportedDriver = bool(o.Bool(configNVProxyAllowUnsupportedDriverAt))
x.TPUProxy = bool(o.Bool(configTPUProxyAt))
x.RDMAProxy = bool(o.Bool(configRDMAProxyAt))
x.TestOnlyAllowRunAsCurrentUserWithoutChroot = bool(o.Bool(configTestOnlyAllowRunAsCurrentUserWithoutChrootAt))
x.TestOnlyTestNameEnv = string(strings.Clone(o.Text(configTestOnlyTestNameEnvAt)))
x.TestOnlyAFSSyscallPanic = bool(o.Bool(configTestOnlyAFSSyscallPanicAt))
x.ReproduceNAT = bool(o.Bool(configReproduceNATAt))
x.ReproduceNftables = bool(o.Bool(configReproduceNftablesAt))
x.NetDisconnectOk = bool(o.Bool(configNetDisconnectOkAt))
x.TestOnlyAutosaveImagePath = string(strings.Clone(o.Text(configTestOnlyAutosaveImagePathAt)))
x.TestOnlyAutosaveResume = bool(o.Bool(configTestOnlyAutosaveResumeAt))
x.RestoreSpecValidation = RestoreSpecValidationPolicy(o.Int64(configRestoreSpecValidationAt))
x.GVisorMarkerFile = bool(o.Bool(configGVisorMarkerFileAt))
x.OverrideProcs = string(strings.Clone(o.Text(configOverrideProcsAt)))
x.SystrapDisableSyscallPatching = bool(o.Bool(configSystrapDisableSyscallPatchingAt))
x.SystrapDisableFastPath = bool(o.Bool(configSystrapDisableFastPathAt))
x.Nftables = bool(o.Bool(configNftablesAt))
x.AllowSUID = bool(o.Bool(configAllowSUIDAt))
x.UseCPUNums = bool(o.Bool(configUseCPUNumsAt))
x.PauseExternalNetworking = bool(o.Bool(configPauseExternalNetworkingAt))
x.AllowConnectedOnSave = bool(o.Bool(configAllowConnectedOnSaveAt))
x.AllowRootfsTarAnnotation = bool(o.Bool(configAllowRootfsTarAnnotationAt))
x.ControlRPCStopTimeout = time.Duration(o.Int64(configControlRPCStopTimeoutAt))
x.SharedRootDir = string(strings.Clone(o.Text(configSharedRootDirAt)))
return nil
}
// ---- XDP ---------------------------------------------------------------
const (
xDPModeAt = 0
xDPIfaceNameAt = 8
xDPSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*XDP)(nil)
// MarshalZAP writes XDP from constant offsets.
func (x *XDP) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(xDPSize + 256)
ob := b.StartObject(xDPSize)
ob.SetInt64(xDPModeAt, int64(x.Mode))
ob.SetText(xDPIfaceNameAt, string(x.IfaceName))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads XDP out of the buffer that arrived.
func (x *XDP) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("XDP: %w", err)
}
o := m.Root()
x.Mode = XDPMode(o.Int64(xDPModeAt))
x.IfaceName = string(strings.Clone(o.Text(xDPIfaceNameAt)))
return nil
}
+3
View File
@@ -13,10 +13,12 @@ go_library(
"null_netns.go",
"state_file.go",
"status.go",
"zap.go",
],
visibility = [
"//runsc:__subpackages__",
"//test:__subpackages__",
"//tools/zap:__pkg__",
],
deps = [
"//pkg/abi/linux",
@@ -42,6 +44,7 @@ go_library(
"//runsc/starttime",
"@com_github_gofrs_flock//:go_default_library",
"@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_zap_proto_go//:go",
"@org_golang_x_sys//unix:go_default_library",
],
)
+42 -17
View File
@@ -22,18 +22,43 @@ import (
"sync"
"syscall"
specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/urpc"
"gvisor.dev/gvisor/runsc/specutils"
)
// OpenMountArgs represents a mount to be opened along with its flags.
// OpenMountArgs is one mount source for the host to open on the gofer's
// behalf. It states the mount in this package because the RPC carries it: the
// OCI type it comes from belongs to another module, and a type from another
// module cannot state its own wire.
type OpenMountArgs struct {
Mount *specs.Mount
// Source is the path to open.
Source string
// Options are the mount options the OCI spec gave.
Options []string
// UIDs and GIDs are the mount's id maps.
UIDs []Mapping
GIDs []Mapping
// Flags are the Linux mount flags.
Flags uint32
}
// Mapping is one id range: Size ids starting at Host stand for Size ids
// starting at Container.
type Mapping struct {
Container uint32
Host uint32
Size uint32
}
// mapped reports a source the host must open through an id-mapped user
// namespace, which is what carrying both maps means.
func (a *OpenMountArgs) mapped() bool {
return len(a.UIDs) > 0 && len(a.GIDs) > 0
}
type openMountRequest struct {
args *OpenMountArgs
result *OpenMountResult
@@ -54,12 +79,12 @@ type OpenMountResult struct {
urpc.FilePayload
}
func createIDMappedUserNS(uidMappings, gidMappings []specs.LinuxIDMapping) (*os.File, error) {
func createIDMappedUserNS(uidMappings, gidMappings []Mapping) (*os.File, error) {
var sysUIDMaps []syscall.SysProcIDMap
for _, m := range uidMappings {
sysUIDMaps = append(sysUIDMaps, syscall.SysProcIDMap{
ContainerID: int(m.ContainerID),
HostID: int(m.HostID),
ContainerID: int(m.Container),
HostID: int(m.Host),
Size: int(m.Size),
})
}
@@ -67,8 +92,8 @@ func createIDMappedUserNS(uidMappings, gidMappings []specs.LinuxIDMapping) (*os.
var sysGIDMaps []syscall.SysProcIDMap
for _, m := range gidMappings {
sysGIDMaps = append(sysGIDMaps, syscall.SysProcIDMap{
ContainerID: int(m.ContainerID),
HostID: int(m.HostID),
ContainerID: int(m.Container),
HostID: int(m.Host),
Size: int(m.Size),
})
}
@@ -120,7 +145,7 @@ func createIDMappedUserNS(uidMappings, gidMappings []specs.LinuxIDMapping) (*os.
}
func openIDMappedMount(req *OpenMountArgs) (*os.File, error) {
usernsFD, err := createIDMappedUserNS(req.Mount.UIDMappings, req.Mount.GIDMappings)
usernsFD, err := createIDMappedUserNS(req.UIDs, req.GIDs)
if err != nil {
return nil, err
}
@@ -131,13 +156,13 @@ func openIDMappedMount(req *OpenMountArgs) (*os.File, error) {
openTreeFlags |= unix.AT_RECURSIVE
}
fd, err := unix.OpenTree(unix.AT_FDCWD, req.Mount.Source, openTreeFlags)
fd, err := unix.OpenTree(unix.AT_FDCWD, req.Source, openTreeFlags)
if err != nil {
return nil, fmt.Errorf("open_tree(%q) failed: %w", req.Mount.Source, err)
return nil, fmt.Errorf("open_tree(%q) failed: %w", req.Source, err)
}
setattrFlags := uint(unix.AT_EMPTY_PATH)
if slices.Contains(req.Mount.Options, "ridmap") {
if slices.Contains(req.Options, "ridmap") {
setattrFlags |= unix.AT_RECURSIVE
}
@@ -148,10 +173,10 @@ func openIDMappedMount(req *OpenMountArgs) (*os.File, error) {
if err := unix.MountSetattr(fd, "", setattrFlags, attr); err != nil {
unix.Close(fd)
return nil, fmt.Errorf("mount_setattr(%q) failed: %w", req.Mount.Source, err)
return nil, fmt.Errorf("mount_setattr(%q) failed: %w", req.Source, err)
}
return os.NewFile(uintptr(fd), req.Mount.Source), nil
return os.NewFile(uintptr(fd), req.Source), nil
}
func (rpc *goferToHostRPC) handleRequest(req *openMountRequest) {
@@ -160,10 +185,10 @@ func (rpc *goferToHostRPC) handleRequest(req *openMountRequest) {
var fd *os.File
var err error
if specutils.IsIDMappedMount(*req.args.Mount) {
if req.args.mapped() {
fd, err = openIDMappedMount(req.args)
} else {
fd, err = os.OpenFile(req.args.Mount.Source, unix.O_PATH|unix.O_CLOEXEC, 0)
fd, err = os.OpenFile(req.args.Source, unix.O_PATH|unix.O_CLOEXEC, 0)
}
if err != nil {
req.done <- err
+2 -3
View File
@@ -16,6 +16,7 @@ package container
import (
"encoding/json"
"fmt"
"os"
"strings"
"testing"
@@ -37,9 +38,7 @@ import (
func remoteSinkConfig(endpoint string) seccheck.SinkConfig {
return seccheck.SinkConfig{
Name: "remote",
Config: map[string]any{
"endpoint": endpoint,
},
Config: json.RawMessage(fmt.Sprintf(`{"endpoint": %q}`, endpoint)),
}
}
+235
View File
@@ -0,0 +1,235 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package container
import (
"encoding/binary"
"fmt"
"strings"
zap "github.com/zap-proto/go"
)
// ---- Mapping -----------------------------------------------------------
const (
mappingContainerAt = 0
mappingHostAt = 4
mappingSizeAt = 8
mappingSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*Mapping)(nil)
// MarshalZAP writes Mapping from constant offsets.
func (x *Mapping) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(mappingSize + 256)
ob := b.StartObject(mappingSize)
ob.SetUint32(mappingContainerAt, uint32(x.Container))
ob.SetUint32(mappingHostAt, uint32(x.Host))
ob.SetUint32(mappingSizeAt, uint32(x.Size))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads Mapping out of the buffer that arrived.
func (x *Mapping) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("Mapping: %w", err)
}
o := m.Root()
x.Container = uint32(o.Uint32(mappingContainerAt))
x.Host = uint32(o.Uint32(mappingHostAt))
x.Size = uint32(o.Uint32(mappingSizeAt))
return nil
}
// ---- OpenMountArgs -----------------------------------------------------
const (
openMountArgsSourceAt = 0
openMountArgsOptionsAt = 8
openMountArgsUIDsAt = 16
openMountArgsGIDsAt = 24
openMountArgsFlagsAt = 32
openMountArgsSize = 40
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*OpenMountArgs)(nil)
// MarshalZAP writes OpenMountArgs from constant offsets.
func (x *OpenMountArgs) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(openMountArgsSize + 256)
optionsAt, optionsN := 0, len(x.Options)
if optionsN > 0 {
var blob []byte
for i := range x.Options {
enc := []byte(x.Options[i])
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
optionsAt = b.WriteBytes(blob)
}
uIDsAt, uIDsN := 0, len(x.UIDs)
if uIDsN > 0 {
var blob []byte
for i := range x.UIDs {
enc, err := x.UIDs[i].MarshalZAP()
if err != nil {
return nil, err
}
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
uIDsAt = b.WriteBytes(blob)
}
gIDsAt, gIDsN := 0, len(x.GIDs)
if gIDsN > 0 {
var blob []byte
for i := range x.GIDs {
enc, err := x.GIDs[i].MarshalZAP()
if err != nil {
return nil, err
}
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
gIDsAt = b.WriteBytes(blob)
}
ob := b.StartObject(openMountArgsSize)
ob.SetText(openMountArgsSourceAt, string(x.Source))
ob.SetUint32(openMountArgsFlagsAt, uint32(x.Flags))
if optionsN > 0 {
ob.SetList(openMountArgsOptionsAt, optionsAt, optionsN)
}
if uIDsN > 0 {
ob.SetList(openMountArgsUIDsAt, uIDsAt, uIDsN)
}
if gIDsN > 0 {
ob.SetList(openMountArgsGIDsAt, gIDsAt, gIDsN)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads OpenMountArgs out of the buffer that arrived.
func (x *OpenMountArgs) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("OpenMountArgs: %w", err)
}
o := m.Root()
x.Source = string(strings.Clone(o.Text(openMountArgsSourceAt)))
if l := o.List(openMountArgsOptionsAt); l.Len() > 0 {
rows := make([]string, l.Len())
for i := range rows {
rows[i] = string(l.BytesAt(i))
}
x.Options = rows
}
if l := o.List(openMountArgsUIDsAt); l.Len() > 0 {
rows := make([]Mapping, l.Len())
for i := range rows {
if err := rows[i].UnmarshalZAP(l.BytesAt(i)); err != nil {
return err
}
}
x.UIDs = rows
}
if l := o.List(openMountArgsGIDsAt); l.Len() > 0 {
rows := make([]Mapping, l.Len())
for i := range rows {
if err := rows[i].UnmarshalZAP(l.BytesAt(i)); err != nil {
return err
}
}
x.GIDs = rows
}
x.Flags = uint32(o.Uint32(openMountArgsFlagsAt))
return nil
}
// ---- OpenMountResult ---------------------------------------------------
const (
openMountResultFilePayloadAt = 0
openMountResultSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*OpenMountResult)(nil)
// MarshalZAP writes OpenMountResult from constant offsets.
func (x *OpenMountResult) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(openMountResultSize + 256)
ob := b.StartObject(openMountResultSize)
innerFilePayload, err := x.FilePayload.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(openMountResultFilePayloadAt, innerFilePayload)
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads OpenMountResult out of the buffer that arrived.
func (x *OpenMountResult) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("OpenMountResult: %w", err)
}
o := m.Root()
if raw := o.Bytes(openMountResultFilePayloadAt); len(raw) > 0 {
if err := x.FilePayload.UnmarshalZAP(raw); err != nil {
return err
}
}
return nil
}
+1
View File
@@ -63,6 +63,7 @@ go_library(
"@com_github_moby_sys_capability//:go_default_library",
"@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_vishvananda_netlink//:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
)
+4 -4
View File
@@ -562,7 +562,7 @@ func loopbackLink(conf *config.Config, iface net.Interface, addrs []net.Addr, di
dst := *ipNet
dst.IP = dst.IP.Mask(dst.Mask)
link.Routes = append(link.Routes, boot.Route{
Destination: dst,
Destination: boot.Subnet(dst),
})
}
@@ -608,7 +608,7 @@ func routesForIface(iface net.Interface, disableIPv6 bool) ([]boot.Route, *boot.
return nil, nil, nil, fmt.Errorf("more than one default route found %q, def: %+v, route: %+v", iface.Name, defv4, r)
}
defv4 = &boot.Route{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IPv4zero,
Mask: net.IPMask(net.IPv4zero),
},
@@ -622,7 +622,7 @@ func routesForIface(iface net.Interface, disableIPv6 bool) ([]boot.Route, *boot.
if !disableIPv6 {
defv6 = &boot.Route{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IPv6zero,
Mask: net.IPMask(net.IPv6zero),
},
@@ -642,7 +642,7 @@ func routesForIface(iface net.Interface, disableIPv6 bool) ([]boot.Route, *boot.
}
dst.IP = dst.IP.Mask(dst.Mask)
routes = append(routes, boot.Route{
Destination: dst,
Destination: boot.Subnet(dst),
Gateway: r.Gw,
MTU: mtu,
})
+16 -16
View File
@@ -290,13 +290,13 @@ func defaultLoopbackLinks() []boot.LoopbackLink {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{127, 0, 0, 0},
Mask: net.IPMask{255, 0, 0, 0},
},
},
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.ParseIP("::1"),
Mask: net.IPMask{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
@@ -334,13 +334,13 @@ func TestCollectLinksAndRoutes_SingleInterface(t *testing.T) {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{10, 0, 0, 0},
Mask: net.IPMask{255, 255, 255, 0},
},
},
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{192, 168, 1, 0},
Mask: net.IPMask{255, 255, 255, 0},
},
@@ -360,7 +360,7 @@ func TestCollectLinksAndRoutes_SingleInterface(t *testing.T) {
wantGW := boot.DefaultRoute{
Name: "testveth0",
Route: boot.Route{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IPv4zero,
Mask: net.IPMask(net.IPv4zero),
},
@@ -404,13 +404,13 @@ func TestCollectLinksAndRoutes_LoopbackOnly(t *testing.T) {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{127, 0, 0, 0},
Mask: net.IPMask{255, 0, 0, 0},
},
},
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.ParseIP("::1"),
Mask: net.IPMask{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
@@ -465,7 +465,7 @@ func TestCollectLinksAndRoutes_MultipleInterfaces(t *testing.T) {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{10, 0, 0, 0},
Mask: net.IPMask{255, 255, 255, 0},
},
@@ -482,7 +482,7 @@ func TestCollectLinksAndRoutes_MultipleInterfaces(t *testing.T) {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{192, 168, 1, 0},
Mask: net.IPMask{255, 255, 255, 0},
},
@@ -497,7 +497,7 @@ func TestCollectLinksAndRoutes_MultipleInterfaces(t *testing.T) {
wantGW := boot.DefaultRoute{
Name: "testveth0",
Route: boot.Route{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IPv4zero,
Mask: net.IPMask(net.IPv4zero),
},
@@ -550,7 +550,7 @@ func TestCollectLinksAndRoutes_IPv6Disabled(t *testing.T) {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{10, 0, 0, 0},
Mask: net.IPMask{255, 255, 255, 0},
},
@@ -575,7 +575,7 @@ func TestCollectLinksAndRoutes_IPv6Disabled(t *testing.T) {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{127, 0, 0, 0},
Mask: net.IPMask{255, 0, 0, 0},
},
@@ -682,19 +682,19 @@ func TestCollectLinksAndRoutes_LoopbackExtraRoutes(t *testing.T) {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{127, 0, 0, 0},
Mask: net.IPMask{255, 0, 0, 0},
},
},
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IPv6loopback,
Mask: net.CIDRMask(128, 128),
},
},
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{10, 88, 0, 0},
Mask: net.IPMask{255, 255, 0, 0},
},
@@ -718,7 +718,7 @@ func TestCollectLinksAndRoutes_LoopbackExtraRoutes(t *testing.T) {
},
Routes: []boot.Route{
{
Destination: net.IPNet{
Destination: boot.Subnet{
IP: net.IP{10, 0, 0, 0},
Mask: net.IPMask{255, 255, 255, 0},
},
+19 -4
View File
@@ -70,6 +70,8 @@ import (
"gvisor.dev/gvisor/runsc/starttime"
metricpb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
"google.golang.org/protobuf/proto"
)
const (
@@ -409,7 +411,10 @@ func New(conf *config.Config, args *Args) (*Sandbox, error) {
if err := s.call(boot.MetricsGetRegistered, nil, &registeredMetrics); err != nil {
return nil, fmt.Errorf("cannot get registered metrics: %v", err)
}
s.RegisteredMetrics = registeredMetrics.RegisteredMetrics
s.RegisteredMetrics = &metricpb.MetricRegistration{}
if err := proto.Unmarshal(registeredMetrics.Registration, s.RegisteredMetrics); err != nil {
return nil, fmt.Errorf("cannot read registered metrics: %w", err)
}
}
c.Release()
@@ -522,9 +527,14 @@ func (s *Sandbox) StartSubcontainer(spec *specs.Spec, conf *config.Config, cid s
}
payload.Files = append(payload.Files, goferFiles...)
doc, err := json.Marshal(spec)
if err != nil {
return fmt.Errorf("writing spec: %w", err)
}
// Start running the container.
args := boot.StartArgs{
Spec: spec,
Spec: doc,
Conf: conf,
CID: cid,
NumGoferFilestoreFDs: len(goferFilestores),
@@ -671,9 +681,14 @@ func (s *Sandbox) RestoreSubcontainer(spec *specs.Spec, conf *config.Config, cid
}
payload.Files = append(payload.Files, goferFiles...)
doc, err := json.Marshal(spec)
if err != nil {
return fmt.Errorf("writing spec: %w", err)
}
// Start running the container.
args := boot.StartArgs{
Spec: spec,
Spec: doc,
Conf: conf,
CID: cid,
NumGoferFilestoreFDs: len(goferFilestoreFiles),
@@ -1673,7 +1688,7 @@ func (s *Sandbox) Checkpoint(conf *config.Config, cid string, imagePath string,
log.Debugf("Checkpoint sandbox %q, imagePath %q, opts %+v", s.ID, imagePath, opts)
opt := control.SaveOpts{
Metadata: opts.Compression.ToMetadata(),
Metadata: control.Pairs(opts.Compression.ToMetadata()),
AppMFExcludeCommittedZeroPages: opts.ExcludeCommittedZeroPages,
Resume: opts.Resume,
CudaCheckpointPath: opts.CudaCheckpointPath,
+3 -1
View File
@@ -17,6 +17,7 @@ go_library(
"rdma.go",
"restore.go",
"specutils.go",
"zap.go",
],
visibility = ["//:sandbox"],
deps = [
@@ -32,8 +33,9 @@ go_library(
"@com_github_cenkalti_backoff//:go_default_library",
"@com_github_moby_sys_capability//:go_default_library",
"@com_github_mohae_deepcopy//:go_default_library",
"@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_opencontainers_runtime_spec//specs-go/features:go_default_library",
"@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_zap_proto_go//:go",
"@org_golang_x_sys//unix:go_default_library",
],
)
+68
View File
@@ -0,0 +1,68 @@
// Copyright 2026 The gVisor 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.
// Code generated by zip; DO NOT EDIT.
package specutils
import (
"fmt"
"strings"
zap "github.com/zap-proto/go"
)
// ---- GoferMountConf ----------------------------------------------------
const (
goferMountConfLowerAt = 0
goferMountConfUpperAt = 1
goferMountConfSizeAt = 8
goferMountConfSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GoferMountConf)(nil)
// MarshalZAP writes GoferMountConf from constant offsets.
func (x *GoferMountConf) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(goferMountConfSize + 256)
ob := b.StartObject(goferMountConfSize)
ob.SetUint8(goferMountConfLowerAt, uint8(x.Lower))
ob.SetUint8(goferMountConfUpperAt, uint8(x.Upper))
ob.SetText(goferMountConfSizeAt, string(x.Size))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GoferMountConf out of the buffer that arrived.
func (x *GoferMountConf) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GoferMountConf: %w", err)
}
o := m.Root()
x.Lower = GoferMountConfLowerType(o.Uint8(goferMountConfLowerAt))
x.Upper = GoferMountConfUpperType(o.Uint8(goferMountConfUpperAt))
x.Size = string(strings.Clone(o.Text(goferMountConfSizeAt)))
return nil
}
+19
View File
@@ -0,0 +1,19 @@
load("//tools:defs.bzl", "go_binary")
package(default_applicable_licenses = ["//:license"])
licenses(["notice"])
go_binary(
name = "zap",
srcs = ["zap.go"],
visibility = ["//:sandbox"],
deps = [
"//pkg/sentry/control",
"//pkg/sentry/state/stateipc",
"//pkg/urpc",
"//runsc/boot",
"//runsc/container",
"@com_github_zap_proto_zip//:zip",
],
)
+224
View File
@@ -0,0 +1,224 @@
// Copyright 2026 The gVisor 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.
// Command zap states the ZAP wire of every urpc payload, reading it from the
// type and writing it as Go source with the offsets as constants. Nothing
// reflects when a call is served.
//
// Run it after changing a payload:
//
// make zap
//
// A payload it cannot state is named on stderr and left alone. Answering that
// is a change to the type: a map, an interface or a fixed array of anything but
// bytes has no offset, so there is no layout to write down.
//
// The layouts live in the packages that declare the payloads, so a type change
// can leave a layout that no longer compiles — which is the point, since a
// stale offset is silent corruption. `make zap` empties each layout before
// regenerating it, so the package the generator reflects over is the package
// the types are in today.
package main
import (
"fmt"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"github.com/zap-proto/zip"
"gvisor.dev/gvisor/pkg/sentry/control"
"gvisor.dev/gvisor/pkg/sentry/state/stateipc"
"gvisor.dev/gvisor/pkg/urpc"
"gvisor.dev/gvisor/runsc/boot"
"gvisor.dev/gvisor/runsc/container"
)
// module is the import path this repository serves. A layout outside it names a
// package we cannot write to, which is a refusal and not an output.
const module = "gvisor.dev/gvisor/"
// roots are the arguments and results of every method urpc serves. Everything
// they reach is stated with them, so only the top of each call appears here.
//
// A payload missing from this list states no wire, and the call that carries it
// fails naming the type. Adding a method means adding its two payloads.
var roots = []reflect.Type{
// pkg/urpc: the envelope itself.
reflect.TypeFor[urpc.FilePayload](),
// pkg/sentry/control.
reflect.TypeFor[control.CatOpts](),
reflect.TypeFor[control.CgroupsReadArgs](),
reflect.TypeFor[control.CgroupsResults](),
reflect.TypeFor[control.CgroupsWriteArgs](),
reflect.TypeFor[control.ContainerArgs](),
reflect.TypeFor[control.EventsOpts](),
reflect.TypeFor[control.ExecArgs](),
reflect.TypeFor[control.GetRegisteredMetricsOpts](),
reflect.TypeFor[control.LoggingArgs](),
reflect.TypeFor[control.MemoryUsage](),
reflect.TypeFor[control.MemoryUsageFile](),
reflect.TypeFor[control.MemoryUsageFileOpts](),
reflect.TypeFor[control.MemoryUsageOpts](),
reflect.TypeFor[control.MetricsExportData](),
reflect.TypeFor[control.MetricsExportOpts](),
reflect.TypeFor[control.MetricsRegistrationResponse](),
reflect.TypeFor[control.MountOpts](),
reflect.TypeFor[control.Process](),
reflect.TypeFor[control.PsArgs](),
reflect.TypeFor[control.ReadOpts](),
reflect.TypeFor[control.SaveOpts](),
reflect.TypeFor[control.SaveRestoreExecOpts](),
reflect.TypeFor[control.SignalContainerArgs](),
reflect.TypeFor[control.SignalProcessArgs](),
reflect.TypeFor[control.StartContainerArgs](),
reflect.TypeFor[control.TarRootfsUpperLayerOpts](),
reflect.TypeFor[control.UmountOpts](),
reflect.TypeFor[control.UsageReduceOpts](),
reflect.TypeFor[control.UsageReduceOutput](),
// pkg/sentry/control, the profile options.
reflect.TypeFor[control.BlockProfileOpts](),
reflect.TypeFor[control.CPUProfileOpts](),
reflect.TypeFor[control.GoroutineProfileOpts](),
reflect.TypeFor[control.HeapProfileOpts](),
reflect.TypeFor[control.MutexProfileOpts](),
reflect.TypeFor[control.TraceProfileOpts](),
// pkg/sentry/state/stateipc.
reflect.TypeFor[stateipc.CloseRequest](),
reflect.TypeFor[stateipc.CloseResponse](),
reflect.TypeFor[stateipc.OpenRequest](),
reflect.TypeFor[stateipc.OpenResponse](),
reflect.TypeFor[stateipc.RegisterClientFileRequest](),
reflect.TypeFor[stateipc.RegisterClientFileResponse](),
// runsc/boot.
reflect.TypeFor[boot.CreateArgs](),
reflect.TypeFor[boot.CreateLinksAndRoutesArgs](),
reflect.TypeFor[boot.CreateTraceSessionArgs](),
reflect.TypeFor[boot.FSSaveArgs](),
reflect.TypeFor[boot.InitPluginStackArgs](),
reflect.TypeFor[boot.MountArgs](),
reflect.TypeFor[boot.PortForwardOpts](),
reflect.TypeFor[boot.Savings](),
reflect.TypeFor[boot.SignalArgs](),
reflect.TypeFor[boot.StartArgs](),
reflect.TypeFor[boot.WaitFSRestoreArgs](),
reflect.TypeFor[boot.WaitPIDArgs](),
// runsc/container.
reflect.TypeFor[container.OpenMountArgs](),
reflect.TypeFor[container.OpenMountResult](),
}
func main() {
dir := os.Getenv("BUILD_WORKSPACE_DIRECTORY")
if dir == "" {
fmt.Fprintln(os.Stderr, "zap: run me with bazel run //tools/zap")
os.Exit(1)
}
// One root at a time, so a refusal names the payload that carries it
// instead of stopping the run at the first one.
var take []reflect.Type
var refused []string
for _, r := range roots {
if _, err := zip.Layouts(r); err != nil {
refused = append(refused, fmt.Sprintf("%s.%s: %s", short(r.PkgPath()), r.Name(), trim(err)))
continue
}
take = append(take, r)
}
layouts, err := zip.Layouts(take...)
if err != nil {
fmt.Fprintln(os.Stderr, "zap:", err)
os.Exit(1)
}
var wrote, outside []string
for _, l := range layouts {
rel, ok := strings.CutPrefix(l.Path, module)
if !ok {
outside = append(outside, fmt.Sprintf("%s: another module owns it (%s)", l.Path, strings.Join(l.Types, ", ")))
continue
}
if _, err := os.Stat(filepath.Join(dir, rel)); err != nil {
outside = append(outside, fmt.Sprintf("%s: no source here, bazel writes it (%s)", rel, strings.Join(l.Types, ", ")))
continue
}
path := filepath.Join(dir, rel, "zap.go")
if err := os.WriteFile(path, append([]byte(license), l.Source...), 0644); err != nil {
fmt.Fprintln(os.Stderr, "zap:", err)
os.Exit(1)
}
wrote = append(wrote, fmt.Sprintf("%s (%d types)", rel, len(l.Types)))
}
sort.Strings(wrote)
for _, w := range wrote {
fmt.Println("wrote", w)
}
if len(outside) > 0 {
sort.Strings(outside)
fmt.Fprintln(os.Stderr, "\nreached, but not ours to write:")
for _, o := range outside {
fmt.Fprintln(os.Stderr, " ", o)
}
}
if len(refused) > 0 {
sort.Strings(refused)
fmt.Fprintln(os.Stderr, "\nno layout:")
for _, r := range refused {
fmt.Fprintln(os.Stderr, " ", r)
}
os.Exit(1)
}
}
// short drops the module prefix from an import path so a verdict reads as the
// package a reader would open.
func short(path string) string {
if rel, ok := strings.CutPrefix(path, module); ok {
return rel
}
return path
}
// trim drops the emitter's own prefix from a refusal: the reader already knows
// which generator is speaking.
func trim(err error) string {
return strings.TrimPrefix(err.Error(), "zip: ")
}
const license = `// Copyright 2026 The gVisor 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.
`