mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
KVM: SVM: ensure that EFER.SVME is set when running nested guest or on nested vmexit
Fixing nested_vmcb_check_save to avoid all TOC/TOU races
is a bit harder in released kernels, so do the bare minimum
by avoiding that EFER.SVME is cleared. This is problematic
because svm_set_efer frees the data structures for nested
virtualization if EFER.SVME is cleared.
Also check that EFER.SVME remains set after a nested vmexit;
clearing it could happen if the bit is zero in the save area
that is passed to KVM_SET_NESTED_STATE (the save area of the
nested state corresponds to the nested hypervisor's state
and is restored on the next nested vmexit).
Cc: stable@vger.kernel.org
Fixes: 2fcf4876ad
("KVM: nSVM: implement on demand allocation of the nested state")
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
a58d9166a7
commit
3c346c0c60
@ -229,6 +229,13 @@ static bool nested_vmcb_check_save(struct vcpu_svm *svm, struct vmcb *vmcb12)
|
||||
{
|
||||
bool vmcb12_lma;
|
||||
|
||||
/*
|
||||
* FIXME: these should be done after copying the fields,
|
||||
* to avoid TOC/TOU races. For these save area checks
|
||||
* the possible damage is limited since kvm_set_cr0 and
|
||||
* kvm_set_cr4 handle failure; EFER_SVME is an exception
|
||||
* so it is force-set later in nested_prepare_vmcb_save.
|
||||
*/
|
||||
if ((vmcb12->save.efer & EFER_SVME) == 0)
|
||||
return false;
|
||||
|
||||
@ -382,7 +389,14 @@ static void nested_prepare_vmcb_save(struct vcpu_svm *svm, struct vmcb *vmcb12)
|
||||
svm->vmcb->save.gdtr = vmcb12->save.gdtr;
|
||||
svm->vmcb->save.idtr = vmcb12->save.idtr;
|
||||
kvm_set_rflags(&svm->vcpu, vmcb12->save.rflags);
|
||||
svm_set_efer(&svm->vcpu, vmcb12->save.efer);
|
||||
|
||||
/*
|
||||
* Force-set EFER_SVME even though it is checked earlier on the
|
||||
* VMCB12, because the guest can flip the bit between the check
|
||||
* and now. Clearing EFER_SVME would call svm_free_nested.
|
||||
*/
|
||||
svm_set_efer(&svm->vcpu, vmcb12->save.efer | EFER_SVME);
|
||||
|
||||
svm_set_cr0(&svm->vcpu, vmcb12->save.cr0);
|
||||
svm_set_cr4(&svm->vcpu, vmcb12->save.cr4);
|
||||
svm->vmcb->save.cr2 = svm->vcpu.arch.cr2 = vmcb12->save.cr2;
|
||||
@ -1188,6 +1202,8 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
|
||||
*/
|
||||
if (!(save->cr0 & X86_CR0_PG))
|
||||
goto out_free;
|
||||
if (!(save->efer & EFER_SVME))
|
||||
goto out_free;
|
||||
|
||||
/*
|
||||
* All checks done, we can enter guest mode. L1 control fields
|
||||
|
Loading…
Reference in New Issue
Block a user