KVM: nVMX: check for required but missing VMCS12 in KVM_SET_NESTED_STATE
A missing VMCS12 was not causing -EINVAL (it was just read with copy_from_user, so it is not a security issue, but it is still wrong). Test for VMCS12 validity and reject the nested state if a VMCS12 is required but not present. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Родитель
9319676595
Коммит
0f02bd0ade
|
@ -6108,9 +6108,16 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Empty 'VMXON' state is permitted */
|
||||
if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12))
|
||||
/* Empty 'VMXON' state is permitted if no VMCS loaded */
|
||||
if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12)) {
|
||||
/* See vmx_has_valid_vmcs12. */
|
||||
if ((kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE) ||
|
||||
(kvm_state->flags & KVM_STATE_NESTED_EVMCS) ||
|
||||
(kvm_state->hdr.vmx.vmcs12_pa != -1ull))
|
||||
return -EINVAL;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (kvm_state->hdr.vmx.vmcs12_pa != -1ull) {
|
||||
if (kvm_state->hdr.vmx.vmcs12_pa == kvm_state->hdr.vmx.vmxon_pa ||
|
||||
|
|
|
@ -47,6 +47,11 @@ static inline struct vmcs12 *get_shadow_vmcs12(struct kvm_vcpu *vcpu)
|
|||
return to_vmx(vcpu)->nested.cached_shadow_vmcs12;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the same condition is checked against the state provided by userspace
|
||||
* in vmx_set_nested_state; if it is satisfied, the nested state must include
|
||||
* the VMCS12.
|
||||
*/
|
||||
static inline int vmx_has_valid_vmcs12(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
|
|
|
@ -183,9 +183,19 @@ void test_vmx_nested_state(struct kvm_vm *vm)
|
|||
state->hdr.vmx.smm.flags = KVM_STATE_NESTED_SMM_GUEST_MODE;
|
||||
test_nested_state_expect_einval(vm, state);
|
||||
|
||||
/* Size must be large enough to fit kvm_nested_state and vmcs12. */
|
||||
/*
|
||||
* Size must be large enough to fit kvm_nested_state and vmcs12
|
||||
* if VMCS12 physical address is set
|
||||
*/
|
||||
set_default_vmx_state(state, state_sz);
|
||||
state->size = sizeof(*state);
|
||||
state->flags = 0;
|
||||
test_nested_state_expect_einval(vm, state);
|
||||
|
||||
set_default_vmx_state(state, state_sz);
|
||||
state->size = sizeof(*state);
|
||||
state->flags = 0;
|
||||
state->hdr.vmx.vmcs12_pa = -1;
|
||||
test_nested_state(vm, state);
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче