]> git.baikalelectronics.ru Git - kernel.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)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 2 May 2022 15:42:42 +0000 (11:42 -0400)
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: ee1238620d2b ("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>
arch/x86/kvm/x86.c

index 1abce22b14d77ffb8722329e98b87e2021b44906..ba4faeb324374121c4273d402187148d6170b870 100644 (file)
@@ -11816,20 +11816,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)
@@ -11935,11 +11930,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);