Repository navigation
nvx-rs: mount the host export as a source of a root's mappings - #864
Merged
Pedro Henrique Penna (ppenna) merged 2 commits intoOct 25, 2026
Merged
Pedro Henrique Penna (ppenna) merged 2 commits into
Pedro Henrique Penna (ppenna) merged 2 commits into
Conversation
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
The privileged export-mount path has an unresolved access-control concern and needs human review.
1 open issue
What changed in this PR
Adds the guest-library support needed for #822’s runtime adapter to use the host export as a mapping source, without changing NVX’s current guest behavior.
Changes:
- Adds strict parsing of aggregate-export boot tokens and shares the export-directory constant with host planning.
- Adds
Root::mount_export, including mount ownership, failure latching, and teardown integration. - Adds parser fixtures, mount-lifecycle tests, and API documentation.
| File | Description |
|---|---|
nvx-rs/tests/fixtures/export-tokens.json |
Defines accepted and rejected export-token cases. |
nvx-rs/src/protocol/mod.rs |
Exposes and documents the export module. |
nvx-rs/src/protocol/export/tests.rs |
Tests parsing, validation, and fixture coverage. |
nvx-rs/src/protocol/export.rs |
Defines export types, constants, and strict parsing. |
nvx-rs/src/host/filesystem.rs |
Reuses the protocol’s export-directory constant. |
nvx-rs/src/guest/root/tests.rs |
Tests export mounting, mappings, refusals, and teardown. |
nvx-rs/src/guest/root/share.rs |
Implements export mounting and private-directory preparation. |
nvx-rs/src/guest/root.rs |
Integrates export ownership, stale-mount checks, and documentation. |
nvx-rs/README.md |
Documents the new protocol and guest APIs. |
Review effort: Balanced
Enrique Saurez (esaurez)
changed the base branch from
dev
to
esaurez/822-pr04-framing-20261023
October 24, 2026 17:32
Enrique Saurez (esaurez)
force-pushed
the
esaurez/822-pr05-export-mapping-source-20261023
branch
from
October 24, 2026 17:32
fe1ed2d to
1a46aba
Compare
This was referenced Oct 24, 2026
This was referenced Oct 25, 2026
Pedro Henrique Penna (ppenna)
force-pushed
the
esaurez/822-pr04-framing-20261023
branch
from
October 25, 2026 15:09
73831cd to
d34ccaa
Compare
A guest that maps host paths into a layered root from the host's mapping table needs the host export, the aggregate virtio-fs device that OpenVMM attaches for those paths, mounted outside the root. NVX's shell init mounts it for its own agent, but a guest built on nvx::guest had no way to mount it as the source of Root::map. - nvx::protocol::export: HostExport::parse, a strict parser of the virtfs_dir=, virtfs_tag=, virtfs_mode=, and virtfs_aggregate=1 tokens that OpenVMM appends for the export: all four or none, each once and in its form, with the checks of the shell init's mount_host_export, and no nvx_share= token. EXPORT_DIRECTORY is the export's guest directory, which nvx::host::filesystem::GUEST_EXPORT now names, so the host's plan and the guest's parser share it. tests/fixtures/export-tokens.json holds the parser's cases. - Root::mount_export mounts the export nosuid,nodev, read-only or read-write, at hostfs/root in the runtime directory, below a directory that only root may enter, owns the mount, unmounts it after the mappings at teardown, and returns its SourceRoot for Root::map. A root mounts one export; a failure latches the root, and an assembly refuses a runtime directory where an export is mounted already. Part of #822. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3d31a6be-a0f8-4952-8667-0ebdc440d08d
Root::mount_export mounts the host export below hostfs in the runtime directory, a directory that only root may enter, so that a workload reaches host paths only through their mappings. A hostfs that was there already kept its owner and mode, so one that another user owned, or that its group or others could enter, would expose the export's children directly. Accept a hostfs that is there already only if it is private to the process's effective user: owned by that user, with no permission for its group or others, as the one that an earlier root leaves. Refuse any other, and leave it unchanged. NVX's shell init refuses any hostfs that is there already, since it mounts the export once per boot, while a root may be assembled again in a runtime directory where an earlier root left hostfs. Part of #822 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3d31a6be-a0f8-4952-8667-0ebdc440d08d
Pedro Henrique Penna (ppenna)
force-pushed
the
esaurez/822-pr05-export-mapping-source-20261023
branch
from
October 25, 2026 15:36
1a46aba to
b684976
Compare
Pedro Henrique Penna (ppenna)
deleted the
esaurez/822-pr05-export-mapping-source-20261023
branch
October 25, 2026 16:01
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.

Part of #822: PR 5 of 11, the export as a mapping source, in
nvx::guest. It follows #822's PRs 1 to 4, #863, #867, #869, and #865, in that order, which have merged. This PR is rebased onto dev at8c678005, #865's merge, and holds only its own two commits, which need nothing from those PRs.A guest that maps host paths into a layered root from the host's mapping table needs the host export, the aggregate virtio-fs device that OpenVMM attaches for those paths, mounted outside the root. NVX's shell init mounts it for its own agent (
mount_host_exportinguest/common/nvx-init-agent), but a guest built onnvx::guesthad no way to mount it as the source ofRoot::map. This is #822's one library addition.Changes
nvx::protocol::export, a new module:HostExport::parse, a strict parser of the tokens that OpenVMM appends for an aggregate export.virtfs_dir=/run/nvx/hostfs/root(EXPORT_DIRECTORY),virtfs_tag=a name of letters, digits,_, and-,virtfs_mode=roorrw(ExportMode), andvirtfs_aggregate=1.mount_host_export, including its refusal ofnvx_share=tokens, which bind live shares.virtfs_aggregate=1, another aggregate value, or a token without a value is refused.tests/fixtures/export-tokens.jsonholds its vectors.nvx::host::filesystem::GUEST_EXPORTnow namesEXPORT_DIRECTORY, so that the host's plan and the guest's parser share the directory. Its value does not change.Root::mount_export(tag, access), innvx::guest::root:nosuid,nodev, read-only or read-write, athostfs/rootin the runtime directory, outside the root, below ahostfsdirectory that only root may enter (mode 0700, whatever the umask), as the shell does. Ahostfsthat is there already, such as one that an earlier root left, must be as private: owned by the process's effective user, with no permission for its group or others. Another is refused, and stays unchanged;SourceRootforRoot::map.A refused tag creates and mounts nothing, and a root mounts one export. A later failure latches the root, as a share's does, and an assembly refuses a runtime directory where an export is still mounted.
From<ExportMode> for Accessgives the mount's access from the parsed mode.NVX's own guest does not change, so the boot contract version stays. #817 can replace the shell's export mount with these, and #845's PR 3 mounts a clone's export with them.
Validation
At this head,
b6849761, rebased onto dev at8c678005once #865 merged. The rebase applied without conflicts, andgit range-diffshows both commits unchanged. Of their files, dev changed onlynvx-rs/README.md, in rows that this PR does not touch. CI passed on this head, the KVM, MSHV, and WHP jobs included.Windows, x86_64, at this head:
nvx.py verify;nvx-rsfmt, Clippy in the three configurations, the tests in the three configurations, rustdoc, and the 1.89 MSRV check;tests/runtime-adapterin its protocol-only and host-only configurations: fmt, Clippy, the build, the tests, and the MSRV check;aci_edge_sandboxesfmt, Clippy, the tests, rustdoc, and the MSRV check; andscripts/check_markdown_links.py.At the previous head,
1a46abac, on #865's branch:Linux, x86_64:
nvx-rs:cargo fmt --check; Clippy with-D warnings, with all targets and features and for the library without default features; the tests with all features, with the default features, and of the library without default features; the bundled-artifacts test; rustdoc with-D warnings; the 1.89 MSRV check; and theaarch64-apple-darwincheck.nvx.py check-guest-binaries,build-guest-binaries, andtest-guest-binaries.tests/runtime-adapter, in its protocol-only, host-only, and musl guest-only configurations: fmt, Clippy, the build, the tests, and the MSRV check.aci_edge_sandboxes: fmt, Clippy, the tests,nvx.py test-agent-bundling, rustdoc, the MSRV check, and the macOS check.scripts/check_markdown_links.py.Windows, x86_64:
nvx-rsfmt, Clippy, the tests in the three configurations, rustdoc, and the MSRV check.WHP: the runtime adapter's VM scenarios, the ignored tests of
tests/vm_layered.rs,tests/vm_restart.rs, andtests/vm_steps.rs, 30 in all, withcargo test --locked --features host -- --ignored.The change adds no behavior that a VM shows by itself: the adapter mounts the export in VMs from #822's PR 6 on.