Skip to content

Commit 0f02bd0

Browse files
committed
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 <[email protected]>
1 parent 9319676 commit 0f02bd0

File tree

3 files changed

+26
-4
lines changed

3 files changed

+26
-4
lines changed

arch/x86/kvm/vmx/nested.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6108,9 +6108,16 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
61086108
if (ret)
61096109
return ret;
61106110

6111-
/* Empty 'VMXON' state is permitted */
6112-
if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12))
6113-
return 0;
6111+
/* Empty 'VMXON' state is permitted if no VMCS loaded */
6112+
if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12)) {
6113+
/* See vmx_has_valid_vmcs12. */
6114+
if ((kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE) ||
6115+
(kvm_state->flags & KVM_STATE_NESTED_EVMCS) ||
6116+
(kvm_state->hdr.vmx.vmcs12_pa != -1ull))
6117+
return -EINVAL;
6118+
else
6119+
return 0;
6120+
}
61146121

61156122
if (kvm_state->hdr.vmx.vmcs12_pa != -1ull) {
61166123
if (kvm_state->hdr.vmx.vmcs12_pa == kvm_state->hdr.vmx.vmxon_pa ||

arch/x86/kvm/vmx/nested.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ static inline struct vmcs12 *get_shadow_vmcs12(struct kvm_vcpu *vcpu)
4747
return to_vmx(vcpu)->nested.cached_shadow_vmcs12;
4848
}
4949

50+
/*
51+
* Note: the same condition is checked against the state provided by userspace
52+
* in vmx_set_nested_state; if it is satisfied, the nested state must include
53+
* the VMCS12.
54+
*/
5055
static inline int vmx_has_valid_vmcs12(struct kvm_vcpu *vcpu)
5156
{
5257
struct vcpu_vmx *vmx = to_vmx(vcpu);

tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,19 @@ void test_vmx_nested_state(struct kvm_vm *vm)
183183
state->hdr.vmx.smm.flags = KVM_STATE_NESTED_SMM_GUEST_MODE;
184184
test_nested_state_expect_einval(vm, state);
185185

186-
/* Size must be large enough to fit kvm_nested_state and vmcs12. */
186+
/*
187+
* Size must be large enough to fit kvm_nested_state and vmcs12
188+
* if VMCS12 physical address is set
189+
*/
190+
set_default_vmx_state(state, state_sz);
191+
state->size = sizeof(*state);
192+
state->flags = 0;
193+
test_nested_state_expect_einval(vm, state);
194+
187195
set_default_vmx_state(state, state_sz);
188196
state->size = sizeof(*state);
197+
state->flags = 0;
198+
state->hdr.vmx.vmcs12_pa = -1;
189199
test_nested_state(vm, state);
190200

191201
/*

0 commit comments

Comments
 (0)