Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
11b430d
host: reconcile verified stop outcomes onto feature
Nov 10, 2026
99d0045
host: journal CLI launches and persist saved VM records
Nov 10, 2026
1cb779e
guest: serve snapshot capture requests from init
Nov 10, 2026
dc669fa
tests: keep adapter sandbox names short below data roots
Nov 10, 2026
adeb1d4
tests: format the compact sandbox creation diagnostic
Nov 10, 2026
13bbbc8
host: verify CLI launch liveness from its log and endpoint
Nov 10, 2026
92ac710
host: reconcile recorded process opening onto qualified stop
Nov 10, 2026
8752816
guest: retain restored ingress as an init helper
Nov 10, 2026
688db9f
cli: run cold blockless VMs through the verified lifecycle
Nov 10, 2026
72e3bd5
docs: document CLI foreground child ownership
Nov 10, 2026
9785ad4
Merge qualified VM reattach input into CLI launch liveness
Nov 10, 2026
b134e70
integration: adapt CLI liveness to qualified process opening proofs
Nov 10, 2026
cc4ded0
cli: recover interrupted launches under the sandbox lock
Nov 10, 2026
573f0ba
guest: activate repaired init sessions
Nov 10, 2026
93bd4d5
cli: preserve unrecorded run artifacts and planned-share runtime cove…
Nov 10, 2026
356eb21
style: format planned-share scenario export mode
Nov 10, 2026
8921c45
test: reconnect the owned Windows recovery control fixture
Nov 10, 2026
67bb715
test: align download cleanup with restored cold-run fixtures
Nov 10, 2026
206b3f1
test(nvx-rs): exercise restored init with native readiness
Nov 10, 2026
df508ad
cli: run cold blockless VMs through the verified lifecycle
Nov 10, 2026
b08649d
docs: document CLI foreground child ownership
Nov 10, 2026
8268f52
cli: preserve unrecorded run artifacts and planned-share runtime cove…
Nov 10, 2026
570b331
style: format planned-share scenario export mode
Nov 10, 2026
46adcc1
test: align download cleanup with restored cold-run fixtures
Nov 10, 2026
9ff7907
cli: address foreground connection, output, and report findings
Nov 10, 2026
773403c
cli: stream lossy UTF-8 only to Windows consoles
Nov 10, 2026
9b81347
test: scope unsafe console calls to the isolated Windows helper
Nov 10, 2026
6bc5c0a
test: initialize boot capacity in the integrated launch fixture
Nov 10, 2026
d56d3d3
guest: route new sandbox boots through nvx-init
Nov 10, 2026
ea86726
Merge published feature input for SL3.5b integration
Nov 10, 2026
8b66cc4
Merge published SL3.3b recovery input
Nov 10, 2026
3984b7d
Merge published SL3.4a2 CLI launch input
Nov 10, 2026
2e26738
Retain the published init test seam count after joining inputs
Nov 10, 2026
e484329
Reconcile joined test fixtures with current VM and process APIs
Nov 10, 2026
928edaa
Merge the now-published SL3.4a2 producer fix once
Nov 10, 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
30 changes: 27 additions & 3 deletions guest/common/init
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ case "$cmdline" in
*" nvx_sandbox=1 "*) sandbox_mode=true ;;
*) sandbox_mode=false ;;
esac
new_init=false
if [ "$sandbox_mode" = true ]; then
case "$cmdline" in
*" nvx_lifecycle="*) ;;
*) new_init=true ;;
esac
fi

fatal() {
echo "$*" >&2
Expand Down Expand Up @@ -189,7 +196,7 @@ for token in $cmdline; do
esac
done
set +f
if [ -n "$nvx_exec" ]; then
if [ -n "$nvx_exec" ] && [ "$new_init" = false ]; then
case "$nvx_exec" in
/*) ;;
*) fatal "nvx_exec must be an absolute initramfs path" ;;
Expand All @@ -206,6 +213,7 @@ if [ "$sandbox_mode" = false ]; then
mount_virtfs
fi
# virt-net: if --net attached a NIC, configure the only non-loopback interface.
announcer_pid=
nip=$(sed -n 's/.*virtnet_ip=\([^ ]*\).*/\1/p' /proc/cmdline)
if [ -n "$nip" ]; then
nmask=$(sed -n 's/.*virtnet_mask=\([^ ]*\).*/\1/p' /proc/cmdline)
Expand Down Expand Up @@ -289,6 +297,7 @@ if [ -n "$nip" ]; then
allow | host-loopback)
if [ -n "$ngw" ] && [ -x /sbin/nvx-ingress ]; then
/sbin/nvx-ingress "$ngw" </dev/null &
announcer_pid=$!
else
virtnet_error "$ningress ingress needs /sbin/nvx-ingress and an IPv4 gateway"
fi
Expand All @@ -308,9 +317,24 @@ if [ -n "$nip" ]; then
fi
fi
if [ "$sandbox_mode" = true ]; then
[ -x /sbin/nvx-init-agent ] ||
if [ "$new_init" = false ]; then
[ -x /sbin/nvx-init-agent ] ||
workload_fatal "selected guest cannot act as sandbox control"
exec /sbin/nvx-init-agent
fi
[ -x /sbin/nvx-init ] ||
workload_fatal "selected guest cannot act as sandbox control"
exec /sbin/nvx-init-agent
# nvx-time boot returns before its child publishes the daemon PID.
tries=0
while [ ! -r /run/nvx/time/daemon.pid ] && [ "$tries" -lt 600 ]; do
sleep 0.05
tries=$((tries + 1))
done
time_daemon=$(cat /run/nvx/time/daemon.pid) ||
workload_fatal "time daemon process ID is unavailable"
set -- "$time_daemon"
[ -z "$announcer_pid" ] || set -- "$@" "$announcer_pid"
exec /sbin/nvx-init "$@"
fi
case "$workload_lifecycle" in
one-shot)
Expand Down
Loading
Loading