Repository navigation
sandbox: deliver managed live shares as a host mapping table - #794
Merged
Enrique Saurez (esaurez) merged 2 commits intoOct 23, 2026
Merged
Enrique Saurez (esaurez) merged 2 commits into
Enrique Saurez (esaurez) merged 2 commits into
Conversation
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
Privileged mappings, workload admission, and failed-start teardown cross the host–guest boundary and warrant human review with the remaining platform validation.
No open issues 🎉
What changed in this PR
This PR moves managed layered sandboxes from boot-token live shares to ordered host mapping tables, building on the shared export planner and descriptor-rooted mapper. One-shot launches retain their existing boot-token behavior.
Changes:
- Export managed shares through one aggregate and deliver
MAPSrequests after guest readiness, before completingstart. - Apply mappings beneath the container root, block workloads until all mappings succeed, and unmount them during shutdown.
- Update feature negotiation, failure-path tests, fake OpenVMM behavior, and documentation.
| File | Description |
|---|---|
| scripts/test_nvx_tools.py | Tests managed export bootstrap validation and permissions. |
| nvx-rs/tests/cli.rs | Tests required features and failed-mapping cleanup. |
| nvx-rs/src/testing/fake_openvmm.rs | Models lifecycle-specific share delivery. |
| nvx-rs/src/protocol/tests.rs | Checks updated mapping-table feature sets. |
| nvx-rs/src/protocol/features.rs | Advertises and requires sandbox mapping-table support. |
| nvx-rs/src/host/sandbox/tests.rs | Separates managed and one-shot rendering assertions. |
| nvx-rs/src/host/sandbox/prepared.rs | Prepares launches with lifecycle-specific share delivery. |
| nvx-rs/src/host/sandbox/plan/tests.rs | Tests mapping tables, exports, and command-line budgets. |
| nvx-rs/src/host/sandbox/plan.rs | Renders managed exports and exposes ordered mappings. |
| nvx-rs/src/host/sandbox/options/tests.rs | Keeps one-shot option tests on boot-token rendering. |
| nvx-rs/src/host/sandbox/mount.rs | Generates managed aggregate bootstrap fragments. |
| nvx-rs/src/host/sandbox/golden.rs | Preserves one-shot Python parity checks. |
| nvx-rs/src/host/cli/session.rs | Sends mapping batches and handles guest responses. |
| nvx-rs/src/host/cli/sandbox/mod.rs | Keeps one-shot runs on boot-token preparation. |
| nvx-rs/src/host/cli/sandbox/lifecycle.rs | Delivers mappings before commit and handles failed starts. |
| nvx-rs/src/guest/managed_agent/mod.rs | Prepares mappings in both modes and tears down sandbox mappings. |
| nvx-rs/src/guest/managed_agent/mappings.rs | Maps beneath sandbox roots and reports teardown failures. |
| nvx-rs/src/guest/managed_agent/dispatch.rs | Tests sandbox mapping order, restrictions, and workload admission. |
| nvx-rs/src/guest/managed_agent/diagnostics.rs | Adds host-unmapping failure diagnostics. |
| nvx-rs/README.md | Documents managed mapping delivery and feature requirements. |
| guest/common/nvx-init-agent | Mounts the managed export separately from one-shot shares. |
| doc/usage.md | Explains lifecycle-specific share delivery and limits. |
| doc/run.md | Documents mapping admission, shutdown, and caller ownership behavior. |
| doc/design/5.2-readiness-and-runtime-control.md | Updates the managed start sequence. |
| doc/design/4.4-host-guest-control-interface.md | Documents sandbox mapping-table support. |
| doc/design/4.1-guest-filesystem-and-image-model.md | Describes managed export placement and root mapping. |
| .github/workflows/run-nvx-microvm-tests.yml | Expects caller-owned managed starts to fail without required privileges. |
Review effort: Balanced
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a4-pr4-export-composition-20261021
branch
from
October 23, 2026 11:08
3fd464f to
1f60357
Compare
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a4-pr4-export-composition-20261021-maps
branch
from
October 23, 2026 11:30
551cea5 to
748a37e
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
esaurez/a4-pr4-export-composition-20261021
branch
from
October 23, 2026 13:36
1f60357 to
cda9371
Compare
Base automatically changed from
esaurez/a4-pr4-export-composition-20261021
to
dev
October 23, 2026 13:55
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a4-pr4-export-composition-20261021-maps
branch
from
October 23, 2026 14:55
748a37e to
87aa251
Compare
Enrique Saurez (esaurez)
marked this pull request as ready for review
October 23, 2026 15:03
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a4-pr4-export-composition-20261021-maps
branch
from
October 23, 2026 15:56
87aa251 to
e1ae2ab
Compare
The managed agent's sandbox mode gains the host mapping table of its direct mode. When the kernel command line announces mappings with nvx_maps=, the agent applies the ordered MAPS batches through the descriptor-rooted mapper beneath the container's assembled root, from the export that the guest mounts at /run/nvx/hostfs/root, with the direct mode's ordering and latching. It refuses the targets that the container runtime keeps, admits no workload until the whole table is mounted, and keeps refusing workloads after a failed mapping. When its session ends, the agent unmounts the mappings in reverse order before it returns to the init agent, which then unmounts the root, and reports each mapping that stays mounted. No launch announces mappings to a sandbox yet, so the agent does not advertise the feature in this mode until one does. Part of #622 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e4de0d1f-0989-4804-ab6b-3c2891554406
A managed layered sandbox now receives its live shares as the blockless root receives its host directories. OpenVMM exports every share as a child of one aggregate, which the init agent mounts at /run/nvx/hostfs/root, in a directory that only root can enter, and the kernel command line announces only the number of mappings. Once the guest agent answers, start sends the plan's ordered mapping table as MAPS requests before the launch commits. A mapping that the guest refuses fails the start, after the guest shuts down as a stop has it do, unmounting what it mapped, the export, the overlay, and the scratch disk, and OpenVMM is terminated only if the guest does not shut down. start requires the host mapping table, which the sandbox agent now advertises, and the kernel command line no longer bounds the number of a managed sandbox's shares. The one-shot lifecycle keeps its nvx_share= boot tokens, as do /init's plain path and the restore probe, and the init agent's managed branch refuses them. SandboxPlan and PreparedLaunch render the managed lifecycle, and their one-shot renderings, with which the CLI's run prepares its launch, become crate-private. With --mount-owner caller, the guest agent reaches the shares as guest root, which OpenVMM squashes to their owner, before any workload runs, so a managed sandbox whose OpenVMM cannot assume that identity no longer starts. The microVM workflow's caller-owned test, whose runner grants OpenVMM neither CAP_SETUID nor CAP_SETGID, checks that now. Part of #622 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e4de0d1f-0989-4804-ab6b-3c2891554406
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a4-pr4-export-composition-20261021-maps
branch
from
October 23, 2026 17:04
e1ae2ab to
a3edbd3
Compare
Enrique Saurez (esaurez)
deleted the
esaurez/a4-pr4-export-composition-20261021-maps
branch
October 23, 2026 17:35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A managed layered sandbox now receives its live shares as ordered
MAPSrequests once its guest agent is ready, as the blockless root receives its host directories, instead of as boot tokens. This is the second part of A4's shared export composition: it builds on the export planner of #765 and the descriptor-rooted mapper of #774.What changed
The managed agent maps host paths in sandbox mode.
nvx_maps=), the sandbox-mode agent applies the orderedMAPSbatches throughnvx::guest::mappingsbeneath the container's assembled root, in the mount namespace of its own of which each execution's starts as a copy, from the export mounted at/run/nvx/hostfs/root, with the direct mode's ordering and latching. It refuses the targets that the container runtime keeps (Reserved::container_root) and creates a missing target only on the overlay, never inside another mapping.stage=host-unmapping).The init agent mounts the export.
nvx-init-agent's managed branch mounts the virtio-fs export at/run/nvx/hostfs/root, in a directory that only root can enter, withnosuid,nodev, and unmounts it after the agent's mappings and before the overlay.nvx_share=tokens and any other export location. The one-shot lifecycle keeps its tokens, as do/init's plain path (nvx-hostmount) and the virtio restore probe.startdelivers the plan's mapping table.SandboxPlan::openvmm_argumentsandkernel_command_line, and soPreparedLaunch::new, render the managed lifecycle: every share as a child of one aggregate atGUEST_EXPORT, andnvx_maps=COUNT.SandboxPlan::mapping_tablegives the ordered table. The one-shot renderings, with today's tokens, are crate-private and built only with theclifeature; the CLI's one-shotsandbox runprepares its launch with them.startrequires,startsends the table in as manyMAPSrequests as it takes, before the launch commits. A mapping that the guest refuses failsstart: the guest first shuts down asstophas it do, unmounting what it mapped, the export, the overlay, and the scratch disk, and OpenVMM is terminated only if the guest does not shut down within--timeout. The sandbox stays provisioned and stopped. A sandbox without shares maps nothing.GuestFeatures::LAYERED_SANDBOX, whichstartrequires, adds the host mapping table to per-execution environments.Behavior changes
--mount-owner caller, the guest agent reaches the shares as guest root, which OpenVMM squashes to the shares' owner, before any workload runs. A managed sandbox whose OpenVMM cannot assume that identity therefore fails to start, rather than start with shares that refuse every operation. The microVM workflow's caller-owned test, whose runner grants OpenVMM neitherCAP_SETUIDnorCAP_SETGID, now checks that the managed start fails with OpenVMM'sEPERMand the agent's host-mappings error; its one-shot part is unchanged.Part of #622
Refs #621
Validation
At this head, on
devat00d21385, on Windows 11 (WHP), and on Linux with MSHV on a VM host, where builds and checks ran as a non-root user and VMs as root, which alone may open the hypervisor device there:python scripts/nvx.py verifynvx-rs, withNVX_BUNDLE=skip:cargo fmt --all --check;cargo clippy --locked --all-targets --all-features -- -D warnings;cargo clippy --locked --lib --no-default-features -- -D warnings;cargo test --locked --all-features;cargo test --locked;cargo build --locked --lib --no-default-featuresandcargo test --locked --lib --no-default-features;cargo doc --locked --no-deps --all-featureswithRUSTDOCFLAGS=-D warnings;cargo +1.89 check --locked --all-targets --all-features; on Linux also theaarch64-apple-darwincheck, the agent bundling test, and the guest binaries' check and build.aci_edge_sandboxes: the steps ofcheck-aci-edge-sandboxes(fmt, both clippy configurations, both test configurations, docs, MSRV; macOS check on Linux).tests/runtime-adapter: the protocol-only and host-only configurations on both, and the guest-only (musl) configuration on Linux, whose MSRV check used the GNU target there.check-quality's Python and shell checks:ruff check,ruff format --check,pyright --pythonplatform LinuxandWindows, shellcheck and shfmt with the pinned images, and the Markdown link check.validate-nvx'scompileall, unittest list, and help commands on both; on Windows, thetest_setup_azuretests of the Linux setup scripts fail on this host with and without this change.--cpu-profile hoston this VM host), with the artifacts ofv0.1.0-dev.a37991311d1a, the newest development release in this branch's first-parent history, that ofa3799131, whose OpenVMM is79a501b6, the gitlink of both, and on both the Alpine initramfs built from this branch on Linux (nvx.py build-initramfs --guest alpine):nvx.py test-microvmwithfilesystem-shares,filesystem-policy,filesystem-comma-paths,filesystem-owner,denied-filesystem-paths,filesystem-snapshot,managed-lifecycle,managed-exec-config, andsandbox-lifecycle;nvx.py test-aci-edge-sandboxes: all pass on WHP; on MSHV, as root, the five tests that write through read-write mappings fail withPermission deniedwith and without this change, and the other 14 pass;cargo test --features host -- --ignored);nvx.py benchmark --suite device-restore-profile --restore-devices virtiofs --warmups 0 --runs 1), in both activation modes;/bin/...):startfails with the guest'sELOOPmapping error after the guest powers off with status 0, the scratch disk is left clean (noneeds_recovery),execreports the sandbox stopped, anddeprovisionsucceeds.