summaryrefslogtreecommitdiffstats
path: root/KVM-x86-Check-non-canonical-addresses-upon-WRMSR.patch
diff options
context:
space:
mode:
Diffstat (limited to 'KVM-x86-Check-non-canonical-addresses-upon-WRMSR.patch')
-rw-r--r--KVM-x86-Check-non-canonical-addresses-upon-WRMSR.patch145
1 files changed, 0 insertions, 145 deletions
diff --git a/KVM-x86-Check-non-canonical-addresses-upon-WRMSR.patch b/KVM-x86-Check-non-canonical-addresses-upon-WRMSR.patch
deleted file mode 100644
index 61d0b6058..000000000
--- a/KVM-x86-Check-non-canonical-addresses-upon-WRMSR.patch
+++ /dev/null
@@ -1,145 +0,0 @@
-From: Nadav Amit <namit@cs.technion.ac.il>
-Date: Fri, 24 Oct 2014 17:07:12 +0200
-Subject: [PATCH] KVM: x86: Check non-canonical addresses upon WRMSR
-
-Upon WRMSR, the CPU should inject #GP if a non-canonical value (address) is
-written to certain MSRs. The behavior is "almost" identical for AMD and Intel
-(ignoring MSRs that are not implemented in either architecture since they would
-anyhow #GP). However, IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if
-non-canonical address is written on Intel but not on AMD (which ignores the top
-32-bits).
-
-Accordingly, this patch injects a #GP on the MSRs which behave identically on
-Intel and AMD. To eliminate the differences between the architecutres, the
-value which is written to IA32_SYSENTER_ESP and IA32_SYSENTER_EIP is turned to
-canonical value before writing instead of injecting a #GP.
-
-Some references from Intel and AMD manuals:
-
-According to Intel SDM description of WRMSR instruction #GP is expected on
-WRMSR "If the source register contains a non-canonical address and ECX
-specifies one of the following MSRs: IA32_DS_AREA, IA32_FS_BASE, IA32_GS_BASE,
-IA32_KERNEL_GS_BASE, IA32_LSTAR, IA32_SYSENTER_EIP, IA32_SYSENTER_ESP."
-
-According to AMD manual instruction manual:
-LSTAR/CSTAR (SYSCALL): "The WRMSR instruction loads the target RIP into the
-LSTAR and CSTAR registers. If an RIP written by WRMSR is not in canonical
-form, a general-protection exception (#GP) occurs."
-IA32_GS_BASE and IA32_FS_BASE (WRFSBASE/WRGSBASE): "The address written to the
-base field must be in canonical form or a #GP fault will occur."
-IA32_KERNEL_GS_BASE (SWAPGS): "The address stored in the KernelGSbase MSR must
-be in canonical form."
-
-This patch fixes CVE-2014-3610.
-
-Cc: stable@vger.kernel.org
-Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- arch/x86/include/asm/kvm_host.h | 14 ++++++++++++++
- arch/x86/kvm/svm.c | 2 +-
- arch/x86/kvm/vmx.c | 2 +-
- arch/x86/kvm/x86.c | 27 ++++++++++++++++++++++++++-
- 4 files changed, 42 insertions(+), 3 deletions(-)
-
-diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
-index 7d603a71ab3a..ccc94de4ac49 100644
---- a/arch/x86/include/asm/kvm_host.h
-+++ b/arch/x86/include/asm/kvm_host.h
-@@ -989,6 +989,20 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
- kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
- }
-
-+static inline u64 get_canonical(u64 la)
-+{
-+ return ((int64_t)la << 16) >> 16;
-+}
-+
-+static inline bool is_noncanonical_address(u64 la)
-+{
-+#ifdef CONFIG_X86_64
-+ return get_canonical(la) != la;
-+#else
-+ return false;
-+#endif
-+}
-+
- #define TSS_IOPB_BASE_OFFSET 0x66
- #define TSS_BASE_SIZE 0x68
- #define TSS_IOPB_SIZE (65536 / 8)
-diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
-index 65510f624dfe..00bed2c5e948 100644
---- a/arch/x86/kvm/svm.c
-+++ b/arch/x86/kvm/svm.c
-@@ -3251,7 +3251,7 @@ static int wrmsr_interception(struct vcpu_svm *svm)
- msr.host_initiated = false;
-
- svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
-- if (svm_set_msr(&svm->vcpu, &msr)) {
-+ if (kvm_set_msr(&svm->vcpu, &msr)) {
- trace_kvm_msr_write_ex(ecx, data);
- kvm_inject_gp(&svm->vcpu, 0);
- } else {
-diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
-index 0acac81f198b..148020a7dd98 100644
---- a/arch/x86/kvm/vmx.c
-+++ b/arch/x86/kvm/vmx.c
-@@ -5291,7 +5291,7 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu)
- msr.data = data;
- msr.index = ecx;
- msr.host_initiated = false;
-- if (vmx_set_msr(vcpu, &msr) != 0) {
-+ if (kvm_set_msr(vcpu, &msr) != 0) {
- trace_kvm_msr_write_ex(ecx, data);
- kvm_inject_gp(vcpu, 0);
- return 1;
-diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index 34c8f94331f8..5a7195573a32 100644
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -987,7 +987,6 @@ void kvm_enable_efer_bits(u64 mask)
- }
- EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
-
--
- /*
- * Writes msr value into into the appropriate "register".
- * Returns 0 on success, non-0 otherwise.
-@@ -995,8 +994,34 @@ EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
- */
- int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
- {
-+ switch (msr->index) {
-+ case MSR_FS_BASE:
-+ case MSR_GS_BASE:
-+ case MSR_KERNEL_GS_BASE:
-+ case MSR_CSTAR:
-+ case MSR_LSTAR:
-+ if (is_noncanonical_address(msr->data))
-+ return 1;
-+ break;
-+ case MSR_IA32_SYSENTER_EIP:
-+ case MSR_IA32_SYSENTER_ESP:
-+ /*
-+ * IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if
-+ * non-canonical address is written on Intel but not on
-+ * AMD (which ignores the top 32-bits, because it does
-+ * not implement 64-bit SYSENTER).
-+ *
-+ * 64-bit code should hence be able to write a non-canonical
-+ * value on AMD. Making the address canonical ensures that
-+ * vmentry does not fail on Intel after writing a non-canonical
-+ * value, and that something deterministic happens if the guest
-+ * invokes 64-bit SYSENTER.
-+ */
-+ msr->data = get_canonical(msr->data);
-+ }
- return kvm_x86_ops->set_msr(vcpu, msr);
- }
-+EXPORT_SYMBOL_GPL(kvm_set_msr);
-
- /*
- * Adapt set_msr() to msr_io()'s calling convention
---
-1.9.3
-