sandbox

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package sandbox is the harness's per-session confinement capability, host tier: it owns the session cgroups under the harness's delegated cgroup subtree and writes the policy the Rust launcher enforces.

The harness runs each session's turn executor behind the launcher (Session.LaunchPrefix), which joins the session's cgroup, applies the Landlock and seccomp policy and execs the executor. This package creates that cgroup and writes that policy; it kills the whole subtree on cancel (Session.Kill) and reads the cpu and memory receipts (Session.Usage) before removing it (Session.Remove).

It reaches the cgroup filesystem through os file APIs, which is why it lives under ipc/ (CS-16). The cgroup root and the self-cgroup path are injectable so a spec drives the whole capability over a temporary directory.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotDelegated reports a harness that cannot create session cgroups,
	// naming the operator's fix.
	ErrNotDelegated = errors.New("sandbox: the harness is not in a delegated cgroup; the operator must restart it with " +
		"`systemd-run --user --scope -p Delegate=yes --unit csf-harness csf serve <its flags>`")
	// ErrNoLauncher reports a manager built without the launcher binary.
	ErrNoLauncher = errors.New("sandbox: a launcher binary path is required")
	// ErrNotPrepared reports Open before Prepare established the sessions cgroup.
	ErrNotPrepared = errors.New("sandbox: Prepare must establish the sessions cgroup before a session opens")
)

Functions

This section is empty.

Types

type Capacity

type Capacity struct {
	// Cores is the number of logical CPUs.
	Cores int
	// MemoryBytes is the host's total memory.
	MemoryBytes uint64
}

Capacity is the host capacity a session's bounds are derived from.

type Limits

type Limits struct {
	CPUMax             string `json:"cpu_max"`
	MemoryMaxBytes     uint64 `json:"memory_max_bytes"`
	MemorySwapMaxBytes uint64 `json:"memory_swap_max_bytes"`
	PidsMax            uint64 `json:"pids_max"`
	Derivation         string `json:"derivation"`
}

Limits are the cgroup v2 bounds written into a session's cgroup. The JSON shape matches the launcher's policy exactly, so the Rust launcher reads what this writes.

func DeriveLimits

func DeriveLimits(capacity Capacity) Limits

DeriveLimits computes a session's bounds from host capacity and records, in Derivation, exactly how each was chosen, so a receipt carries the basis for every limit. There is no per-session cgroup peak history before this slice, so the bounds are a conservative share of host capacity; the cpu and memory receipts this slice records are what later tightens them.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager owns the session cgroups and writes launcher policies. It is the harness's sandbox capability, granted the launcher and proxy binaries and the host capacity the per-session limits derive from.

func NewManager

func NewManager(launcher string, options ...ManagerOption) (*Manager, error)

NewManager builds the sandbox capability. The launcher path is required; the capacity defaults to the host's when not set.

func (*Manager) Open

func (manager *Manager) Open(params SessionParams) (*Session, error)

Open creates the session's cgroup and writes its launcher policy, returning the handle that builds the launch prefix and later cancels and measures it.

func (*Manager) Prepare

func (manager *Manager) Prepare() error

Prepare establishes the sessions cgroup under the harness's own delegated cgroup: it moves the harness into a supervisor leaf, enables the controllers on its subtree, and creates the sessions subtree the per-session cgroups live under. It reports ErrNotDelegated when the harness's cgroup does not offer the controllers, which is the case until the operator restarts it delegated.

type ManagerOption

type ManagerOption func(manager *Manager) error

ManagerOption configures a Manager.

func WithAllowedImages

func WithAllowedImages(images ...string) ManagerOption

WithAllowedImages lists the image references a session's containers may run: the digests the repository pins.

func WithCapacity

func WithCapacity(capacity Capacity) ManagerOption

WithCapacity sets the host capacity the per-session limits derive from, instead of reading it from the host.

func WithCgroupRoot

func WithCgroupRoot(root string) ManagerOption

WithCgroupRoot and WithProcSelfCgroup are test seams: they point the manager at a directory and file standing in for the cgroup filesystem.

func WithProcSelfCgroup

func WithProcSelfCgroup(path string) ManagerOption

func WithProxy

func WithProxy(path string) ManagerOption

WithProxy grants the Docker proxy binary a session points DOCKER_HOST at.

func WithReadOnlyRoots

func WithReadOnlyRoots(roots ...string) ManagerOption

WithReadOnlyRoots lists the system and toolchain paths a session may read and execute but not write.

func WithSessionsRoot

func WithSessionsRoot(path string) ManagerOption

WithSessionsRoot sets the cgroup directory per-session cgroups are created under directly, instead of letting Manager.Prepare establish it. It is for a caller that already owns a prepared sessions cgroup, and for specs that drive Open over a temporary directory.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session is one session's sandbox: its cgroup, its policy and the commands and receipts around it.

func (*Session) Cgroup

func (session *Session) Cgroup() string

Cgroup is the session's cgroup directory.

func (*Session) DockerProxyCommand

func (session *Session) DockerProxyCommand(upstream string) []string

DockerProxyCommand is the per-session Docker proxy invocation: the socket the session's DOCKER_HOST points at, the real Engine socket, the session label, the pinned images and the paths binds may target.

func (*Session) Kill

func (session *Session) Kill() error

Kill sends SIGKILL to every process in the session's cgroup with one write to cgroup.kill. A cgroup already gone is treated as killed.

func (*Session) LaunchPrefix

func (session *Session) LaunchPrefix() []string

LaunchPrefix is the argv prefix the harness puts in front of the turn executor: the launcher, the policy and the `--` that ends the launcher's own arguments.

func (*Session) Remove

func (session *Session) Remove() error

Remove deletes the session's cgroup. It must be empty of processes, so Kill precedes it and the executor is reaped between them.

func (*Session) Usage

func (session *Session) Usage() (Usage, error)

Usage reads the session's cpu and memory receipt. Call it after the executor has exited and before Session.Remove.

type SessionParams

type SessionParams struct {
	// ID is the assignment identifier; it names the cgroup and labels the
	// session's containers.
	ID string
	// PolicyPath is where the launcher's policy JSON is written, under the run
	// directory.
	PolicyPath string
	// ReadWrite are the paths the session may write: its worktree, run
	// directory and caches. They are also the paths a bind mount's source may
	// lie within.
	ReadWrite []string
	// PrivateTmp, when set, is a per-session writable tmp this capability
	// creates and adds to the writable set, so the executor's TMPDIR need not
	// expose the host's.
	PrivateTmp string
	// ReadOnly are extra read-only paths beyond the manager's system roots.
	ReadOnly []string
	// ProxySocket is the Docker proxy socket for this session; empty grants no
	// container access.
	ProxySocket string
}

SessionParams is one session's confinement request.

type SessionPolicy

type SessionPolicy struct {
	SessionID         string   `json:"session_id"`
	Cgroup            string   `json:"cgroup"`
	Limits            Limits   `json:"limits"`
	ReadWritePaths    []string `json:"read_write_paths"`
	ReadOnlyPaths     []string `json:"read_only_paths"`
	DockerProxySocket string   `json:"docker_proxy_socket,omitempty"`
}

SessionPolicy is the launcher's policy for one session. Its JSON field names match the Rust launcher's SessionPolicy exactly.

type Usage

type Usage struct {
	// CPU is the total on-CPU time, from cpu.stat's usage_usec.
	CPU time.Duration
	// MemoryPeakBytes is the high-water mark, from memory.peak.
	MemoryPeakBytes uint64
}

Usage is what a session's cgroup spent, read for its receipt before the cgroup is removed.

func ParseUsage

func ParseUsage(cpuStat []byte, memoryPeak []byte) (Usage, error)

ParseUsage reads a receipt from the contents of cpu.stat and memory.peak.

func ProcessCgroupUsage

func ProcessCgroupUsage(pid int) (Usage, error)

ProcessCgroupUsage reads the receipt of the cgroup process pid runs in, as /proc/<pid>/cgroup names it under the host's cgroup root: a container's cgroup, read through its init process.

func ReadCgroupUsage

func ReadCgroupUsage(cgroup string) (Usage, error)

ReadCgroupUsage reads the cpu and memory receipt of the cgroup directory cgroup.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL