diff options
author | Jim Mattson <jmattson@google.com> | 2016-07-08 15:36:06 -0700 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-07-14 19:11:20 +0200 |
commit | 2f1fe81123f59271bddda673b60116bde9660385 (patch) | |
tree | 8fead675d92c2fbdc180db2231fd47e6ff067984 /virt | |
parent | 4e59516a12a6ef6dcb660cb3a3f70c64bd60cfec (diff) | |
download | linux-2f1fe81123f59271bddda673b60116bde9660385.tar.gz linux-2f1fe81123f59271bddda673b60116bde9660385.tar.bz2 linux-2f1fe81123f59271bddda673b60116bde9660385.zip |
KVM: nVMX: Fix memory corruption when using VMCS shadowing
When freeing the nested resources of a vcpu, there is an assumption that
the vcpu's vmcs01 is the current VMCS on the CPU that executes
nested_release_vmcs12(). If this assumption is violated, the vcpu's
vmcs01 may be made active on multiple CPUs at the same time, in
violation of Intel's specification. Moreover, since the vcpu's vmcs01 is
not VMCLEARed on every CPU on which it is active, it can linger in a
CPU's VMCS cache after it has been freed and potentially
repurposed. Subsequent eviction from the CPU's VMCS cache on a capacity
miss can result in memory corruption.
It is not sufficient for vmx_free_vcpu() to call vmx_load_vmcs01(). If
the vcpu in question was last loaded on a different CPU, it must be
migrated to the current CPU before calling vmx_load_vmcs01().
Signed-off-by: Jim Mattson <jmattson@google.com>
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/kvm_main.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 48bd520fc702..dd25346ec356 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -148,6 +148,7 @@ int vcpu_load(struct kvm_vcpu *vcpu) put_cpu(); return 0; } +EXPORT_SYMBOL_GPL(vcpu_load); void vcpu_put(struct kvm_vcpu *vcpu) { @@ -157,6 +158,7 @@ void vcpu_put(struct kvm_vcpu *vcpu) preempt_enable(); mutex_unlock(&vcpu->mutex); } +EXPORT_SYMBOL_GPL(vcpu_put); static void ack_flush(void *_completed) { |