Commit be5fa873 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

KVM: SVM: check validity of VMCB controls when returning from SMM



The VMCB12 is stored in guest memory and can be mangled while in SMM; it
is then reloaded by svm_leave_smm(), but it is not checked again for
validity.

Move the cached vmcb12 control and save consistency checks out of
svm_set_nested_state() and into a helper, and reuse it in
svm_leave_smm().

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 5a30e8ae
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -418,6 +418,15 @@ static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu)
	return __nested_vmcb_check_controls(vcpu, ctl);
}

int nested_svm_check_cached_vmcb12(struct kvm_vcpu *vcpu)
{
	if (!nested_vmcb_check_save(vcpu) ||
	    !nested_vmcb_check_controls(vcpu))
		return -EINVAL;

	return 0;
}

/*
 * If a feature is not advertised to L1, clear the corresponding vmcb12
 * intercept.
@@ -1028,8 +1037,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu)
	nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
	nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);

	if (!nested_vmcb_check_save(vcpu) ||
	    !nested_vmcb_check_controls(vcpu)) {
	if (nested_svm_check_cached_vmcb12(vcpu) < 0) {
		vmcb12->control.exit_code    = SVM_EXIT_ERR;
		vmcb12->control.exit_info_1  = 0;
		vmcb12->control.exit_info_2  = 0;
+4 −0
Original line number Diff line number Diff line
@@ -4880,6 +4880,10 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram)
	vmcb12 = map.hva;
	nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
	nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);

	if (nested_svm_check_cached_vmcb12(vcpu) < 0)
		goto unmap_save;

	ret = enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, vmcb12, false);

	if (ret)
+1 −0
Original line number Diff line number Diff line
@@ -797,6 +797,7 @@ static inline int nested_svm_simple_vmexit(struct vcpu_svm *svm, u32 exit_code)

int nested_svm_exit_handled(struct vcpu_svm *svm);
int nested_svm_check_permissions(struct kvm_vcpu *vcpu);
int nested_svm_check_cached_vmcb12(struct kvm_vcpu *vcpu);
int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
			       bool has_error_code, u32 error_code);
int nested_svm_exit_special(struct vcpu_svm *svm);