b136801
From: Petr Matousek <pmatouse@redhat.com>
b136801
Date: Fri, 24 Oct 2014 17:07:18 +0200
b136801
Subject: [PATCH] kvm: vmx: handle invvpid vm exit gracefully
b136801
b136801
On systems with invvpid instruction support (corresponding bit in
b136801
IA32_VMX_EPT_VPID_CAP MSR is set) guest invocation of invvpid
b136801
causes vm exit, which is currently not handled and results in
b136801
propagation of unknown exit to userspace.
b136801
b136801
Fix this by installing an invvpid vm exit handler.
b136801
b136801
This is CVE-2014-3646.
b136801
b136801
Cc: stable@vger.kernel.org
b136801
Signed-off-by: Petr Matousek <pmatouse@redhat.com>
b136801
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
b136801
---
b136801
 arch/x86/include/uapi/asm/vmx.h | 2 ++
b136801
 arch/x86/kvm/vmx.c              | 9 ++++++++-
b136801
 2 files changed, 10 insertions(+), 1 deletion(-)
b136801
b136801
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
b136801
index 0e79420376eb..990a2fe1588d 100644
b136801
--- a/arch/x86/include/uapi/asm/vmx.h
b136801
+++ b/arch/x86/include/uapi/asm/vmx.h
b136801
@@ -67,6 +67,7 @@
b136801
 #define EXIT_REASON_EPT_MISCONFIG       49
b136801
 #define EXIT_REASON_INVEPT              50
b136801
 #define EXIT_REASON_PREEMPTION_TIMER    52
b136801
+#define EXIT_REASON_INVVPID             53
b136801
 #define EXIT_REASON_WBINVD              54
b136801
 #define EXIT_REASON_XSETBV              55
b136801
 #define EXIT_REASON_APIC_WRITE          56
b136801
@@ -114,6 +115,7 @@
b136801
 	{ EXIT_REASON_EOI_INDUCED,           "EOI_INDUCED" }, \
b136801
 	{ EXIT_REASON_INVALID_STATE,         "INVALID_STATE" }, \
b136801
 	{ EXIT_REASON_INVD,                  "INVD" }, \
b136801
+	{ EXIT_REASON_INVVPID,               "INVVPID" }, \
b136801
 	{ EXIT_REASON_INVPCID,               "INVPCID" }
b136801
 
b136801
 #endif /* _UAPIVMX_H */
b136801
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
b136801
index 0881ec6154cc..12dd2b2e655c 100644
b136801
--- a/arch/x86/kvm/vmx.c
b136801
+++ b/arch/x86/kvm/vmx.c
b136801
@@ -6639,6 +6639,12 @@ static int handle_invept(struct kvm_vcpu *vcpu)
b136801
 	return 1;
b136801
 }
b136801
 
b136801
+static int handle_invvpid(struct kvm_vcpu *vcpu)
b136801
+{
b136801
+	kvm_queue_exception(vcpu, UD_VECTOR);
b136801
+	return 1;
b136801
+}
b136801
+
b136801
 /*
b136801
  * The exit handlers return 1 if the exit was handled fully and guest execution
b136801
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
b136801
@@ -6684,6 +6690,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
b136801
 	[EXIT_REASON_MWAIT_INSTRUCTION]	      = handle_mwait,
b136801
 	[EXIT_REASON_MONITOR_INSTRUCTION]     = handle_monitor,
b136801
 	[EXIT_REASON_INVEPT]                  = handle_invept,
b136801
+	[EXIT_REASON_INVVPID]                 = handle_invvpid,
b136801
 };
b136801
 
b136801
 static const int kvm_vmx_max_exit_handlers =
b136801
@@ -6917,7 +6924,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
b136801
 	case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD:
b136801
 	case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE:
b136801
 	case EXIT_REASON_VMOFF: case EXIT_REASON_VMON:
b136801
-	case EXIT_REASON_INVEPT:
b136801
+	case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID:
b136801
 		/*
b136801
 		 * VMX instructions trap unconditionally. This allows L1 to
b136801
 		 * emulate them for its L2 guest, i.e., allows 3-level nesting!
b136801
-- 
b136801
1.9.3
b136801