forked from Minki/linux
KVM: nSVM: call nested_svm_load_cr3 on nested state load
While KVM's MMU should be fully reset by loading of nested CR0/CR3/CR4 by KVM_SET_SREGS, we are not in nested mode yet when we do it and therefore only root_mmu is reset. On regular nested entries we call nested_svm_load_cr3 which both updates the guest's CR3 in the MMU when it is needed, and it also initializes the mmu again which makes it initialize the walk_mmu as well when nested paging is enabled in both host and guest. Since we don't call nested_svm_load_cr3 on nested state load, the walk_mmu can be left uninitialized, which can lead to a NULL pointer dereference while accessing it if we happen to get a nested page fault right after entering the nested guest first time after the migration and we decide to emulate it, which leads to the emulator trying to access walk_mmu->gva_to_gpa which is NULL. Therefore we should call this function on nested state load as well. Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Message-Id: <20210401141814.1029036-3-mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
8486039a6c
commit
232f75d3b4
@ -215,24 +215,6 @@ static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
|
||||
if (WARN_ON(!is_guest_mode(vcpu)))
|
||||
return true;
|
||||
|
||||
if (!nested_svm_vmrun_msrpm(svm)) {
|
||||
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
||||
vcpu->run->internal.suberror =
|
||||
KVM_INTERNAL_ERROR_EMULATION;
|
||||
vcpu->run->internal.ndata = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool nested_vmcb_check_controls(struct vmcb_control_area *control)
|
||||
{
|
||||
if (CC(!vmcb_is_intercept(control, INTERCEPT_VMRUN)))
|
||||
@ -1330,6 +1312,28 @@ out_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
|
||||
if (WARN_ON(!is_guest_mode(vcpu)))
|
||||
return true;
|
||||
|
||||
if (nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3,
|
||||
nested_npt_enabled(svm)))
|
||||
return false;
|
||||
|
||||
if (!nested_svm_vmrun_msrpm(svm)) {
|
||||
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
||||
vcpu->run->internal.suberror =
|
||||
KVM_INTERNAL_ERROR_EMULATION;
|
||||
vcpu->run->internal.ndata = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct kvm_x86_nested_ops svm_nested_ops = {
|
||||
.check_events = svm_check_nested_events,
|
||||
.triple_fault = nested_svm_triple_fault,
|
||||
|
Loading…
Reference in New Issue
Block a user