Commit 21be4ca1 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

KVM: nVMX: Clear nested_run_pending if setting nested state fails

VMX's nested_run_pending flag is subtly consumed when stuffing state to
enter guest mode, i.e. needs to be set according before KVM knows if
setting guest state is successful.  If setting guest state fails, clear
the flag as a nested run is obviously not pending.
Reported-by: default avatarAaron Lewis <aaronlewis@google.com>
Signed-off-by: default avatarSean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent db80927e
...@@ -5423,39 +5423,44 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, ...@@ -5423,39 +5423,44 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
if (!(kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE)) if (!(kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE))
return 0; return 0;
vmx->nested.nested_run_pending =
!!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
ret = -EINVAL;
if (nested_cpu_has_shadow_vmcs(vmcs12) && if (nested_cpu_has_shadow_vmcs(vmcs12) &&
vmcs12->vmcs_link_pointer != -1ull) { vmcs12->vmcs_link_pointer != -1ull) {
struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu); struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu);
if (kvm_state->size < sizeof(*kvm_state) + VMCS12_SIZE + sizeof(*vmcs12)) if (kvm_state->size < sizeof(*kvm_state) + VMCS12_SIZE + sizeof(*vmcs12))
return -EINVAL; goto error_guest_mode;
if (copy_from_user(shadow_vmcs12, if (copy_from_user(shadow_vmcs12,
user_kvm_nested_state->data + VMCS12_SIZE, user_kvm_nested_state->data + VMCS12_SIZE,
sizeof(*vmcs12))) sizeof(*vmcs12))) {
return -EFAULT; ret = -EFAULT;
goto error_guest_mode;
}
if (shadow_vmcs12->hdr.revision_id != VMCS12_REVISION || if (shadow_vmcs12->hdr.revision_id != VMCS12_REVISION ||
!shadow_vmcs12->hdr.shadow_vmcs) !shadow_vmcs12->hdr.shadow_vmcs)
return -EINVAL; goto error_guest_mode;
} }
if (nested_vmx_check_controls(vcpu, vmcs12) || if (nested_vmx_check_controls(vcpu, vmcs12) ||
nested_vmx_check_host_state(vcpu, vmcs12) || nested_vmx_check_host_state(vcpu, vmcs12) ||
nested_vmx_check_guest_state(vcpu, vmcs12, &exit_qual)) nested_vmx_check_guest_state(vcpu, vmcs12, &exit_qual))
return -EINVAL; goto error_guest_mode;
vmx->nested.dirty_vmcs12 = true; vmx->nested.dirty_vmcs12 = true;
vmx->nested.nested_run_pending =
!!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
ret = nested_vmx_enter_non_root_mode(vcpu, false); ret = nested_vmx_enter_non_root_mode(vcpu, false);
if (ret) { if (ret)
vmx->nested.nested_run_pending = 0; goto error_guest_mode;
return -EINVAL;
}
return 0; return 0;
error_guest_mode:
vmx->nested.nested_run_pending = 0;
return ret;
} }
void nested_vmx_vcpu_setup(void) void nested_vmx_vcpu_setup(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment