Files
visor/runsc/container/zap.go
T
zeekayandHanzo Dev 3da05638df 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]>
2026-09-22 23:10:33 -07:00

236 lines
5.8 KiB
Go

// 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
}