Skip to content

openvmm: pin overflow-free memory-expansion ranges - #1423

Merged
Pedro Henrique Penna (ppenna) merged 2 commits into
devfrom
agents/issue-1364-expansion-overflow
Nov 10, 2026
Merged

Pedro Henrique Penna (ppenna) merged 2 commits into
devfrom
agents/issue-1364-expansion-overflow

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1364

What and why

A microVM snapshot that declares a RAM capacity records, in its machine
contract, the canonical memory-expansion ranges: the parts of the capacity's
RAM layout beyond its base RAM, which memory.bin lacks. OpenVMM's
canonical_memory_expansion_ranges (openvmm_helpers/src/snapshot/microvm.rs)
computes them when it builds a contract and when it checks a contract's shape,
as opening a snapshot does. It placed each range at
gpa_start + logical_start - file_offset, so for the capacity's high-RAM
range, at GPA 4 GiB and memory.bin offset 3 GiB, the addition overflowed
whenever the base RAM was at least 2^64 - 4 GiB and below the capacity,
although the result, below the range's end, fits. A debug build panicked with
"attempt to add with overflow", and a release build wrapped back to the right
address. No VM has such RAM, but a crafted manifest can declare it, and opening
that snapshot panicked a debug build before the size check of memory.bin
could refuse it.

microsoft/openvmm#5003, openvmm_helpers: compute memory-expansion ranges without overflow, subtracts first, gpa_start + (logical_start - file_offset). The subtraction cannot underflow, since logical_start is at
least file_offset, and the sum is below the range's end, which
canonical_microvm_memory_ranges has checked fits in a u64. Every range that
the old expression computed without overflowing is unchanged, so release
builds and every RAM size that a VM can have compute the same ranges as
before. Its test, memory_expansion_near_gpa_limit_does_not_overflow, requires
a base RAM of 2^64 - 4 GiB with a capacity of 2^64 - 2 GiB to expand by one
2 GiB range at GPA 2^64 - 3 GiB, the shape check to accept the manifest whose
contract records it, and a restore to the capacity to select it.

Commits:

  • openvmm: pin overflow-free memory-expansion ranges moves the gitlink, and
    nothing else, from b4028c1aa, the head of feature/microvm/dev, to
    ac3dc27a738808d38e1148d3caefc5e89111ee32, the head of
    [DO NOT REVIEW] openvmm_helpers: compute memory-expansion ranges without overflow openvmm#5003, one commit on b4028c1aa. The vectors, source
    excerpts, contract versions, and CPU profiles that nvx-rs copies from
    OpenVMM match the revision's.
  • doc: map the overflow-free memory-expansion ranges in the OpenVMM roadmap
    maps position 236, unassigned, 105 commits past the mapped tip, with the
    mapped work that it changes: the memory-expansion ranges that PR20's
    position 099 adds to the machine contract of PR17's position 074. It
    conflicts with upstream main in its only file, so it follows PR17 and PR20
    upstream.

Decisions:

  • The fix and the test's name are those that the issue proposes, and the
    test's expected values follow the memory layout of
    2.3 Memory Layout.
  • No test builds a contract from a command line at that size: it would need a
    full microVM command line, and the builder calls the same helper.
  • The end-to-end check, a crafted manifest opened as a snapshot, stayed a
    scratch test, since the unit test covers the helper that it reaches.
  • NVX computes no memory-expansion ranges itself, so no NVX code or document
    changes beyond the pin and the roadmap.

ac3dc27a7 is the commit that the validation before this restack tested,
78085e3c6 on 154548a0e, rebased onto b4028c1aa: git range-diff shows
the patch identical.

Stack

This is the bottom of a stack of four drafts, one for each of four issues, each
based on the branch of the one below it; their OpenVMM pull requests stack the
same way.

Layer NVX pull request (base) Issue OpenVMM pull request (base) Pinned OpenVMM revision
1, this one #1423 (dev) #1364 microsoft/openvmm#5003 (feature/microvm/dev) ac3dc27a7, position 236
2 #1424 (agents/issue-1364-expansion-overflow) #1154 microsoft/openvmm#5004 (copilot/nvx-issue-1364-expansion-overflow) cba21d109, position 237
3 #1425 (agents/issue-1154-fifo-artifact) #1138 microsoft/openvmm#5005 (copilot/nvx-issue-1154-fifo-artifact) 46bfe02ed, position 238
4 #1427 (agents/issue-1138-input-gate-lock) #544, part 2 none 46bfe02ed, layer 3's

Landing order, bottom first, one layer at a time; each OpenVMM pull request
lands before its NVX pull request merges:

  1. Land [DO NOT REVIEW] openvmm_helpers: compute memory-expansion ranges without overflow openvmm#5003 by fast-forwarding feature/microvm/dev to
    ac3dc27a738808d38e1148d3caefc5e89111ee32, since OpenVMM's merge button
    squashes and would leave the pin off the branch. Then merge this pull
    request through the merge queue; GitHub deletes its branch and retargets
    openvmm: pin refusing a FIFO snapshot artifact without waiting #1424 to dev.
  2. Retarget [DO NOT REVIEW] openvmm_helpers: refuse a FIFO artifact without waiting for a writer openvmm#5004 to feature/microvm/dev
    (gh pr edit 5004 --repo microsoft/openvmm --base feature/microvm/dev),
    fast-forward feature/microvm/dev to
    cba21d109eeb99fbc573c79b2ed9f4754f734b25, and merge openvmm: pin refusing a FIFO snapshot artifact without waiting #1424.
  3. Retarget [DO NOT REVIEW] vmotherboard: gate a device's input without closing it to the vCPUs openvmm#5005 the same way, fast-forward
    feature/microvm/dev to 46bfe02ed65697e858f66ce55eb60831b3ac3461, and
    merge openvmm: pin input gating that keeps devices open to the vCPUs #1425.
  4. Merge nvx-rs: activate a clone from its restore packet's record #1427, which moves no pin.

Validation

Before this restack, at OpenVMM 78085e3c6 (the same patch on 154548a0e),
and NVX's previous pin 154548a0e for "before":

Check Profile Backend or build Host type Before After
memory_expansion_near_gpa_limit_does_not_overflow local workstation, and a Linux build Windows (MSVC), Linux - panics: "attempt to add with overflow" at microvm.rs:913:24 passes
memory_expansion_near_gpa_limit_does_not_overflow nvx-kvm-test, nvx-mshv-test, nvx-whp-test kvm, mshv, whp virtual machine - passes
Scratch test: open a snapshot whose manifest declares 2^64 - 4 GiB of RAM and a 2^64 - 2 GiB capacity local workstation Windows (MSVC) - panics in OpenedSnapshot::open refused: "memory.bin size (1024 bytes) doesn't match manifest (18446744069414584320 bytes)"
test-microvm --scenario restore-memory, OpenVMM built at the pin nvx-kvm-test, nvx-mshv-test, nvx-whp-test kvm, mshv, whp virtual machine - pass
test-runtime-adapter nvx-kvm-test kvm virtual machine - 158 of 158 pass

openvmm_helpers passed then, 118 tests on Windows and 124 on Linux, with
cargo clippy, cargo doc, and cargo xtask fmt clean.

Rerun for this restack, at OpenVMM ac3dc27a7 and this head:

  • OpenVMM, Rust 1.97.1: cargo nextest run --profile agent -p openvmm_helpers,
    127 passed on Windows and 133 on Linux (nvx-kvm-test, glibc);
    cargo clippy --all-targets -p openvmm_helpers and
    cargo doc --no-deps -p openvmm_helpers, without warnings on both;
    cargo xtask fmt at the stack's top OpenVMM head, 46bfe02ed, clean.
  • NVX: python scripts/nvx.py verify; python scripts/local_gates.py --base origin/dev --only test-changes markdown-links test-layout openvmm-vectors openvmm-cpu-profiles --run, all passed, with no change to an existing test
    and the 4 vector and 1 CPU-profile comparisons passing against ac3dc27a7;
    python scripts/openvmm_pin.py check-roadmap --worktree and
    check-branch --topic --target origin/dev, passed;
    python scripts/rebase_check.py verify, passed after the rebase onto
    dca5af173, nvx-rs: boot templates with an adapter's kernel tuning parameters #1422's merge. The gates ran on nvx-rs: boot templates with an adapter's kernel tuning parameters #1422's head, d48786283,
    whose tree is that merge's, and this head's tree is the one that they tested.

Left for marking ready: the restore-memory scenario on KVM, MSHV, and WHP
with OpenVMM built at ac3dc27a7, the always-selected nvx-cli gate, which this
change cannot affect, and openvmm-ci, which waits for OpenVMM's CI of the pin,
which microsoft/openvmm#5003 gets only once it is ready for review. Left to
CI: the microVM matrix, the other scenarios and processor counts, and
benchmarks. Drafts skip CI.

Pins ac3dc27a738808d38e1148d3caefc5e89111ee32, the head of
microsoft/openvmm#5003, one commit on b4028c1aa, the head of
feature/microvm/dev:

- ac3dc27a7 openvmm_helpers: compute memory-expansion ranges without
  overflow

OpenVMM placed each of a snapshot's canonical memory-expansion ranges by
adding a memory.bin offset to the capacity range's GPA before it
subtracted the range's own offset, so a base RAM of at least
2^64 - 4 GiB overflowed the addition, although the address fits. A
crafted manifest that declares such RAM panicked a debug build of
OpenVMM when it opened the snapshot, in the shape check of the machine
contract, instead of being refused (#1364). The revision subtracts
first. Release builds, which wrapped back to the right address, and
every RAM size that a VM can have compute the same ranges as before.

The vectors, the source excerpts, the contract versions, and the CPU
profiles that nvx-rs copies from OpenVMM match the revision's, as the
openvmm_vectors and openvmm_cpu_profiles comparisons show.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…dmap

Maps NVX's new pin, ac3dc27a7, the head of microsoft/openvmm#5003, at
position 236, after position 235, b4028c1aa, the head of
feature/microvm/dev, which microsoft/openvmm#5001 merged. The pin is
105 commits past the mapped tip, and positions 132-236 stay unassigned.

Position 236 changes how the canonical memory-expansion ranges that
PR20's position 099 adds to the machine contract of PR17's position 074
compute their start: it offsets into the capacity's range before it
adds the range's start, so that a base RAM of at least 2^64 - 4 GiB no
longer overflows the sum. It adds a test beside position 099's tests of
the memory capacity. Replaying it on upstream main conflicts in its
only file, since upstream main lacks the microVM snapshot module of
position 074 and the memory expansion of position 099, so it follows
PR17 and PR20 upstream.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The roadmap leaves position 236 unassigned instead of folding it into PR20’s position 099, making the no-fixups statement, DAG, and PR20 summary/mapping inconsistent.

1 open issue
What changed in this PR

This PR pins OpenVMM’s overflow-free memory-expansion calculation to address #1364, preventing debug-build panics when opening crafted snapshots with extreme RAM sizes.

Changes:

  • Advances the OpenVMM pin to ac3dc27a7, which subtracts before adding and includes a regression test.
  • Updates the upstream roadmap for position 236, its dependencies, and the pin’s distance from the mapped tip.
File Description
doc/​openvmm-upstream-roadmap.md Records the new pin, updates chain counts and the DAG, and describes its relationship to PR17 and PR20.

Review effort: Balanced

| 233 | `d501e5066` | - | - | - | - | microvm: carry a clone's activation record in the restore packet (microsoft/openvmm#4996) |
| 234 | `f41a1ecfc` | - | - | - | - | openvmm_helpers: don't publish a snapshot over an empty directory (microsoft/openvmm#4997) |
| 235 | `b4028c1aa` | - | - | - | - | openvmm_helpers: admit kernel tuning on platform command lines (microsoft/openvmm#5001) |
| 236 | `ac3dc27a7` | - | - | - | - | openvmm_helpers: compute memory-expansion ranges without overflow (microsoft/openvmm#5003) |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

openvmm: memory-expansion range math overflows near the top of the GPA space

2 participants