Repository navigation
[DO NOT REVIEW] openvmm_helpers: compute memory-expansion ranges without overflow - #5003
Merged
Pedro Henrique Penna (ppenna) merged 1 commit intoNov 10, 2026
Conversation
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. canonical_memory_expansion_ranges computes them when OpenVMM 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/nvx#1364). Subtract 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. At feature/microvm/dev 154548a, a scratch test that opens a snapshot whose manifest declares 2^64 - 4 GiB of RAM and a 2^64 - 2 GiB capacity panicked in OpenedSnapshot::open on Windows; with the fix, the open fails with "memory.bin size (1024 bytes) doesn't match manifest (18446744069414584320 bytes)". Tests: a unit test that base RAM of 2^64 - 4 GiB with a capacity of 2^64 - 2 GiB expands by one 2 GiB range at GPA 2^64 - 3 GiB, that the shape check accepts the manifest whose contract records it, and that a restore to the capacity selects it. It panics without the fix on Linux and Windows and passes with it, as do the other openvmm_helpers tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Nov 9, 2026
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>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Nov 9, 2026
…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>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Nov 9, 2026
Pins cba21d109eeb99fbc573c79b2ed9f4754f734b25, the head of microsoft/openvmm#5004, one commit on ac3dc27a7, the head of microsoft/openvmm#5003, on which it stacks, which follows b4028c1aa, the head of feature/microvm/dev: - cba21d109 openvmm_helpers: refuse a FIFO artifact without waiting for a writer A FIFO without a writer in place of a snapshot's manifest.bin, state.bin, memory.bin, or paired scratch.img made restore wait forever before it validated anything (#1154). OpenVMM opened each artifact without following a final link and only then checked the type of the file that it opened, and a read-only open of a FIFO waits until a writer opens it. The pinned revision opens artifacts with O_NONBLOCK on Unix, so it refuses such a FIFO at once, with "<artifact> is not a regular file", before a restore can claim a resume snapshot, and then makes a regular file's descriptor blocking again. Windows is unchanged: its relative opens never wait for a file's type. The protocol vectors, the excerpts and contract versions that nvx-rs copies from OpenVMM, and its CPU profiles match the revision's. With 904a33c32, the same patch on d501e5066, on nvx-kvm-test and nvx-mshv-test (KVM and MSHV virtual machines), a FIFO in place of each artifact of a workload-start and an instance-checkpoint snapshot made the OpenVMM of release v0.1.0-dev.a0173e7b7d97, at 6cb6ba87c, wait in the kernel's wait_for_partner until it was killed 30 s later, while the fix's glibc and musl builds exited with status 1 and that error within 0.01 s; none of the 32 restores claimed the instance checkpoint. On Windows, an AF_UNIX socket, which is a reparse point, in place of each artifact made that release's openvmm.exe refuse it at once, so WHP had no such wait. The snapshot-tiers and scratch-snapshot scenarios passed with it on KVM, MSHV, and WHP. Tests: OpenVMM's openvmm_helpers tests pass at the pinned revision, 135 of 135 on Linux (glibc) and 127 of 127 on Windows, as they did at 904a33c32, 131 of 131 on Linux, glibc and musl, and 123 of 123 on Windows, where the two new ones failed without the change. The openvmm_vectors and openvmm_cpu_profiles comparisons pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Nov 9, 2026
Maps NVX's new pin, cba21d109, the head of microsoft/openvmm#5004, at position 237, after position 236, ac3dc27a7, the head of microsoft/openvmm#5003, on which it stacks, which follows position 235, b4028c1aa, the head of feature/microvm/dev. The pin is 106 commits past the mapped tip, and positions 132-237 stay unassigned. Position 237 changes the artifact openers of the snapshot file system module that PR11's position 032 adds, with the path-based opener and the type check, and its position 033 extends with the directory-relative opener, through which PR12's position 035 restores: on Unix both now open with O_NONBLOCK, so that the type check refuses a FIFO without waiting for a writer, and then make a regular file's descriptor blocking again. It adds tests beside positions 032's and 035's, and extends the restore paragraph that PR12's position 036 adds to the snapshot format guide. Replaying it on upstream main conflicts in all three of its files, since upstream main lacks the file system module of position 032, the directory-relative restore of position 035, and that paragraph, so it follows PR11, PR12, and PR19 upstream. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Nov 9, 2026
A guest's snapshot request could crash a multi-vCPU microVM, or lose the device accesses of its other vCPUs (#1138). The snapshot boundary gates host input before it stops the vCPUs, so they run while each device's state unit changes the device's gate, and the unit held the device's mutex closed for the change, until the end of its wait. A port or MMIO access that another vCPU made then was dropped, a read returning all ones; an interrupt from another device was lost; and an EOI or a PCI configuration access panicked the VM worker with "lock should not be closed". Pin 46bfe02ed65697e858f66ce55eb60831b3ac3461, the head of microsoft/openvmm#5005, one commit on cba21d109, the head of microsoft/openvmm#5004, on which it stacks, which follows ac3dc27a7, the head of microsoft/openvmm#5003, and b4028c1aa, the head of feature/microvm/dev: - 46bfe02ed vmotherboard: gate a device's input without closing it to the vCPUs The revision splits a device's gate change into a synchronous part, which the unit makes under the lock that the vCPUs' accesses take, and a wait that does not borrow the device, which the unit awaits without it. The virtio transports and the remote device proxy send their gate's request in the synchronous part, in the order of the guest's accesses. Evidence: a microVM guest with 2 and 4 vCPUs requested 2000 snapshots, each of which gated host input and then failed its preflight, since its destination existed, while its other vCPUs read the magic value of the virtio-fs device's MMIO window, and with 4 vCPUs the console's too, in a loop. With OpenVMM at d6addf8c1, 145 to 2358 of a run's reads returned all ones, and OpenVMM logged that the device did not respond, in each of 3 runs per count on nvx-kvm-test (KVM), nvx-mshv-test (MSHV), and nvx-whp-test (WHP), all virtual machines; with a91d4c7a4, the same patch on d6addf8c1, no read did. With a91d4c7a4, the default microVM suite passed on all three, with 1, 2, and 4 vCPUs. At the pinned revision, the OpenVMM tests of the changed packages and the virtio devices pass, 545 on Windows and 550 on Linux, as they did at a91d4c7a4. NVX needs no coordinated change: the control-session vectors, the source excerpts, the contract versions, and the CPU profiles that nvx-rs copies from OpenVMM match the revision's. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Nov 9, 2026
Maps NVX's new pin, 46bfe02ed, the head of microsoft/openvmm#5005, at position 238, after position 237, cba21d109, the head of microsoft/openvmm#5004, on which it stacks, which follows positions 236, ac3dc27a7, the head of microsoft/openvmm#5003, and 235, b4028c1aa, the head of feature/microvm/dev. The pin is 107 commits past the mapped tip, and positions 132-238 stay unassigned. Position 238 changes the input gate that PR09's position 018 adds: the chipset device unit, which changed a device's gate with the device's mutex closed, now makes the gate's synchronous part under the device's ordinary lock and awaits the rest without the device, since the vCPUs run through a gate change. It changes the gate's methods of ChangeDeviceState, the erased chipset devices, and the remote device proxy, which position 018 adds, and the virtio transports' forwarding of the gate, which PR13's position 040 adds, and adds tests of the unit, both virtio transports, and the proxy. Replaying it on upstream main conflicts in all eight of the files that it changes, since upstream main lacks the input gate of position 018 and its forwarding by position 040, so it follows PR09 and PR13 upstream. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Nov 9, 2026
Pedro Henrique Penna (ppenna)
marked this pull request as ready for review
November 9, 2026 23:26
Pedro Henrique Penna (ppenna)
merged commit Nov 10, 2026
ac3dc27
into
feature/microvm/dev
144 checks passed
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.
Makes a microVM snapshot's canonical memory-expansion ranges compute without overflowing near the top of the guest-physical address space, for microsoft/nvx#1364. A manifest that declares a base RAM of at least 2^64 - 4 GiB below a larger RAM capacity overflowed an addition when OpenVMM built or checked its machine contract, so opening such a crafted snapshot panicked a debug build with "attempt to add with overflow" before the size check of
memory.bincould refuse it. No VM has such RAM, but a manifest can declare it.One commit on
b4028c1aa, the head offeature/microvm/dev. microsoft/nvx#1423 pins this head. It is a draft, at the bottom of a stack of three; see Stack.Compute memory-expansion ranges without overflow (
ac3dc27a7)canonical_memory_expansion_rangescomputes the parts of the capacity's RAM layout beyond the base RAM, whichmemory.binlacks, when OpenVMM builds a contract and when it checks a contract's shape, as opening a snapshot does. It placed each range atgpa_start + logical_start - file_offset, so for the capacity's high-RAM range, at GPA 4 GiB andmemory.binoffset 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, and a release build wrapped back to the right address.gpa_start + (logical_start - file_offset). The subtraction cannot underflow, sincelogical_startis at leastfile_offset, and the sum is below the range's end, whichcanonical_microvm_memory_rangeshas checked fits in au64. Every range that the old expression computed without overflowing is unchanged.memory_expansion_near_gpa_limit_does_not_overflowrequires 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 values that NVX's memory-layout design (doc/design/2.3-memory-layout.md) gives, the shape check to accept the manifest whose contract records it, and a restore to the capacity to select it. Without the fix, it panics with "attempt to add with overflow" atmicrovm.rs:913:24, on Windows and Linux. A contract-builder test would need a full command line and reaches the same helper, so there is none.Validation
At this head,
ac3dc27a7, with Rust 1.97.1. It is the commit that NVX's phase-1 validation tested,78085e3c6on154548a0e, rebased ontob4028c1aa;git range-diffshows the patch identical.cargo nextest run --profile agent -p openvmm_helpers, 127 passed;cargo clippy --all-targets -p openvmm_helpersandcargo doc --no-deps -p openvmm_helpers, without warnings.cargo xtask fmtat the head of the stack, which holds this commit's file as it is here, clean.At
78085e3c6:openvmm_helperspassed, 118 tests on Windows and 124 on Linux;cargo clippy,cargo doc, andcargo xtask fmtwere clean.OpenedSnapshot::openon Windows without the fix, and with it failed with "memory.bin size (1024 bytes) doesn't match manifest (18446744069414584320 bytes)".restore-memoryscenario passed on its KVM, MSHV, and WHP test VMs with OpenVMM built from it, and NVX's runtime-adapter suite passed, 158 of 158, on KVM.Stack
Three drafts, one for each of three microsoft/nvx issues, each based on the branch of the one before it:
feature/microvm/dev.NVX pins each one's head in its own draft, stacked the same way: microsoft/nvx#1423, microsoft/nvx#1424, and microsoft/nvx#1425, in this order, with microsoft/nvx#1427, part 2 of microsoft/nvx#544, which moves no pin, on top.
This one lands first, by fast-forwarding
feature/microvm/devto this head,ac3dc27a738808d38e1148d3caefc5e89111ee32, since this repository's merge button squashes and would leave NVX's pin off the branch. The next one then has its base retargeted tofeature/microvm/devand lands the same way, at its exact head.