Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bbbb238
cli: run cold blockless VMs through the verified lifecycle
Nov 10, 2026
1e3cea2
docs: document CLI foreground child ownership
Nov 10, 2026
b51da00
cli: preserve unrecorded run artifacts and planned-share runtime cove…
Nov 10, 2026
1bc21ea
style: format planned-share scenario export mode
Nov 10, 2026
2822089
test: align download cleanup with restored cold-run fixtures
Nov 10, 2026
4c3653e
cli: address foreground connection, output, and report findings
Nov 10, 2026
e2f037d
cli: stream lossy UTF-8 only to Windows consoles
Nov 10, 2026
1578158
test: scope unsafe console calls to the isolated Windows helper
Nov 10, 2026
6f010ee
test: initialize boot capacity in the integrated launch fixture
Nov 10, 2026
9d66d7e
fix: preserve cold-run diagnostics and confirmed cleanup
Nov 10, 2026
8cdf727
test: move the attachment receiver into its scoped worker
Nov 10, 2026
6add626
fix: preserve cold-run refusal diagnostics after preflight
Nov 10, 2026
8ab2b7b
fix: preserve canonical interruption after cold-run report publication
Nov 10, 2026
4bb2b7f
fix: cancel foreground attachment and preserve terminal interrupts
Nov 10, 2026
452ed07
test: exercise raw-terminal foreground cancellation through private t…
Nov 10, 2026
55c273e
test: retain exact terminal cancellation receipts and pipe EOF handling
Nov 10, 2026
86e7661
fix: preserve the public owned-launch API during foreground integration
Nov 10, 2026
a620571
fix: release scoped attachment cancellation handles after handshake
Nov 10, 2026
d876ee5
style: format scoped cancellation handle release
Nov 10, 2026
44b0a1a
test: require the gated native process start time before holding it
Nov 10, 2026
f0c4e34
test: give the private ConPTY CLI its actual console input
Nov 10, 2026
dc9a7c6
Keep quit and suspend keys in the raw guest console
Nov 11, 2026
f5ebf5a
Apply formatter output to terminal input regression fixtures
Nov 11, 2026
a08aa41
Classify terminal dependencies in the existing notices inventory
Nov 11, 2026
95dcce4
test: report terminal readiness only after interrupts are enabled
ppenna Nov 11, 2026
4beb1ce
cli: restore the console's entry input mode on Windows
ppenna Nov 11, 2026
231b618
test: restore Ctrl-C processing in the private console helpers
ppenna Nov 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ the distribution tooling.
| Rust `libc` crate 0.2.189 | linked into the guest binaries and the Linux `bin/nvx-rs` through `nix` and `getrandom` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are at [`rust-lang/libc` tag 0.2.189](https://github.com/rust-lang/libc/tree/0.2.189). |
| Rust `nix` crate 0.31.3 | system-call wrappers used by the guest binaries and the Linux `bin/nvx-rs` | MIT; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`nix-rust/nix`](https://crates.io/crates/nix/0.31.3). |
| Rust `getrandom` crate 0.4.3 | random bytes for the guest binaries, such as `nvx-reseed --sample`, and for `bin/nvx-rs[.exe]`, such as control capabilities | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`rust-random/getrandom`](https://crates.io/crates/getrandom/0.4.3). |
| Rust `bitflags` crate 2.13.2 | transitive `nix` dependency in the guest binaries and the Linux `bin/nvx-rs` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`bitflags/bitflags`](https://crates.io/crates/bitflags/2.13.2). |
| Rust `bitflags` crate 2.13.2 | transitive `nix` dependency in the guest binaries and `nix` or `crossterm` dependency in `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`bitflags/bitflags`](https://crates.io/crates/bitflags/2.13.2). |
| Rust `cfg-if` crate 1.0.5 | transitive `nix`, `getrandom`, and `sha2` dependency in the guest binaries and `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`rust-lang/cfg-if`](https://crates.io/crates/cfg-if/1.0.5). |
| Rust `memoffset` crate 0.9.1 | transitive `nix` dependency in the guest binaries and the Linux `bin/nvx-rs` | MIT; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`Gilnaa/memoffset`](https://crates.io/crates/memoffset/0.9.1). |
| Rust `serde` crate 1.0.229 | serialization framework of `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`serde-rs/serde`](https://crates.io/crates/serde/1.0.229). |
Expand All @@ -37,6 +37,18 @@ the distribution tooling.
| Rust `typenum` crate 1.20.1 | transitive `sha2` dependency in `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`paholg/typenum`](https://crates.io/crates/typenum/1.20.1). |
| Rust `windows-sys` crate 0.61.2 | Windows API bindings of `bin/nvx-rs.exe` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`microsoft/windows-rs`](https://crates.io/crates/windows-sys/0.61.2). |
| Rust `windows-link` crate 0.2.1 | transitive `windows-sys` dependency in `bin/nvx-rs.exe` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and the source is published by [`microsoft/windows-rs`](https://crates.io/crates/windows-link/0.2.1). |
| Rust `crossterm` crate 0.29.0 | terminal-mode preservation in `bin/nvx-rs[.exe]` | MIT; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`crossterm`](https://crates.io/crates/crossterm/0.29.0). |
| Rust `crossterm_winapi` crate 0.9.1 | transitive `crossterm` Windows console support in `bin/nvx-rs.exe` | MIT; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`crossterm_winapi`](https://crates.io/crates/crossterm_winapi/0.9.1). |
| Rust `winapi` crate 0.3.9 | transitive `crossterm` and `crossterm_winapi` Windows API bindings in `bin/nvx-rs.exe` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`winapi`](https://crates.io/crates/winapi/0.3.9). |
| Rust `parking_lot` crate 0.12.5 | transitive `crossterm` synchronization in `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`parking_lot`](https://crates.io/crates/parking_lot/0.12.5). |
| Rust `parking_lot_core` crate 0.9.12 | transitive `parking_lot` synchronization in `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`parking_lot_core`](https://crates.io/crates/parking_lot_core/0.9.12). |
| Rust `lock_api` crate 0.4.14 | transitive `parking_lot` synchronization in `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`lock_api`](https://crates.io/crates/lock_api/0.4.14). |
| Rust `scopeguard` crate 1.2.0 | transitive `lock_api` cleanup guards in `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`scopeguard`](https://crates.io/crates/scopeguard/1.2.0). |
| Rust `smallvec` crate 1.16.5 | transitive `parking_lot_core` storage in `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`smallvec`](https://crates.io/crates/smallvec/1.16.5). |
| Rust `document-features` crate 0.2.12 | build-time procedural macro used by `crossterm`, not linked into `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`document-features`](https://crates.io/crates/document-features/0.2.12). |
| Rust `litrs` crate 1.0.1 | build-time `document-features` dependency, not linked into `bin/nvx-rs[.exe]` | MIT OR Apache-2.0; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`litrs`](https://crates.io/crates/litrs/1.0.1). |
| Rust `rustix` crate 1.1.5 | transitive `crossterm` terminal-mode support in the Linux `bin/nvx-rs` | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`rustix`](https://crates.io/crates/rustix/1.1.5). |
| Rust `linux-raw-sys` crate 0.12.1 | transitive `rustix` Linux API bindings in the Linux `bin/nvx-rs` | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT; the exact crate checksum is pinned in `nvx-rs/Cargo.lock`, and source and license files are published with [`linux-raw-sys`](https://crates.io/crates/linux-raw-sys/0.12.1). |
| musl libc | statically linked into `/sbin/nvx-console-pending`, `/sbin/nvx-mmio-write`, `/sbin/nvx-reseed`, `/sbin/nvx-exit`, `/sbin/nvx-device-io`, `/sbin/nvx-managed-agent`, `/sbin/nvx-ingress`, `/sbin/nvx-time`, `/sbin/nvx-time-probe`, and `/sbin/nvx-init` in every generated initramfs, and into `bin/nvx-rs` of the `linux-kvm` and `linux-mshv` release packages | MIT; Copyright © 2005-2020 Rich Felker, et al. The exact implementation is supplied by the pinned Rust release's `x86_64-unknown-linux-musl` target. Upstream source and the full copyright notice are at [musl libc](https://musl.libc.org/). |
| LLVM `libunwind` | statically linked, with musl, into the ten guest binaries and the Linux `bin/nvx-rs`, which unwind and print backtraces through it | Apache-2.0 WITH LLVM-exception, whose exception lifts the attribution conditions for code embedded in a compiled program. The exact implementation is the `libunwind.a` that the pinned Rust release's `x86_64-unknown-linux-musl` target supplies, which the Rust project builds from its fork of [`llvm-project/libunwind`](https://github.com/llvm/llvm-project/tree/main/libunwind). |
| Microsoft C runtime: the Visual C++ runtime and the Universal C Runtime | statically linked into `bin/nvx-rs.exe` of the `windows-whp` release package, which CI builds with `-C target-feature=+crt-static`, so that it runs without the Visual C++ Redistributable | Proprietary Microsoft object code, linked in by the Visual Studio build tools and the Windows SDK of CI's Windows runner under their Microsoft Software License Terms, which permit distributing the programs built with them; see [Redistribute Visual C++ files](https://learn.microsoft.com/cpp/windows/redistributing-visual-cpp-files). No source is distributed. |
Expand Down
15 changes: 12 additions & 3 deletions doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ nvx-rs/target/release/nvx-rs run
| `--memory-capacity-mib MIB` | none | Reserve an immutable, 128 MiB-aligned RAM capacity for a fresh microVM snapshot, in the range of `--memory-mib`. |
| `--processors {1,2,4,8}` | `1` | Select the microVM processor count, written as one of the choices. |
| `--cpu-profile ID` | `auto` | Select the guest's [CPU profile](#cpu-profiles): `auto` for the built-in profile of the host's CPU, which falls back with a warning to a development profile derived from this host on an Intel or AMD CPU that no built-in profile serves, a built-in profile ID, or `host` for that development profile. A restore uses the snapshot's profile, which `auto` and, for a host profile, `host` also name. |
| `--mount GUEST_TARGET,HOST_PATH[,ro\|rw]` | none | Expose a host directory, or a single regular host file without its directory, at the guest target: an absolute, canonical path other than `/`, without whitespace, control characters, double quotes, backslashes, `=`, or any UTF-8 byte that Linux treats as whitespace, such as the `0xa0` in `à`. The mode follows the last comma, so `HOST_PATH` may contain commas when the mode is given. Repeat to expose more directories or files, each with its own target and mode, as the children of an aggregate on the microVM's one virtio-fs device, which the guest binds at their targets; a shared file always uses the aggregate. Targets and host paths must not overlap, and the shares' kernel command-line tokens must fit its 1024-byte budget. An `rw` mapping accepts guest-created symbolic links, which the host never follows. Active snapshot restore requires the same mappings in the same order, with the same canonical paths, kinds, targets, modes, and ownership mode; a dormant-slot restore may attach one new directory mapping that the resumed guest mounts explicitly. |
| `--mount GUEST_TARGET,HOST_PATH[,ro\|rw]` | none | Expose a host directory, or a single regular host file without its directory, at the guest target: an absolute, canonical path other than `/`, without whitespace, control characters, double quotes, backslashes, `=`, or any UTF-8 byte that Linux treats as whitespace, such as the `0xa0` in `à`. Cold boots also protect the system paths listed below. The mode follows the last comma, so `HOST_PATH` may contain commas when the mode is given. Repeat to expose more directories or files, each with its own target and mode, as the children of an aggregate on the microVM's one virtio-fs device, which the guest binds at their targets; a shared file always uses the aggregate. Targets and host paths must not overlap, and the shares' kernel command-line tokens must fit its 1024-byte budget. An `rw` mapping accepts guest-created symbolic links, which the host never follows. Active snapshot restore requires the same mappings in the same order, with the same canonical paths, kinds, targets, modes, and ownership mode; a dormant-slot restore may attach one new directory mapping that the resumed guest mounts explicitly. |
| `--mount-deny HOST_PATH` | none | Hide one existing file or directory inside a mounted host root; repeat to deny multiple paths. It may name the root itself when `--mount-allow` paths inside it remain. With several mappings, or a shared file, the path must be absolute; a shared file takes none. |
| `--mount-allow HOST_PATH` | none | Expose one existing file or directory inside a `--mount-deny` path again; the hidden directories on the way list only the entries that lead to it. Repeat to allow multiple paths. With several mappings, or a shared file, the path must be absolute; a shared file takes none. See [Access policy](run.md#access-policy). |
| `--mount-write HOST_PATH` | none | Make one existing file or directory one of the only writable parts of an `rw` mapping; the guest's writes anywhere else in it fail with `EROFS`. Repeat to declare multiple writable paths. With several mappings, or a shared file, the path must be absolute; a shared file takes none. Active snapshot restore requires the same denied, allowed, and writable paths. |
Expand All @@ -179,15 +179,24 @@ nvx-rs/target/release/nvx-rs run
| `--host-loopback {allow,deny}` | existing mapping | Control access between the guest and host loopback services. Explicit `allow` is bidirectional: the guest reaches host loopback through its gateway, and every TCP and UDP port on which the guest listens is published on host loopback for the host alone, or with `--network-ingress allow` admits the host as well; it needs a `--net` prefix of `/29` or shorter, which OpenVMM checks; see [Host-loopback access](run.md#host-loopback-access). Snapshot capture rejects `allow`, and so does a restore, unless `--restore-network-policy` installs a new policy. |
| `--network-proxy IPV4:TCP-PORT` | none | Allow one explicit host TCP proxy endpoint. |
| `--host-loopback-forward PROTOCOL:HOST_PORT:GUEST_PORT` | none | Publish one TCP or UDP localhost port to the guest; repeat to add forwards. Snapshot capture rejects forwards, and so does a restore, unless `--restore-network-policy` installs a new policy. |
| `--outcome-report PATH` | none | Write a bounded local JSON outcome report. |
| `--cmdline TEXT` | empty | Append kernel parameters; `nvx_*` and `tsc=` tokens are reserved. |
| `--outcome-report PATH` | none | Write a bounded local JSON outcome report to a new file in an existing plain directory. A cold boot rejects an existing destination before launch and never replaces a file or follows a destination symlink. A missing report or publication failure is diagnosed without replacing OpenVMM's exit status. |
| `--cmdline TEXT` | empty | Append kernel parameters; `nvx_*` and `tsc=` tokens are reserved. Cold boots reject double quotes and a standalone `--` token, which the VM control console cannot represent; snapshot restore retains its existing command-line handling. |
| `--restore-snapshot PATH` | none | Restore the immutable machine contract and saved state from a snapshot directory. A snapshot captured with `--net` needs `--network-profile portable` and the network policy options of its capture, unless `--restore-network-policy` installs a new policy; see [Networked snapshots](run.md#networked-snapshots). |
| `--restore-processors {1,2,4,8}` | none | Bring this contiguous processor prefix online before restore readiness. Requires an opt-in microVM snapshot and cannot exceed `--processors` capacity. |
| `--restore-memory-mib MIB` | none | Select the 128 MiB-aligned RAM target for an expansion-capable snapshot restore, in the range of `--memory-mib`. |
| `--restore-ready-path PATH` | none | Publish one restore-readiness event to an existing Unix socket or Windows named pipe. |
| `--restore-network-policy` | off | Install the policy of the network options, which may include `--network-ingress allow`, explicit `--host-loopback allow`, and forwards, in place of the complete deny-all policy, `--network-egress deny` and `--host-loopback deny` without egress rules, a proxy, or ingress, that the snapshot's NIC was captured with. The guest applies the new policy's DNS server and listener announcements before the host releases its input; see [Networked snapshots](run.md#networked-snapshots). Requires `--restore-snapshot`. |
| `--dry-run` | off | Print the generated OpenVMM command without running it. |

Cold `--mount` targets may not cover, equal, or lie below `/bin`, `/boot`,
`/dev`, `/etc`, `/lib`, `/proc`, `/root`, `/run`, `/sbin`, `/sys`, `/usr`,
`/var`, or `/init`: these paths belong to the guest's blockless system.
For example, use `/config/single.txt` rather than `/etc/single.txt` for a
shared configuration file. Snapshot restore keeps its existing mapping rules.
Cold mount-policy options require a `--mount`, and network-policy options
require networking. A proxy is the guest's sole egress path, so it cannot be
combined with `--network-egress-allow` rules for direct connections.

`nvx-rs run` checks its options, prints the OpenVMM command after `>> `, and
unless `--dry-run` is given, runs OpenVMM with the standard streams. A cold
boot attaches the guest's console, the boot console `hvc1`, to them, so that
Expand Down
17 changes: 15 additions & 2 deletions guest/common/nvx-hostmount
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# virtfs_mode= tokens describe. When virtfs_aggregate=1 marks it as an
# aggregate of host directories and files, its root lists one child per
# directory or file, which only root can enter, and each
# nvx_share=CHILD,TARGET,MODE[,file] token binds one child at TARGET with
# nvx_share=SOURCE,TARGET,MODE[,file] token binds a child or child-relative
# source from the planned export at TARGET with
# MODE, without set-user-ID programs or device nodes; the file suffix marks a
# child that is a host file, which is bound at a file. With --unmount, the
# binds and then the share are unmounted.
Expand Down Expand Up @@ -53,8 +54,20 @@ parse_share() {
esac
share_target=${share_rest%,*}
share_mode=${share_rest##*,}
case "/$share_child/" in
*"//"* | *"/./"* | *"/../"*) fail "invalid live share $1" ;;
esac
case "$share_child" in
'' | . | .. | *[!A-Za-z0-9._-]*) fail "invalid live share $1" ;;
*/*)
share_root=${share_child%%/*}
case "$share_root" in
'' | *[!0-9]*) fail "invalid live share $1" ;;
esac
case "$share_child" in
*\\*) fail "invalid live share $1" ;;
esac
;;
*[!A-Za-z0-9._-]*) fail "invalid live share $1" ;;
esac
case "$share_mode" in ro | rw) ;; *) fail "invalid live share mode in $1" ;; esac
case "$share_target" in /?*) ;; *) fail "invalid live share target in $1" ;; esac
Expand Down
Loading
Loading