sandbox

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package sandbox runs a real binary inside a given rootfs using Linux namespaces + pivot_root, implemented directly on golang.org/x/sys/unix (no libcontainer / runc dependency).

Topology recap: the agent itself lives in the control-root and is NOT affected by rollback. Each command the agent runs becomes a child here, with the inner-env subvolume as its root. The child is PID 1 of a fresh PID namespace, so killing it (see repo.killAll on checkout) tears down the whole inner-env process tree.

Networking: we deliberately do NOT create a new network namespace, so the child shares the host network and `apt install` can reach the internet. The host's /etc/resolv.conf is bind-mounted in for DNS.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Child

func Child()

Child is the entry point for the re-executed process. It sets up the inner-env root and execs the target command. It never returns on success.

func IsChild

func IsChild() bool

IsChild reports whether the current process was re-executed as the namespaced child (i.e. os.Args == [exe, "__child", rootfs, cmd...]).

func Run

func Run(rootfs string, args, env []string, stdin io.Reader, stdout, stderr io.Writer) error

Run executes args inside rootfs and blocks until it exits (foreground).

func RunPTY

func RunPTY(rootfs string, args, env []string, rootless bool) (int, error)

RunPTY runs an interactive command inside rootfs on a pseudo-terminal that's wired to the caller's terminal (raw mode + window-size propagation). rootless adds a user namespace so a non-root caller can do it. Returns the exit code.

When stdin is not a terminal (e.g. piped), the call falls back to a plain non-PTY run with the same plumbing — the caller still gets stdout/stderr.

Previously this file hand-rolled /dev/ptmx / TIOCSPTLCK / TIOCGPTN / /dev/pts path-joining / termios raw-mode bit flips / SIGWINCH plumbing — about 130 lines of brittle ioctl wrangling. creack/pty + golang.org/x/term shrink it to ~30 well-tested lines (pure-Go, no cgo, no extra runtime dependencies).

func RunPTYHook added in v0.2.0

func RunPTYHook(rootfs string, args, env []string, rootless bool, onStart func(*exec.Cmd)) (int, error)

RunPTYHook is RunPTY plus an onStart callback invoked with the child process handle right after it starts (PTY path only). A supervisor uses it to register the interactive agent so a rollback (checkout) can kill it — when the process dies, this call returns and the supervisor restarts it from the restored environment.

func RunRootless

func RunRootless(rootfs string, args, env []string, stdin io.Reader, stdout, stderr io.Writer) error

RunRootless is like Run but creates a new USER namespace too, mapping container root (uid/gid 0) to the caller's real uid/gid. This lets an unprivileged, non-root process (e.g. a restricted K8s pod running as uid 1001) gain namespaced CAP_SYS_ADMIN and thus do mount/pivot_root — without any host privilege.

func Start

func Start(rootfs string, args, env []string, out io.Writer) (*exec.Cmd, error)

Start launches args inside rootfs detached and returns immediately. The caller owns the returned *exec.Cmd: it must Wait() on it (to reap) and may Kill() it. Killing the process kills the whole inner-env PID namespace it leads.

func StartRootless

func StartRootless(rootfs string, args, env []string, out io.Writer) (*exec.Cmd, error)

StartRootless is the rootless (user-namespace) variant of Start.

Types

This section is empty.

Jump to

Keyboard shortcuts

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