Re: [PATCH] KVM: nVMX: Re-arm the vmcs12 pages request if mapping the pages fails
Jinwoo Lee <[email protected]>
| Newsgroups | dev.linux.lists.sashiko-reviews,org.kernel.vger.kvm,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <CALz4YMQa4h0oHxrpsiFsPd2qWZO1Q-pE2mbDwvT2wV1b+ukZdg@mail.gmail.com> |
Resending as plain text; the previous copy was rejected by [email protected] because Gmail included an HTML MIME part. Sorry for the duplicate on lists that received the first copy. --- Thanks for the review. > This is a pre-existing issue, but should the same re-arm be applied to > vmx_get_nested_state_pages() and svm_get_nested_state_pages()? At the request-lifetime level, yes. kvm_check_request() consumes KVM_REQ_GET_NESTED_STATE_PAGES before get_nested_state_pages() is called. If the callback returns false, the request needs to remain pending; otherwise a later KVM_RUN can skip the deferred setup. On further inspection, re-arming the request in nested_get_vmcs12_pages() is too low-level. That helper is also called directly from the normal nested VM-Entry path, before enter_guest_mode(), and that caller switches back to vmcs01 if the helper fails. I will move the retry to the KVM_REQ_GET_NESTED_STATE_PAGES consumption path in vcpu_enter_guest(), or to an equivalent wrapper, so that the request is re-armed only after it was actually consumed. That will also cover failures returned by both the VMX and SVM get_nested_state_pages() callbacks. The eVMCS path needs additional handling beyond a generic re-arm. nested_vmx_handle_enlightened_vmptrld() releases the old eVMCS mapping before attempting to map the new GPA. If kvm_vcpu_map() fails, hv_evmcs_vmptr is left as EVMPTR_INVALID, whereas nested_get_evmcs_page() retries the mapping only when hv_evmcs_vmptr is EVMPTR_MAP_PENDING. Re-arming the request alone would therefore not necessarily retry the failed eVMCS mapping. I will preserve or restore a retryable eVMCS state on that failure path in v2. For SVM, I agree that failures in load_pdptrs(), nested_svm_merge_msrpm(), and kvm_hv_verify_vp_assist() can lose the consumed request, and that L2 must not resume until the deferred setup has completed successfully. However, I do not currently see evidence that the SVM failures have the same unpinned-HPA/UAF mechanism as the nVMX APIC-backed VMCS02 fields. In particular, nested_vmcb02_prepare_control() initially copies vmcb01's KVM-owned MSRPM address into vmcb02, and nested_svm_merge_msrpm() switches vmcb02 to the KVM-owned merged MSRPM only after the merge completes successfully. Losing the request after a failed merge can therefore allow L2 to run without L1's complete MSR intercept state, but it does not appear to leave hardware pointing at an unpinned guest page. I will describe and test the SVM impact separately instead of treating it as the same UAF without supporting evidence. > Does this allow L2 to resume with unpinned HPAs and lead to a > use-after-free? Not uniformly across these paths. The unpinned-HPA mechanism is the concern for the nVMX VMCS02 address fields described in the patch, but I have not yet reproduced host-page reuse or an actual use-after-free end to end. For eVMCS and SVM, the current evidence establishes that the deferred setup request can be lost; it does not yet establish the same unpinned-HPA mechanism. I will also correct the commit message. Not every failure reports KVM_EXIT_INTERNAL_ERROR: the load_pdptrs() failure used by my RSM reproducer returns with exit_reason unchanged, which is KVM_EXIT_UNKNOWN in the test. I will rework the patch and selftest accordingly and runtime-test the fix before posting v2. Thanks, Jinwoo On Thu, Aug 13, 2026 at 1:57 PM <[email protected]> wrote: > > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: > > Pre-existing issues: > - [High] The patch fixes the missing re-arming of `KVM_REQ_GET_NESTED_STATE_PAGES` in `nested_get_vmcs12_pages()` for VMX but overlooks identical vulnerabilities in `vmx_get_nested_state_pages()` (VMX eVMCS) and `svm_get_nested_state_pages()` (SVM). > -- > > --- Patch [1]: [PATCH] KVM: nVMX: Re-arm the vmcs12 pages request if mapping the pages fails --- > commit ce93ee9654c7f639f51372bb8a7e1b25a376436b > Author: Jinwoo Lee <[email protected]> > > KVM: nVMX: Re-arm the vmcs12 pages request if mapping the pages fails > > This commit ensures KVM_REQ_GET_NESTED_STATE_PAGES is re-armed if > nested_get_vmcs12_pages() fails to map the pages. This forces KVM to retry the > mapping on the next KVM_RUN rather than resuming L2 with a stale vmcs02, which > prevents hardware from accessing unpinned host physical pages. > > > diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c > > index ddf6df7bee93b..9e9bd6c541baa 100644 > > --- a/arch/x86/kvm/vmx/nested.c > > +++ b/arch/x86/kvm/vmx/nested.c > [ ... ] > > @@ -3525,6 +3525,20 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu) > > exec_controls_clearbit(vmx, CPU_BASED_USE_MSR_BITMAPS); > > > > return true; > > + > > +fail: > > + /* > > + * Re-arm the request so that KVM retries the mapping instead of running > > + * L2 with a stale vmcs02. Bailing here leaves the vCPU in guest mode > > + * with vmcs02 loaded and its APIC-access, virtual-APIC and posted > > + * interrupt descriptor addresses still pointing at the host pages that > > + * were mapped for the *previous* nested VM-Enter, which have since been > > + * unmapped and unpinned by nested_put_vmcs12_pages(). KVM returns to > > + * userspace without leaving guest mode, so if userspace resumes the > > + * vCPU, VM-Enter succeeds and hardware accesses those stale HPAs. > > + */ > > + kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); > > + return false; > > } > > > > static bool vmx_get_nested_state_pages(struct kvm_vcpu *vcpu) > > [Severity: High] > This is a pre-existing issue, but should the same re-arm be applied to > vmx_get_nested_state_pages() and svm_get_nested_state_pages()? > > If nested_get_evmcs_page() fails in vmx_get_nested_state_pages(), it returns > false and exits to userspace with KVM_EXIT_INTERNAL_ERROR without re-arming > the request: > > arch/x86/kvm/vmx/nested.c:vmx_get_nested_state_pages() { > if (!nested_get_evmcs_page(vcpu)) { > pr_debug_ratelimited("%s: enlightened vmptrld failed\n", > __func__); > vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; > vcpu->run->internal.suberror = > KVM_INTERNAL_ERROR_EMULATION; > vcpu->run->internal.ndata = 0; > > return false; > } > ... > } > > Similarly, in arch/x86/kvm/svm/nested.c:svm_get_nested_state_pages(), if > load_pdptrs(), kvm_hv_verify_vp_assist(), or nested_svm_merge_msrpm() fail, > they also exit without re-arming. > > If a compromised QEMU sets KVM_REQ_GET_NESTED_STATE_PAGES and KVM clears the > request but fails in these setup steps, a subsequent KVM_RUN could skip state > setup and proceed directly to VM-Enter L2 with stale control structures. > > Does this allow L2 to resume with unpinned HPAs and lead to a use-after-free? > > -- > Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1