Disallow MSR read/writes#991
Draft
ludfjig wants to merge 11 commits into
Draft
Conversation
aeca04d to
968f2f4
Compare
e859ff9 to
e793129
Compare
8f55249 to
3bb2294
Compare
032168d to
c0383dd
Compare
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Design doc for resetting guest-written MSRs across MultiUseSandbox::restore() with a per-MSR opt-in allow list, plus a KVM Phase 1 implementation handoff brief. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Reset the guest-visible stateful MSRs on sandbox restore and gate the per-MSR allow list behind validation, so guest MSR writes cannot leak across restores. Adds host-index sweep, negative-leak, denied-MSR fault, and partial-set poison tests, plus documentation of the reset-set completeness argument and the dormant host_specific/TSC machinery. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Handoff for the mshv agent: the pass-through completeness gap, the Hyper-V/mshv source facts (SVM pass-through MSR set, intercept behavior) the agent cannot see, and the reset-or-mask plan per MSR class. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Widen the KVM-only MSR reset machinery to also cover the mshv backend, so guest MSR writes do not leak across a snapshot restore on Hyper-V. Implement capture_msrs/apply_msrs on MshvVm using batched get_msrs/set_msrs, detecting failure from the returned error (set_msrs reports no count) and poisoning on a partial apply. mshv has no per-MSR deny filter, so a guest can write architectural pass-through MSRs with no intercept, and completeness rests on reset. The reset set covers every stateful pass-through MSR the crate can map and restore: the core syscall, sysenter, and base MSRs, KERNEL_GS_BASE, SPEC_CTRL, and the CET MSRs where CET is active. mshv has no host-probed index list, so the reset set is resolved by probing each mappable index with a get at init, including only those that read back. That resets CET on hosts where it is exposed and skips it elsewhere without failing init. The allow list is validated at VM creation so a non-resettable or unmappable request is a hard error. The pass-through classes with no mapping (PMU, AMX/XFD, FRED, arch LBR) cannot be reset. Completeness holds because the minimal partition enables none of them, so a guest access faults. A test asserts this on the host. Add mshv tests: a pass-through MSR write is reset across restore, a guest read of an unresettable class faults, a rejected set_msrs during restore poisons the sandbox, an allowed MSR does not leak across restore, and allowing a non-resettable or unmapped MSR fails sandbox creation. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Implement MSR reset for the Windows Hypervisor Platform backend, matching the KVM and mshv phases. WHP models MSRs as named registers (no index list), so capture_msrs/apply_msrs map indices to WHV_REGISTER_NAME values. WHP has no usable per-MSR deny filter: the Hyper-V hypervisor refuses to intercept an MSR it implements (WHvSetupPartition rejects MsrActionList/UnimplementedMsrAction; the X64MsrExitBitmap UnhandledMsrs bit only traps already-faulting MSRs). Isolation therefore relies on reset, so the reset set must cover every guest-writable, retained MSR by construction. An audit of every WHP-exposable MSR found real cross-restore leaks not covered by the core reset set: the MTRR family, TSC_ADJUST, and TSC_AUX. Add these to the shared MSR table so both WHP and mshv (both filterless) reset them; the change is a no-op on KVM (guest writes are denied by the filter) and per-backend host-support probes drop unsupported indices. Raw TSC is not reset (it free-runs); a direct WRMSR(TSC) is rolled back via TSC_ADJUST. Also gate the guest ReadMSR/WriteMSR functions to x86_64 and remove redundant target_arch gates from the already-arch-gated hyperlight_vm/x86_64.rs. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Record the WHP MSR-reset implementation, the source-proven finding that Hyper-V cannot intercept an implemented MSR, and the cross-restore leak audit. Flags the remaining Linux validation of the shared MSR-table change on KVM and mshv. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
The WHP MSR reset commit added MTRR and TSC_ADJUST/TSC_AUX to the shared reset table and widened the MSR access-control VM exits to all of x86_64. On an mshv-only Linux build those exits are never constructed, since only KVM and WHP produce them, which fails the build under deny-warnings. Gate VmExit::MsrRead/MsrWrite, the RunVmError violation variants, the run-loop arms, and the error mapping to the backends that construct them (KVM and Windows). Add an mshv leak sweep over the MTRR and TSC MSRs the shared table added. mshv has no per-MSR deny filter, so each is guest-unreachable, masked, or retained. A retained MSR must roll back on restore. The test asserts no value leaks across a restore whichever path the host takes. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
The reset set on WHP and mshv (both filterless) must cover every guest-writable, retained MSR by construction, so add tests that push toward that guarantee instead of spot-checking a handful. test_whp_unresettable_msr_classes_do_not_retain asserts the classes the completeness argument depends on (PMU, AMX, FRED, LBR, masked DEBUGCTL) never retain a guest write. test_whp_no_msr_leaks_across_restore_broad_sweep and its mshv3-gated counterpart sweep ~60 architectural MSRs and require that no guest-written value survives a restore, whatever the host does (fault, mask, or retain-and-reset). The mshv sweep still needs to be run on a real mshv host. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
The no-leak invariant is identical on all backends, but three test families were triplicated per backend (test_{kvm,mshv,whp}_*) with near-identical bodies. Since the CI matrix runs each backend on its own runner, an agnostic test gated only by target_arch (or, for the deny-filter-only sweep, by the filterless backends) and skipped at runtime via get_available_hypervisor().is_none() gives all backends identical coverage from one source.
Consolidate the allow-non-resettable-fails, allowed-msr-no-leak, and broad no-leak sweep families into single shared tests and drop the per-backend copies. Genuinely backend-specific tests (KVM deny-filter poison, KVM host-index-list sweep, mshv unmapped/partial-set, WHP named-register reset) stay as they are. Validated on WHP; KVM and mshv confirm via their CI runners.
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
restore() clears the poisoned flag and works on a poisoned sandbox, so a faulting or filter-denied MSR access is recovered by restoring the pre-access snapshot instead of building a fresh VM. This is much cheaper (the sweep no longer recreates ~60 sandboxes) and removes the reason the sweep was gated off KVM. Ungate the broad sweep to target_arch = x86_64 so it runs on every backend in the CI matrix. On KVM the deny filter intercepts every non-allowed MSR access, so the sweep self-skips there (KVM's coverage is the host-index-list sweep plus the deny tests); on the filterless backends (mshv, WHP) it is the meaningful completeness sweep. Apply the same restore-reuse to the WHP unresettable-classes test. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
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.
Disallows reading/writing MSRs in the guest. Can be bypassed with unsafe function on SandboxConfiguration. The goal is to prevent guest state to persist across snapshot-restores.
Will mark ready for review once KVM releases new version, which should include newly added
KVM_X86_SET_MSR_FILTERvm ioctl that this PR depends on, see rust-vmm/kvm#359