]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
KVM: nVMX: avoid NULL pointer dereference with incorrect EVMCS GPAs
authorVitaly Kuznetsov <vkuznets@redhat.com>
Mon, 9 Mar 2020 15:52:11 +0000 (16:52 +0100)
committerPaolo Pisati <paolo.pisati@canonical.com>
Wed, 18 Mar 2020 10:39:16 +0000 (11:39 +0100)
BugLink: https://bugs.launchpad.net/bugs/1867903
commit 95fa10103dabc38be5de8efdfced5e67576ed896 upstream.

When an EVMCS enabled L1 guest on KVM will tries doing enlightened VMEnter
with EVMCS GPA = 0 the host crashes because the

evmcs_gpa != vmx->nested.hv_evmcs_vmptr

condition in nested_vmx_handle_enlightened_vmptrld() will evaluate to
false (as nested.hv_evmcs_vmptr is zeroed after init). The crash will
happen on vmx->nested.hv_evmcs pointer dereference.

Another problematic EVMCS ptr value is '-1' but it only causes host crash
after nested_release_evmcs() invocation. The problem is exactly the same as
with '0', we mistakenly think that the EVMCS pointer hasn't changed and
thus nested.hv_evmcs_vmptr is valid.

Resolve the issue by adding an additional !vmx->nested.hv_evmcs
check to nested_vmx_handle_enlightened_vmptrld(), this way we will
always be trying kvm_vcpu_map() when nested.hv_evmcs is NULL
and this is supposed to catch all invalid EVMCS GPAs.

Also, initialize hv_evmcs_vmptr to '0' in nested_release_evmcs()
to be consistent with initialization where we don't currently
set hv_evmcs_vmptr to '-1'.

Cc: stable@vger.kernel.org
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
arch/x86/kvm/vmx/nested.c

index e1d8062ef12e5f61cf01ec86ece70e657bd2ffb2..2b44554baf283df434277b080aa3052a130758bd 100644 (file)
@@ -223,7 +223,7 @@ static inline void nested_release_evmcs(struct kvm_vcpu *vcpu)
                return;
 
        kvm_vcpu_unmap(vcpu, &vmx->nested.hv_evmcs_map, true);
-       vmx->nested.hv_evmcs_vmptr = -1ull;
+       vmx->nested.hv_evmcs_vmptr = 0;
        vmx->nested.hv_evmcs = NULL;
 }
 
@@ -1828,7 +1828,8 @@ static int nested_vmx_handle_enlightened_vmptrld(struct kvm_vcpu *vcpu,
        if (!nested_enlightened_vmentry(vcpu, &evmcs_gpa))
                return 1;
 
-       if (unlikely(evmcs_gpa != vmx->nested.hv_evmcs_vmptr)) {
+       if (unlikely(!vmx->nested.hv_evmcs ||
+                    evmcs_gpa != vmx->nested.hv_evmcs_vmptr)) {
                if (!vmx->nested.hv_evmcs)
                        vmx->nested.current_vmptr = -1ull;