From: Isaku Yamahata Make the access to the tertiary processor-based VM control an error if the guest VMX true processor-based controls don't report it. Without this patch, the KVM unit test_vmread_vmwrite() fails because vmread()/vmwrite() can succeeds with the index beyond MSR_IA32_VMX_VMCS_ENUM when the tertiary processor-based VM-executing controls aren't advertised to the guest. Reported-by: kernel test robot Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/nested.c | 20 ++++++++++++++++++++ arch/x86/kvm/vmx/nested.h | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index c8b42c880300..d6ae62e70560 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5794,6 +5794,16 @@ static int handle_vmresume(struct kvm_vcpu *vcpu) return nested_vmx_run(vcpu, false); } +static bool is_vmcs_field_valid(struct kvm_vcpu *vcpu, unsigned long field) +{ + if (!nested_cpu_supports_tertiary_ctls(vcpu) && + (field == TERTIARY_VM_EXEC_CONTROL || + field == TERTIARY_VM_EXEC_CONTROL_HIGH)) + return false; + + return true; +} + static int handle_vmread(struct kvm_vcpu *vcpu) { struct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu) @@ -5824,6 +5834,9 @@ static int handle_vmread(struct kvm_vcpu *vcpu) get_vmcs12(vcpu)->vmcs_link_pointer == INVALID_GPA)) return nested_vmx_failInvalid(vcpu); + if (!is_vmcs_field_valid(vcpu, field)) + return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); + offset = get_vmcs12_field_offset(field); if (offset < 0) return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); @@ -5948,6 +5961,9 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) field = kvm_register_read(vcpu, (((instr_info) >> 28) & 0xf)); + if (!is_vmcs_field_valid(vcpu, field)) + return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); + offset = get_vmcs12_field_offset(field); if (offset < 0) return nested_vmx_fail(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); @@ -7196,6 +7212,10 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, kvm_state->hdr.vmx.preemption_timer_deadline; } + if (!nested_cpu_supports_tertiary_ctls(vcpu) && + vmcs12->tertiary_vm_exec_control) + goto error_guest_mode; + if (nested_vmx_check_controls(vcpu, vmcs12) || nested_vmx_check_host_state(vcpu, vmcs12) || nested_vmx_check_guest_state(vcpu, vmcs12, &ignored)) diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 9ca1df72e228..07c0f112e37e 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -158,6 +158,11 @@ static inline bool __nested_cpu_supports_tertiary_ctls(struct nested_vmx_msrs *m return msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS; } +static inline bool nested_cpu_supports_tertiary_ctls(struct kvm_vcpu *vcpu) +{ + return __nested_cpu_supports_tertiary_ctls(&to_vmx(vcpu)->nested.msrs); +} + static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit) { return vmcs12->cpu_based_vm_exec_control & bit; -- 2.45.2