[PATCH v2 18/36] KVM: nVMX: Add check vmread/vmwrite on tertiary control

isaku.yamahata@intel.com posted 36 patches 3 weeks, 6 days ago
[PATCH v2 18/36] KVM: nVMX: Add check vmread/vmwrite on tertiary control
Posted by isaku.yamahata@intel.com 3 weeks, 6 days ago
From: Isaku Yamahata <isaku.yamahata@intel.com>

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.

Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
---
 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 65f7260d02df..562b5ffc6433 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -5768,6 +5768,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)
@@ -5798,6 +5808,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);
@@ -5922,6 +5935,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);
@@ -7170,6 +7186,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 6df2cfb20d87..1100a8114dd9 100644
--- a/arch/x86/kvm/vmx/nested.h
+++ b/arch/x86/kvm/vmx/nested.h
@@ -157,6 +157,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);
+}
+
 /* APIC TIMER VIRTUALIZATION requires in-kernel lapic. */
 static inline bool nested_cpu_can_support_apic_virt_timer(struct kvm_vcpu *vcpu)
 {
-- 
2.45.2