Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions .github/actions/check-nvx-rs/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,22 @@ runs:
rustup target add --toolchain "${{ steps.toolchains.outputs.toolchain }}" aarch64-apple-darwin
cargo "+${{ steps.toolchains.outputs.toolchain }}" check --locked --all-targets --all-features \
--target aarch64-apple-darwin

# The guest binaries are static x86_64-unknown-linux-musl executables; see the README's
# guest binaries section. This step also adds the musl target that the build step needs.
- name: Lint and test the guest binaries
if: runner.os == 'Linux'
shell: bash
run: >-
python3 scripts/nvx.py check-guest-binaries
--toolchain "${{ steps.toolchains.outputs.toolchain }}"

- name: Build and check the guest binaries
if: runner.os == 'Linux'
shell: bash
working-directory: nvx-rs
run: |
set -euo pipefail
directory="${PWD}/../build/nvx-rs-guest-binaries"
python3 ../scripts/nvx.py build-guest-binaries --output "${directory}"
python3 ../scripts/nvx.py test-guest-binaries --binaries "${directory}"
4 changes: 2 additions & 2 deletions .github/actions/validate-nvx/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ runs:
run: |
set -euo pipefail
python3 -m compileall -q scripts
python3 -m unittest scripts/test_performance.py scripts/test_nvx_tools.py scripts/test_microvm_tests.py scripts/test_development_release.py scripts/test_egress_policy.py scripts/test_control_session.py scripts/test_managed_agent.py scripts/test_guest_time.py scripts/test_guest_ingress.py scripts/test_host_telemetry.py scripts/test_time_abi.py scripts/test_tool_versions.py -v
python3 -m unittest scripts/test_performance.py scripts/test_nvx_tools.py scripts/test_guest_binaries.py scripts/test_microvm_tests.py scripts/test_development_release.py scripts/test_egress_policy.py scripts/test_control_session.py scripts/test_managed_agent.py scripts/test_guest_time.py scripts/test_guest_ingress.py scripts/test_host_telemetry.py scripts/test_time_abi.py scripts/test_tool_versions.py -v
python3 scripts/test_adversarial.py -v
python3 .github/skills/nvx-host-connect/scripts/test_hosts.py -v
python3 scripts/nvx.py --help
Expand All @@ -29,7 +29,7 @@ runs:
$ErrorActionPreference = "Stop"
python -m compileall -q scripts
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
python -m unittest scripts/test_performance.py scripts/test_nvx_tools.py scripts/test_microvm_tests.py scripts/test_development_release.py scripts/test_egress_policy.py scripts/test_control_session.py scripts/test_managed_agent.py scripts/test_guest_time.py scripts/test_guest_ingress.py scripts/test_host_telemetry.py scripts/test_time_abi.py scripts/test_tool_versions.py -v
python -m unittest scripts/test_performance.py scripts/test_nvx_tools.py scripts/test_guest_binaries.py scripts/test_microvm_tests.py scripts/test_development_release.py scripts/test_egress_policy.py scripts/test_control_session.py scripts/test_managed_agent.py scripts/test_guest_time.py scripts/test_guest_ingress.py scripts/test_host_telemetry.py scripts/test_time_abi.py scripts/test_tool_versions.py -v
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
python scripts\test_adversarial.py -v
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Expand Down
11 changes: 11 additions & 0 deletions doc/ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,17 @@ validates bundled artifact staging with a fixture package. Both actions set
`NVX_BUNDLE=skip` for `--all-features` builds, so that `bundled` stages nothing
instead of downloading the pinned release.

On Linux, the `nvx-rs` job also lints and tests the
[guest binaries](../nvx-rs/README.md#guest-binaries) for
`x86_64-unknown-linux-musl`, the target that guests run, and builds them with
the `guest` profile. The action delegates the musl lint and tests to
[`nvx.py check-guest-binaries`](usage.md#check-guest-binaries), the fresh,
path-remapped build, static-ELF check, and digest manifest to
[`nvx.py build-guest-binaries`](usage.md#build-guest-binaries),
and the prebuilt-binary integration run to
`nvx.py test-guest-binaries`. The guests ship the C programs in
`guest/common/` until their build switches to these binaries.

The development release job depends on `aci-edge-sandboxes` and `nvx-rs` and
requires their combined Linux/Windows results to be successful; failed,
cancelled, or skipped crate checks cannot publish a release.
Expand Down
2 changes: 1 addition & 1 deletion doc/contribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ the Python and shell checks.
| Guest and setup shell scripts | ShellCheck, and shfmt with four-space indentation and indented `case` branches. Scripts are POSIX `sh` unless check-quality checks them as Bash. | [check-quality](../.github/actions/check-quality/action.yml) |
| `scripts/setup/setup-windows-whp.ps1` | PowerShell syntax | [check-quality](../.github/actions/check-quality/action.yml) |
| `aci_edge_sandboxes/` | rustfmt, Clippy and rustdoc with warnings denied, tests, and the minimum supported Rust version; see [Rust crates](ci.md#rust-crates) | [check-aci-edge-sandboxes](../.github/actions/check-aci-edge-sandboxes/action.yml) |
| `nvx-rs/` | rustfmt, Clippy and rustdoc with warnings denied, tests including a bundled-release fixture, the minimum supported Rust version, and a macOS check; see [Rust crates](ci.md#rust-crates) | [check-nvx-rs](../.github/actions/check-nvx-rs/action.yml) |
| `nvx-rs/` | rustfmt, Clippy and rustdoc with warnings denied, tests including a bundled-release fixture, the minimum supported Rust version, a macOS check, and, through `nvx.py`, the musl lint, tests, build, digest manifest, and static-ELF check of the guest binaries; see [Rust crates](ci.md#rust-crates) | [check-nvx-rs](../.github/actions/check-nvx-rs/action.yml) |
| NVX CLI | Compiles `scripts/`, runs every `scripts/test_*.py` module, and checks command help, on Linux and Windows | [validate-nvx](../.github/actions/validate-nvx/action.yml) |

check-quality names each shell script that it checks, and a CLI test fails
Expand Down
10 changes: 7 additions & 3 deletions doc/project-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ nvx/
| | |-- net/ CIDR parsing and subtraction, and hostname and guest-network forms
| | |-- host/ Artifacts, launch, policy lowering, sessions, and VM instances
| | |-- testing/ Fake OpenVMM (feature `testing`)
| | `-- bin/ nvx-fake-openvmm test double
| |-- tests/ Fake-OpenVMM instance lifecycle tests
| | |-- guest/ Programs that run in Linux guests (feature `guest`)
| | `-- bin/ nvx-fake-openvmm test double and the guest binaries
| |-- tests/ Fake-OpenVMM instance lifecycle and guest-binary tests
| |-- build.rs Stages the bundled artifacts (feature `bundled`)
| `-- artifacts.json Release package pinned for the bundled artifacts
|-- openvmm/ OpenVMM Git submodule
Expand Down Expand Up @@ -132,6 +133,7 @@ nvx/
| | |-- development_release.py Resumable development release publication
| | |-- doctor.py Time ABI host qualification
| | |-- egress_policy.py Egress policy compiler for OpenVMM's rule grammar
| | |-- elf.py Static-executable check of ELF binaries
| | |-- guests.py Typed guest descriptors
| | |-- host_telemetry.py Benchmark host provenance and Windows capture storage telemetry
| | |-- host_time_probe.rs Host TSC probe that doctor builds and runs
Expand Down Expand Up @@ -266,7 +268,9 @@ The Rust crate `nvx-rs`, whose library `nvx` holds the NVX mechanics: the
authenticated control protocol of the guest agent, artifact discovery and
bundled-release staging, OpenVMM's command line, the lowering of network and
filesystem policies, process and platform primitives for Linux and Windows
hosts, the supervision of VM instances, and a fake OpenVMM for tests. It is a
hosts, the supervision of VM instances, and a fake OpenVMM for tests. Its
`guest` feature adds the programs that will replace the C programs of
`guest/common/`, built as static musl executables. It is a
standalone crate with its own `Cargo.lock`, like `aci_edge_sandboxes`, and
builds independently of the OpenVMM submodule. See its
[README](../nvx-rs/README.md).
Expand Down
55 changes: 55 additions & 0 deletions doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ python3 scripts/nvx.py performance gate --help
| --- | --- |
| `init` | Initialize the OpenVMM submodule and its nested submodules. |
| `build-guest` | Build the Linux kernel and selected guest artifacts. |
| `check-guest-binaries` | Lint and test the Rust guest executables for musl. |
| `build-guest-binaries` | Build and digest the pinned Rust executables for Linux guests. |
| `test-guest-binaries` | Run the musl integration tests against prebuilt Rust guest executables. |
| `build-kernel` | Build the pinned and patched Linux kernel natively. |
| `build-initramfs` | Build the selected Alpine, Ubuntu, or Azure Linux initramfs. |
| `build-distro-layer` | Build a deterministic Ubuntu EROFS distro layer. |
Expand All @@ -34,6 +37,7 @@ python3 scripts/nvx.py performance gate --help
| `setup-cross-os-cache` | Install GNU tar and zstd for GitHub Actions cross-OS caches. |
| `classify-ci-changes` | Select the CI suites that a list of changed files runs. |
| `check-required-ci` | Validate required GitHub Actions job results. |
| `check-static-elf` | Check that executables are static ELF files without an interpreter. |
| `test-openvmm-unit` | Run the OpenVMM workspace unit and documentation tests. |
| `test-openvmm` | Run OpenVMM Petri VMM tests. |
| `test-microvm` | Run NVX Linux and device correctness tests through OpenVMM. |
Expand Down Expand Up @@ -121,6 +125,57 @@ variables. CI supplies the `true` or `false` suite flags that
enabled by the event, repository, and suite flags, and `skipped` for jobs that
are not enabled; mismatches are reported as errors and cause a nonzero exit.

### `check-static-elf`

```text
python3 scripts/nvx.py check-static-elf PATH [PATH ...]
```

Prints each executable's ELF type, size, and linkage, and fails unless every
one is a 64-bit little-endian ELF executable without a program interpreter
(`PT_INTERP`) or needed libraries (`DT_NEEDED`), so that it runs in a guest
without a dynamic loader. A static position-independent executable passes. The
`nvx-rs` CI job checks the [guest binaries](../nvx-rs/README.md#guest-binaries)
with it.

### `check-guest-binaries`

```text
python3 scripts/nvx.py check-guest-binaries [--toolchain TOOLCHAIN]
```

The Linux-only check command adds the `x86_64-unknown-linux-musl` target to the
Rust toolchain that `--toolchain` names, by default the exact
`rust-toolchain.toml` pin. It then runs Clippy with warnings denied on every
target of the `guest` feature, and the feature's musl tests, whose static test
executables run on the host. It ignores an inherited `NVX_GUEST_BINARIES`, so
that the integration tests run the binaries that Cargo builds from the
checkout. The `nvx-rs` CI job runs it with the toolchain that its action
selects, before it builds the binaries.

### `build-guest-binaries`

```text
python3 scripts/nvx.py build-guest-binaries --output DIRECTORY
```

The Linux-only build command checks the exact `rust-toolchain.toml` pin and
builds the six PR 1 guest executables for `x86_64-unknown-linux-musl` with one
`cargo build` of the `guest` profile, a fresh target directory, Cargo's locked
mode, incremental compilation disabled, inherited Cargo profile overrides
removed, remapped source paths, and no linker build IDs. It runs the static-ELF
check and writes `manifest.json` with the source and executable SHA-256 digests.

### `test-guest-binaries`

```text
python3 scripts/nvx.py test-guest-binaries --binaries DIRECTORY
```

The Linux-only test command validates the six binaries and build manifest,
sets `NVX_GUEST_BINARIES`, and runs the musl `guest_tools` integration test
against that exact directory.

See [Setup](setup.md) for host prerequisites.

### `materialize-kernel-provenance-inputs`
Expand Down
35 changes: 35 additions & 0 deletions nvx-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 78 additions & 0 deletions nvx-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ bundled = ["host", "dep:sha2"]
testing = ["dep:getrandom", "dep:serde", "dep:serde_json", "dep:libc", "dep:windows-sys"]
# The serde form of `Hypervisor`. The `host` feature enables it.
serde = ["dep:serde"]
# The programs that run in Linux guests: the `guest` module and the `nvx-*` guest binaries. Build
# them with `--no-default-features --features guest` and the `guest` profile; see README.md.
guest = ["dep:nix", "dep:getrandom"]

[dependencies]
getrandom = { version = "0.4", optional = true }
Expand All @@ -49,6 +52,24 @@ windows-sys = { version = "0.61", optional = true, features = [
"Win32_System_Threading",
] }

[target.'cfg(target_os = "linux")'.dependencies]
nix = { version = "0.31.3", default-features = false, optional = true, features = [
"fs",
"ioctl",
"mman",
"mount",
"net",
"poll",
"process",
"sched",
"signal",
"socket",
"term",
"time",
"uio",
"user",
] }

[build-dependencies]
# Only the `bundled` build script reads JSON; `host`, which `bundled` enables, enables it here too.
serde_json = { version = "1.0.120", optional = true }
Expand All @@ -64,7 +85,64 @@ path = "src/bin/nvx-fake-openvmm.rs"
required-features = ["testing"]
doc = false

# The guest binaries. Their unit tests live in the library, so the binaries have no test harness.
[[bin]]
name = "nvx-console-pending"
path = "src/bin/nvx-console-pending.rs"
required-features = ["guest"]
doc = false
test = false

[[bin]]
name = "nvx-mmio-write"
path = "src/bin/nvx-mmio-write.rs"
required-features = ["guest"]
doc = false
test = false

[[bin]]
name = "nvx-port-io"
path = "src/bin/nvx-port-io.rs"
required-features = ["guest"]
doc = false
test = false

[[bin]]
name = "nvx-reseed"
path = "src/bin/nvx-reseed.rs"
required-features = ["guest"]
doc = false
test = false

[[bin]]
name = "nvx-exit"
path = "src/bin/nvx-exit.rs"
required-features = ["guest"]
doc = false
test = false

[[bin]]
name = "nvx-device-io"
path = "src/bin/nvx-device-io.rs"
required-features = ["guest"]
doc = false
test = false

# The guest binaries: small, static, and stripped.
[profile.guest]
inherits = "release"
opt-level = "s"
lto = "fat"
codegen-units = 1
panic = "abort"
strip = true
debug = false
incremental = false

[lints.rust]
missing_docs = "warn"
unsafe_op_in_unsafe_fn = "deny"
unreachable_pub = "warn"

[lints.clippy]
missing_docs_in_private_items = "warn"
Loading
Loading