Skip to main content

Module staged_runtime

Module staged_runtime 

Source
Expand description

capabilities.shell.staged_runtime: staging a pinned host runtime tree into a capsule root.

§The mechanism, and why it is the inverse of interpreter_runtime

A path-based interpreter — CPython above all — cannot run from an allowlisted binary alone. Its stdlib lives outside the workdir, at a path the DT_NEEDED closure cannot discover, so something has to make that tree reachable. There are exactly two ways to do it:

  • [crate::sandbox]’s interpreter_runtime grants widen the capsule’s Landlock scope outwards, so the host’s /usr/lib/python3.11 stays readable from inside. That works at scoped, and it costs: the capsule is now coupled to one host’s directory layout, host paths stay reachable, and moving to a second host with a different Python build silently changes what the capsule runs. This is why declaring one fires W-SEC-009.
  • staged_runtime moves the tree inwards. A sealed capsule already builds a composed root out of read-only binds (crate::sealed); staging adds one more bind, of an operator-named, operator-pinned runtime tree, at the same absolute path it has on the host. Nothing outside the root becomes reachable, and the pin makes “the same interpreter on both hosts” a claim a human can check rather than assume.

The second supersedes the first for any binary that uses it, which is why the manifest parser refuses both for one binary rather than merging them (see parse_staged_runtime in murmur-artifact). Staging is not an additional grant layered onto a widened scope; it is the thing that makes widening unnecessary.

§What this module contains, and how the mount reaches the launch path

Two independent pieces, with very different reach:

  • check_staged_runtime_floor — pure, every OS, and live in the launch path. It is the gate that refuses to stage a capsule declaring staged_runtime below an effective sealed floor, called from runtime::stage_session next to check_containment_floor.
  • bind_mount_staged_runtimes — Linux-only, and the executable statement of the mount contract: the re-basing rule, the two-call read-only bind, and the failure taxonomy. It is built and proven here in isolation, against a throwaway directory tree inside a mount namespace its own test creates.

The staging mounts are performed on every sealed launch that declares a grant — but not by calling that function. sandbox::resolve_staged_runtime_dirs collects each grant’s source_path into ShellEnforcement::staged_runtime_dirs, build_sealed_root passes them to [crate::sealed::plan_composed_root]’s staged_runtime_read_only parameter, and they are planned as required RootOp::Bind steps ahead of every other step — and so ahead of pivot_root. A grant whose source is missing fails at the real mount(2) with ENOENT, aborting the construction; that reaches the operator as RuntimeError::SealedRootConstructionFailed (E-RUN-014) and is session-fatal.

The function itself stays uncalled by production code because it allocates, and the composed root executes inside the forked child’s pre_exec window, which must not — see bind_mount_staged_runtimes’s own doc comment. It remains valuable as an independently provable statement of what the planned step must do on a real kernel, without needing a sealed capsule, a pivot_root or the enforcement pipeline to demonstrate it.

Structs§

StagedRuntimeMountError
One staged-runtime bind mount that could not be established.

Enums§

StagedRuntimeMountStage
Where bind_mount_staged_runtimes failed, so the error names a step rather than a bare errno.

Functions§

bind_mount_staged_runtimes
Bind-mounts every declared staged_runtime tree read-only into root, each at its own absolute host path re-based under root. Returns the target paths it established, in order.
check_staged_runtime_floor
Refuses a capsule that declares capabilities.shell.staged_runtime without an effective sealed containment floor.