Skip to main content

Sandbox

Struct Sandbox 

Source
pub struct Sandbox {
Show 45 fields pub fs_writable: Vec<PathBuf>, pub fs_readable: Vec<PathBuf>, pub fs_denied: Vec<PathBuf>, pub extra_deny_syscalls: Vec<String>, pub extra_allow_syscalls: Vec<String>, pub protection_policy: ProtectionPolicy, pub net_allow: Vec<NetAllow>, pub net_deny: Vec<NetDeny>, pub net_allow_bind: Vec<u16>, pub net_deny_bind: Vec<u16>, pub http_allow: Vec<HttpRule>, pub http_deny: Vec<HttpRule>, pub http_ports: Vec<u16>, pub http_ca: Option<PathBuf>, pub http_key: Option<PathBuf>, pub http_inject_ca: Vec<PathBuf>, pub http_ca_out: Option<PathBuf>, pub max_memory: Option<ByteSize>, pub max_processes: u32, pub max_open_files: Option<u32>, pub max_cpu: Option<u8>, pub random_seed: Option<u64>, pub time_start: Option<SystemTime>, pub no_randomize_memory: bool, pub no_huge_pages: bool, pub no_coredump: bool, pub deterministic_dirs: bool, pub workdir: Option<PathBuf>, pub cwd: Option<PathBuf>, pub fs_storage: Option<PathBuf>, pub max_disk: Option<ByteSize>, pub on_exit: BranchAction, pub on_error: BranchAction, pub fs_mount: Vec<(PathBuf, PathBuf)>, pub chroot: Option<PathBuf>, pub clean_env: bool, pub env: HashMap<String, String>, pub gpu_devices: Option<Vec<u32>>, pub cpu_cores: Option<Vec<u32>>, pub num_cpus: Option<u32>, pub port_remap: bool, pub no_supervisor: bool, pub uid: Option<u32>, pub policy_fn: Option<PolicyCallback>, pub name: Option<String>, /* private fields */
}
Expand description

Sandbox configuration.

Fields§

§fs_writable: Vec<PathBuf>§fs_readable: Vec<PathBuf>§fs_denied: Vec<PathBuf>§extra_deny_syscalls: Vec<String>§extra_allow_syscalls: Vec<String>§protection_policy: ProtectionPolicy

Per-protection enforcement policy. Default (ProtectionPolicy::strict_all()) preserves the historical hard MIN_ABI = 6 behaviour; SandboxBuilder::allow_degraded / ::disable deviate from strict-all per protection.

Part of the checkpoint: a saved sandbox restores with its exact protection posture. Without this, a sandbox built with a disable() opt-out (required on, e.g., a v5 host that cannot provide a v6 scope) would silently reset to strict_all() on load and fail to restore.

§net_allow: Vec<NetAllow>

Outbound endpoint allowlist as a list of (protocol, host?, ports) rules. Each rule names a protocol (TCP/UDP/ICMP) and either a concrete host or “any IP.” TCP and UDP rules carry ports; ICMP rules have none.

Protocol gating falls out of rule presence. Sandlock denies UDP and ICMP socket creation by default; opting in is “list at least one rule for that protocol” (e.g. udp://*:* for any UDP, icmp://* for any ICMP echo). TCP is always permitted.

Empty net_allow and empty http_allow/http_deny together mean “deny all outbound” (Landlock direct path denies, no on-behalf path is enabled). Otherwise, the on-behalf path enforces these rules: a destination is permitted iff any rule matches the protocol, destination IP (or has host: None = any IP), and destination port (N/A for ICMP).

HTTP rules with concrete hosts auto-add a matching (Tcp, host, [80]) (and (Tcp, host, [443]) when --http-ca is set) entry at build time so the proxy’s intercept ports remain reachable. HTTP rules with wildcard hosts auto-add (Tcp, None, [80]) instead.

§net_deny: Vec<NetDeny>

Parsed --net-deny rules (default-allow, IP/CIDR/port denylist). Mutually exclusive with net_allow.

§net_allow_bind: Vec<u16>

--net-allow-bind: TCP ports the sandbox may bind (default-deny allowlist, Landlock-enforced). Mutually exclusive with net_deny_bind.

§net_deny_bind: Vec<u16>

--net-deny-bind: TCP ports the sandbox may NOT bind (default-allow denylist, enforced on the on-behalf bind() path). Mutually exclusive with net_allow_bind.

§http_allow: Vec<HttpRule>§http_deny: Vec<HttpRule>§http_ports: Vec<u16>

TCP ports to intercept for HTTP ACL. Defaults to [80] (plus 443 when http_ca is set). Override with http_ports to intercept custom ports.

§http_ca: Option<PathBuf>

PEM CA cert for HTTPS MITM. When set, port 443 is also intercepted.

§http_key: Option<PathBuf>

PEM CA key for HTTPS MITM. Required when http_ca is set.

§http_inject_ca: Vec<PathBuf>

Trust-bundle paths to splice the MITM CA into (zero-config HTTPS).

§http_ca_out: Option<PathBuf>

Path to write the active MITM CA public cert (PEM) for external trust wiring (e.g. NODE_EXTRA_CA_CERTS). Never writes the private key.

§max_memory: Option<ByteSize>§max_processes: u32§max_open_files: Option<u32>§max_cpu: Option<u8>§random_seed: Option<u64>§time_start: Option<SystemTime>§no_randomize_memory: bool§no_huge_pages: bool§no_coredump: bool§deterministic_dirs: bool§workdir: Option<PathBuf>§cwd: Option<PathBuf>§fs_storage: Option<PathBuf>§max_disk: Option<ByteSize>§on_exit: BranchAction§on_error: BranchAction§fs_mount: Vec<(PathBuf, PathBuf)>§chroot: Option<PathBuf>§clean_env: bool§env: HashMap<String, String>§gpu_devices: Option<Vec<u32>>§cpu_cores: Option<Vec<u32>>§num_cpus: Option<u32>§port_remap: bool§no_supervisor: bool

Skip the seccomp user-notification supervisor. The sandbox runs with Landlock + a kernel-only deny filter, with none of the supervisor-mediated features (IP allowlist, resource limits, COW, chroot mediation, /proc virtualization, custom handlers). Required when nesting inside another sandlock — the kernel only allows one SECCOMP_FILTER_FLAG_NEW_LISTENER per task.

§uid: Option<u32>§policy_fn: Option<PolicyCallback>§name: Option<String>

Implementations§

Source§

impl Sandbox

Source

pub fn builder() -> SandboxBuilder

Source

pub fn allows_sysv_ipc(&self) -> bool

Returns true iff the policy grants the sysv_ipc syscall group.

Source

pub fn validate(&self) -> Result<(), SandboxError>

Validate cross-section invariants — checks that span multiple fields.

Currently a no-op; retained as an extension point and for API stability. Idempotent: calling repeatedly is safe.

Source

pub fn active_protections( &self, ) -> Result<Vec<(Protection, ProtectionStatus)>, SandlockError>

Resolve the per-protection state against the host’s current Landlock ABI. Returns one entry per Protection. Useful for post-build() posture inspection.

Source

pub fn set_name(&mut self, name: impl Into<String>)

Set the sandbox instance name (also exposed as the virtual hostname). Auto-generated if not set.

Source

pub fn with_name(self, name: impl Into<String>) -> Self

Set the sandbox instance name and return self. Convenience for pipeline fan-out where a base config is cloned and each clone gets a fresh name:

let template = Sandbox::builder()...build()?;
let mut s1 = template.clone().with_name("worker-1");
let mut s2 = template.clone().with_name("worker-2");
Source

pub fn with_init_fn(self, f: impl FnOnce() + Send + 'static) -> Self

Set the COW-fork init function and return self.

The init function runs once in the child process before any COW clones are created. Use it to load expensive shared state.

Source

pub fn with_work_fn(self, f: impl Fn(u32) + Send + Sync + 'static) -> Self

Set the COW-fork work function and return self.

The work function runs in each COW clone (fork(N) produces N clones).

Source

pub fn instance_name(&self) -> Option<&str>

Return the sandbox name if set, or None if not yet started.

Source

pub fn pid(&self) -> Option<i32>

Return the child PID if spawned.

Source

pub fn is_running(&self) -> bool

Return whether the child is currently running or paused.

Source

pub fn pause(&mut self) -> Result<(), SandlockError>

Send SIGSTOP to the child’s process group.

Source

pub fn resume(&mut self) -> Result<(), SandlockError>

Send SIGCONT to the child’s process group.

Source

pub fn kill(&mut self) -> Result<(), SandlockError>

Send SIGKILL to the child’s process group.

Source

pub fn set_on_bind( &mut self, cb: impl Fn(&HashMap<u16, u16>) + Send + Sync + 'static, )

Set a callback invoked whenever a port bind is recorded.

Source

pub async fn port_mappings(&self) -> HashMap<u16, u16>

Return the current virtual-to-real port mappings.

Source

pub async fn wait(&mut self) -> Result<RunResult, SandlockError>

Wait for the child process to exit.

Source

pub async fn create(&mut self, cmd: &[&str]) -> Result<(), SandlockError>

Fork the sandboxed child and install policy (seccomp + notif supervisor + rlimits + landlock + COW + network/HTTP proxies). The child is parked between policy install and execve; call start() to release it. Stdout/stderr are captured for later retrieval via wait().

Source

pub async fn create_interactive( &mut self, cmd: &[&str], ) -> Result<(), SandlockError>

Like create but inherits stdio (no capture).

Source

pub fn start(&mut self) -> Result<(), SandlockError>

Release a previously create()d child to execve the configured command. Returns immediately; use wait() to collect the exit status when the child finishes.

Source

pub async fn spawn(&mut self, cmd: &[&str]) -> Result<(), SandlockError>

Sugar for create() + start() that also blocks until the child has completed execve() and is executing user code. After this returns, operations that read user-code state (e.g. checkpoint(), /proc/<pid>/exe) observe the requested binary rather than the supervisor.

Source

pub async fn spawn_interactive( &mut self, cmd: &[&str], ) -> Result<(), SandlockError>

Like spawn but inherits stdio (no capture).

Source

pub async fn checkpoint(&self) -> Result<Checkpoint, SandlockError>

Capture a checkpoint of the running sandbox.

Source

pub async fn run(&mut self, cmd: &[&str]) -> Result<RunResult, SandlockError>

One-shot: spawn, wait, and return the result. Stdout and stderr are captured. This is the primary way to run a sandboxed command:

let mut sandbox = Sandbox::builder()
    .fs_read("/usr")
    .name("my-sandbox")
    .build()?;
let result = sandbox.run(&["echo", "hello"]).await?;
Source

pub async fn run_interactive( &mut self, cmd: &[&str], ) -> Result<RunResult, SandlockError>

Run with inherited stdio (interactive mode).

Source

pub async fn run_with_handlers<I, S, H>( &mut self, cmd: &[&str], handlers: I, ) -> Result<RunResult, SandlockError>
where I: IntoIterator<Item = (S, H)>, S: TryInto<Syscall, Error = SyscallError>, H: Handler,

One-shot run with user-supplied syscall handlers.

Source

pub async fn run_interactive_with_handlers<I, S, H>( &mut self, cmd: &[&str], handlers: I, ) -> Result<RunResult, SandlockError>
where I: IntoIterator<Item = (S, H)>, S: TryInto<Syscall, Error = SyscallError>, H: Handler,

Interactive-stdio counterpart of run_with_handlers.

Source

pub async fn dry_run( &mut self, cmd: &[&str], ) -> Result<DryRunResult, SandlockError>

Dry-run: create, start, wait, collect filesystem changes, then abort.

Source

pub async fn dry_run_interactive( &mut self, cmd: &[&str], ) -> Result<DryRunResult, SandlockError>

Dry-run with inherited stdio.

Source

pub async fn fork(&mut self, n: u32) -> Result<Vec<Sandbox>, SandlockError>

Create N COW clones of this sandbox.

fork() requires init_fn and work_fn to be set on the sandbox (via SandboxBuilder::init_fn / work_fn, or Sandbox::with_init_fn / with_work_fn). Returns an error if either is missing.

Source

pub async fn reduce( &self, cmd: &[&str], clones: &mut [Sandbox], ) -> Result<RunResult, SandlockError>

Reduce: wait for all clones, then run a reducer command.

Trait Implementations§

Source§

impl Clone for Sandbox

Source§

fn clone(&self) -> Self

Clone a Sandbox — config and runtime-kwargs fields are cloned; the runtime state is not (the clone starts with runtime: None).

Field clone semantics:

  • policy_fn — Arc bump (cheap).
  • work_fn — Arc bump (cheap); multiple Sandboxes share the closure.
  • init_fndropped to None (FnOnce can’t be cloned). If the clone also needs an init function, call .init_fn(...) on it separately or set it via SandboxBuilder::init_fn.
  • runtime — always None; the clone is a fresh, un-started Sandbox.
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Sandbox

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Sandbox

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Drop for Sandbox

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl Serialize for Sandbox

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl TryFrom<&Sandbox> for Confinement

Source§

type Error = SandboxError

The type returned in the event of a conversion error.
Source§

fn try_from(sandbox: &Sandbox) -> Result<Self, Self::Error>

Performs the conversion.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more