]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: x86: avoid loading a vCPU after .vm_destroy was called
authorMaxim Levitsky <mlevitsk@redhat.com>
Tue, 22 Mar 2022 17:24:42 +0000 (19:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jun 2022 06:48:55 +0000 (08:48 +0200)
commit 6fcee03df6a1a3101a77344be37bb85c6142d56c upstream.

This can cause various unexpected issues, since VM is partially
destroyed at that point.

For example when AVIC is enabled, this causes avic_vcpu_load to
access physical id page entry which is already freed by .vm_destroy.

Fixes: 8221c1370056 ("svm: Manage vcpu load/unload when enable AVIC")
Cc: stable@vger.kernel.org
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
Message-Id: <20220322172449.235575-2-mlevitsk@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/kvm/x86.c

index 5ee8cc4ea03c7238c2086d8ff15c2bc82a0129db..39c571224ac28871386b624e4a7be72c34f613af 100644 (file)
@@ -11747,20 +11747,15 @@ static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)
        vcpu_put(vcpu);
 }
 
-static void kvm_free_vcpus(struct kvm *kvm)
+static void kvm_unload_vcpu_mmus(struct kvm *kvm)
 {
        unsigned long i;
        struct kvm_vcpu *vcpu;
 
-       /*
-        * Unpin any mmu pages first.
-        */
        kvm_for_each_vcpu(i, vcpu, kvm) {
                kvm_clear_async_pf_completion_queue(vcpu);
                kvm_unload_vcpu_mmu(vcpu);
        }
-
-       kvm_destroy_vcpus(kvm);
 }
 
 void kvm_arch_sync_events(struct kvm *kvm)
@@ -11866,11 +11861,12 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
                __x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, 0, 0);
                mutex_unlock(&kvm->slots_lock);
        }
+       kvm_unload_vcpu_mmus(kvm);
        static_call_cond(kvm_x86_vm_destroy)(kvm);
        kvm_free_msr_filter(srcu_dereference_check(kvm->arch.msr_filter, &kvm->srcu, 1));
        kvm_pic_destroy(kvm);
        kvm_ioapic_destroy(kvm);
-       kvm_free_vcpus(kvm);
+       kvm_destroy_vcpus(kvm);
        kvfree(rcu_dereference_check(kvm->arch.apic_map, 1));
        kfree(srcu_dereference_check(kvm->arch.pmu_event_filter, &kvm->srcu, 1));
        kvm_mmu_uninit_vm(kvm);