Repository navigation
sandbox: attach multiple virtio-fs shares with independent ro/rw modes - #401
Merged
Pedro Henrique Penna (ppenna) merged 2 commits intoOct 6, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Bind-mount aliases bypass NVX pre-launch validation, and WHP CI omits the claimed scratch-journal check.
Review effort: Balanced
Findings: 2
Open (2)
What changed in this PR
Adds end-to-end support for two concurrent virtio-fs shares with independent read/write policies.
Changes:
- Adds a second OpenVMM virtio-fs slot and kernel mapping.
- Extends CLI, guest mounting, managed configuration, and snapshots for two shares.
- Adds cross-platform tests, CI coverage, and documentation.
| File | Description |
|---|---|
.github/workflows/run-nvx-microvm-tests.yml |
Adds concurrent-share CI coverage. |
doc/ci.md |
Documents CI validation. |
doc/design/integrated-implementation-status.md |
Records the ninth MMIO slot. |
doc/design/machine-and-device-abi.md |
Documents the second filesystem slot. |
doc/design/validation.md |
Describes concurrent-share validation. |
doc/run.md |
Documents multi-share operation. |
doc/usage.md |
Updates CLI reference. |
guest/common/nvx-hostmount |
Mounts repeated host shares. |
guest/common/nvx-init-agent |
Parses, mounts, and unmounts multiple shares. |
guest/common/nvx-sandbox-smoke |
Tests isolated read/write policies. |
kernel/patches/0003-microvm-virtio-mmio-shared-status.patch |
Maps the second slot’s status word. |
openvmm |
Advances the OpenVMM pin. |
scripts/nvx.py |
Accepts and attributes repeated mount options. |
scripts/nvx_tools/microvm_test_scripts/filesystem-shares-snapshot.sh |
Tests two-share snapshot resume. |
scripts/nvx_tools/microvm_test_scripts/filesystem-shares.sh |
Exercises host-enforced access modes. |
scripts/nvx_tools/microvm_tests.py |
Adds the filesystem-shares scenario. |
scripts/nvx_tools/sandbox.py |
Models and validates multiple mounts. |
scripts/nvx_tools/sandbox_lifecycle.py |
Persists format-4 multi-mount configurations. |
scripts/test_microvm_tests.py |
Tests the new scenario harness. |
scripts/test_nvx_tools.py |
Expands CLI, agent, and lifecycle tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Pedro Henrique Penna (ppenna)
force-pushed
the
fix/issue-298-multiple-virtiofs-shares
branch
from
October 6, 2026 04:41
7000cd6 to
4fddc21
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
fix/issue-298-multiple-virtiofs-shares
branch
from
October 6, 2026 05:25
4fddc21 to
dc2de6c
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
fix/issue-298-multiple-virtiofs-shares
branch
from
October 6, 2026 05:41
dc2de6c to
490ed70
Compare
Promote the `openvmm` submodule from `4cb5777fa` to `a41cf7351`, the head of nanvix/openvmm#113. `--mount` becomes repeatable: a second attachment uses a second fixed virtio-fs slot, `fs:microvm1` with tag `microvm1` at MMIO 0xd0008000 and IRQ 13, served by its own HostFs server with its own access mode and denied paths. The guest targets and the host directories of the two shares must not equal or contain one another; on Linux, OpenVMM also compares the filesystem sources that each directory reaches through its mounts, so a bind mount or nested mount can't expose one share inside the other. With two shares, each `--mount-deny` must be an absolute path inside one of them. Snapshots record both shares, pin their discovery and bootstrap tokens in slot order, and a restore must supply them again in capture order. A machine with one share or none keeps its device inventory and command line. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9ee620ea-2f80-4743-9e4a-f771fb2f8c86
Closes #298. Part of #290 (requirement 2) and #281. AWF's Cloud Hypervisor mount policies need a read-write /workspace and a read-only tool cache attached to one sandbox at the same time, each with its access mode enforced by the host. The pinned OpenVMM exposes a second virtio-fs slot for a second `--mount`; use it end to end: - Kernel. The microVM virtio-mmio shared-status patch maps the second slot's MMIO base, 0xd0008000, to its status word, 0x30020. A kernel without the mapping refuses to probe the device, so the share fails closed. - CLI. `sandbox run` and `provision` accept `--mount` twice. Each `--mount-deny` applies to the `--mount` before it, and a relative path resolves in that share; with one share, every `--mount-deny` still applies to it. With two shares, NVX forwards the denied paths as absolute paths, which OpenVMM attributes to the share whose directory contains them. Overlapping guest targets, overlapping host directories, including one directory reached through two paths such as a bind mount and a share inside a bind mount of the other share's directory, a denied path outside its share, and a third share are rejected before OpenVMM starts. `--mount-owner` applies to both shares, and `run` forwards a repeated `--mount` too. - Budget. The bootstrap tokens of both shares count toward the sandbox's 1024-byte kernel command-line budget. - Managed sandboxes. A configuration with two shares lists them under `mounts` in format 4, which earlier NVX releases reject instead of starting without the second share. One share keeps formats 2 and 3. - Guest. `nvx-init-agent` parses every `virtfs_dir=`, `virtfs_tag=`, `virtfs_mode=` triplet before it mounts any, and fails closed on an incomplete or out-of-order triplet, a repeated tag, and targets that equal or contain one another. It mounts the shares in slot order, and a one-shot exit, a managed `stop`, and `fatal` unmount them in reverse order before the overlay. `nvx-hostmount` mounts every share outside the sandbox. - Smoke test. `nvx-sandbox-smoke` checks repeated TARGET MODE pairs and, given an `rw` and an `ro` share, requires a link in the `rw` share to fail to write into the `ro` share. - test-microvm. The new `filesystem-shares` scenario, in the default set on every backend, attaches a read-write workspace and a read-only tool cache, each with its own denied path. Guest writes must reach the workspace, and every mutation of the tool cache must fail, also through a link and, with its tag remounted read-write in the guest, with EROFS from OpenVMM. Three shares, nested guest targets, nested host directories, and a relative denied path must be rejected before boot, and both shares must round-trip through a snapshot whose restore requires them in capture order. - CI. New Linux and Windows steps attach a read-write /workspace share and a read-only /opt/hostedtoolcache share to one Ubuntu sandbox, one-shot and managed. The guest's writes must reach the workspace, the tool cache and the denied files must stay unchanged, the managed configuration must use format 4, and `stop` must leave a clean scratch journal. - Docs. run.md, usage.md, ci.md, and the design notes describe the second share, its rules, and the new coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9ee620ea-2f80-4743-9e4a-f771fb2f8c86
Pedro Henrique Penna (ppenna)
force-pushed
the
fix/issue-298-multiple-virtiofs-shares
branch
from
October 6, 2026 07:20
490ed70 to
c220042
Compare
Pedro Henrique Penna (ppenna)
deleted the
fix/issue-298-multiple-virtiofs-shares
branch
October 6, 2026 08:04
This was referenced Oct 6, 2026
This was referenced Oct 7, 2026
Closed
8 tasks
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.


Closes #298. Part of #290 (requirement 2) and #281.
What
AWF's Cloud Hypervisor mount policies need a read-write
/workspaceshare and a read-only/opt/hostedtoolcacheshare attached to one sandbox at the same time, each with its own guest mount point, device tag, and access mode enforced by the host. The microVM had a single virtio-fs slot. This adds a second slot in OpenVMM and uses it end to end.OpenVMM pin
The
openvmmgitlink moves from4cb5777fatoa41cf7351, the head of nanvix/openvmm#113: two signed commits directly on nanvix/openvmmmain, the feature and a review follow-up. With the new pin:fs:microvm0microvm0xd00010000x30004fs:microvm1microvm10xd00080000x30020--mount. Attachments fill the slots in order. Each adds avirtfs_dir=,virtfs_tag=,virtfs_mode=triplet with its slot's tag. The second slot exists only with a filesystem attached, so a machine with one share or none keeps its device inventory, command line, and snapshot contract./proc/self/mountinfo), so a bind mount or nested mount can't expose part of one share inside the other. With two shares, each--mount-denymust be absolute and applies to the share whose root contains it.--mount-ownerapplies to both shares.NVX
0003-microvm-virtio-mmio-shared-status.patchmaps the second slot's MMIO base to its status word. A kernel without the mapping refuses to probe the device, so the share fails closed.sandbox runandprovisionaccept--mounttwice. Each--mount-denyapplies to the--mountbefore it, and a relative path resolves in that share; with one share, every--mount-denystill applies to it. NVX forwards absolute denied paths to OpenVMM. Overlapping guest targets, overlapping host directories (compared by resolved path and by the file identities of each directory and of the other's ancestors, which also catches one directory reached through two paths and a share inside a bind mount of the other share's directory), a denied path outside its share, and a third share are rejected before OpenVMM starts. OpenVMM's Linux mount-source check also rejects a bind mount that exposes part of one share inside the other. Both shares' bootstrap tokens count toward the 1024-byte command-line budget.runforwards a repeated--mounttoo.mountsin configuration format 4, which earlier NVX releases reject instead of starting without the second share. One share keeps formats 2 and 3.nvx-init-agentparses every triplet before it mounts any, fails closed on an incomplete or out-of-order triplet, a repeated tag, or overlapping targets, mounts the shares in slot order, and unmounts them in reverse order before the overlay on a one-shot exit, a managedstop, orfatal.nvx-hostmountmounts every share outside the sandbox.nvx-sandbox-smokechecks repeatedTARGET MODEpairs and, given anrwand anroshare, requires a link in therwshare to fail to write into theroshare.test-microvm. The newfilesystem-sharesscenario joins the default set on every backend. It attaches a read-write workspace and a read-only tool cache, each with its own denied path, and requires:microvm1tag remounted read-write inside the guest, withEROFSfrom OpenVMM;/workspaceshare and a read-only/opt/hostedtoolcacheshare to one Ubuntu sandbox, one-shot and managed. The guest's writes must reach the workspace, the tool cache and the denied files must stay unchanged, the managed configuration must use format 4, andstopmust leave a clean scratch journal.run.md,usage.md,ci.md, and the design notes.Acceptance criteria
rw/workspaceshare and anro/opt/hostedtoolcacheshare at the same timefilesystem-shares; unit tests for parsing, forwarding, persistence, and the guest agentroshare fail withEROFS/EACCES; writes to therwshare reach the hostro/rwchecks and cross-share link check, with host-side verification of the workspace, the unchanged tool cache, and the denied files;filesystem-sharesfilesystem-sharesremounts themicrovm1tag read-write inside the guest and requirestouch,mkdir, append,rm,mv,ln -s, andchmodto fail withEROFS; each slot is its own HostFs serverroandrwshares on KVM, MSHV, and WHPfilesystem-sharesscenario innvx-microvm-tests-{kvm,mshv,whp}nvx-init-agentreject equal or nested targets; tags are fixed per slot, and the agent rejects a repeated tagValidation
The bare-metal and local runs used NVX
490ed705with OpenVMMe37086001. The final heads, NVXc2200425and OpenVMMa41cf7351, differ from those only in the gitlink:a41cf7351rebasese37086001ontomain, and its tree,b47313c7, is identical, so the tested OpenVMM source is exactly the pinned one. Onc2200425,nvx.py verifyand thevalidate-nvxunit tests pass locally, and CI runs the full matrix. The bare-metal runs used a release OpenVMM built from the pin and guest artifacts built with Docker from this tree, whose provenance inputs are unchanged by the rebase.ruff check,ruff format --check,compileall,pyrightfor Linux and Windows,test_adversarial.py,test_hosts.py, and thevalidate-nvxunit test set (740 tests; all pass except the Windows curl-shim test, whose precondition needsrustconPATH).nvx.py verify;test-microvmsuite (34 scenarios), including everyfilesystem-sharescase, and the Ubuntu and Azure Linux guest smoke runs from the workflow.nvx.py verify, the four Windows Ubuntu sandbox CI steps, including the new concurrent shares, the full defaulttest-microvmsuite (34 scenarios), and the Ubuntu and Azure Linux guest smoke runs.nvx.py runwith anrwworkspace and anroshare that is a bind mount of a workspace subdirectory, or with anrodirectory bind-mounted inside the workspace, fails before boot with OpenVMM'sreach the same files through a mounterror, and the same layout without the bind mount boots; NVX's pre-check rejects anroshare inside a bind mount of the workspace and accepts the same layout without it.cargo xtask fmt; see microVM: attach a second virtio-fs share with its own slot nanvix/openvmm#113.Notes
maintoa41cf7351, so the pin ismain's head.azure-mshv-scus-1, and each time the gate flagged guest-exit teardown and multi-vCPU snapshot restore, by +26%, +41%, and +78% at 2, 4, and 8 vCPUs. That runner has the same CPU as the baseline runners but a different host kernel,6.6.137.mshv2-2.azl3;azure-mshv-1,-6, and-7run6.6.148-200.azl3. Re-running the same build onazure-mshv-7matched the baseline (teardown 24.63 vs 24.58 ms and 8.53 vs 8.16 ms; 8-vCPU restore 53.30 vs 52.80 ms), and same-host A/B runs on bare-metal MSHV showed no difference fromdev. Until the baselines account for it,azure-mshv-scus-1may fail the gate for any PR.