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