[PATCH 3.2 152/152] KVM: x86: SYSENTER emulation is broken

2015-02-16 Thread Ben Hutchings
3.2.67-rc1 review patch.  If anyone has any objections, please let me know.

--

From: Nadav Amit 

commit f3747379accba8e95d70cec0eae0582c8c182050 upstream.

SYSENTER emulation is broken in several ways:
1. It misses the case of 16-bit code segments completely (CVE-2015-0239).
2. MSR_IA32_SYSENTER_CS is checked in 64-bit mode incorrectly (bits 0 and 1 can
   still be set without causing #GP).
3. MSR_IA32_SYSENTER_EIP and MSR_IA32_SYSENTER_ESP are not masked in
   legacy-mode.
4. There is some unneeded code.

Fix it.

Cc: sta...@vger.linux.org
Signed-off-by: Nadav Amit 
Signed-off-by: Paolo Bonzini 
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings 
---
 arch/x86/kvm/emulate.c | 27 ---
 1 file changed, 8 insertions(+), 19 deletions(-)

--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2083,7 +2083,7 @@ static int em_sysenter(struct x86_emulat
 * Not recognized on AMD in compat mode (but is recognized in legacy
 * mode).
 */
-   if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
+   if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA)
&& !vendor_intel(ctxt))
return emulate_ud(ctxt);
 
@@ -2096,23 +2096,13 @@ static int em_sysenter(struct x86_emulat
setup_syscalls_segments(ctxt, , );
 
ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, _data);
-   switch (ctxt->mode) {
-   case X86EMUL_MODE_PROT32:
-   if ((msr_data & 0xfffc) == 0x0)
-   return emulate_gp(ctxt, 0);
-   break;
-   case X86EMUL_MODE_PROT64:
-   if (msr_data == 0x0)
-   return emulate_gp(ctxt, 0);
-   break;
-   }
+   if ((msr_data & 0xfffc) == 0x0)
+   return emulate_gp(ctxt, 0);
 
ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
-   cs_sel = (u16)msr_data;
-   cs_sel &= ~SELECTOR_RPL_MASK;
+   cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK;
ss_sel = cs_sel + 8;
-   ss_sel &= ~SELECTOR_RPL_MASK;
-   if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) {
+   if (efer & EFER_LMA) {
cs.d = 0;
cs.l = 1;
}
@@ -2121,10 +2111,11 @@ static int em_sysenter(struct x86_emulat
ops->set_segment(ctxt, ss_sel, , 0, VCPU_SREG_SS);
 
ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, _data);
-   ctxt->_eip = msr_data;
+   ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data;
 
ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, _data);
-   ctxt->regs[VCPU_REGS_RSP] = msr_data;
+   ctxt->regs[VCPU_REGS_RSP] = (efer & EFER_LMA) ? msr_data :
+   (u32)msr_data;
 
return X86EMUL_CONTINUE;
 }

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3.2 152/152] KVM: x86: SYSENTER emulation is broken

2015-02-16 Thread Ben Hutchings
3.2.67-rc1 review patch.  If anyone has any objections, please let me know.

--

From: Nadav Amit na...@cs.technion.ac.il

commit f3747379accba8e95d70cec0eae0582c8c182050 upstream.

SYSENTER emulation is broken in several ways:
1. It misses the case of 16-bit code segments completely (CVE-2015-0239).
2. MSR_IA32_SYSENTER_CS is checked in 64-bit mode incorrectly (bits 0 and 1 can
   still be set without causing #GP).
3. MSR_IA32_SYSENTER_EIP and MSR_IA32_SYSENTER_ESP are not masked in
   legacy-mode.
4. There is some unneeded code.

Fix it.

Cc: sta...@vger.linux.org
Signed-off-by: Nadav Amit na...@cs.technion.ac.il
Signed-off-by: Paolo Bonzini pbonz...@redhat.com
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings b...@decadent.org.uk
---
 arch/x86/kvm/emulate.c | 27 ---
 1 file changed, 8 insertions(+), 19 deletions(-)

--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2083,7 +2083,7 @@ static int em_sysenter(struct x86_emulat
 * Not recognized on AMD in compat mode (but is recognized in legacy
 * mode).
 */
-   if ((ctxt-mode == X86EMUL_MODE_PROT32)  (efer  EFER_LMA)
+   if ((ctxt-mode != X86EMUL_MODE_PROT64)  (efer  EFER_LMA)
 !vendor_intel(ctxt))
return emulate_ud(ctxt);
 
@@ -2096,23 +2096,13 @@ static int em_sysenter(struct x86_emulat
setup_syscalls_segments(ctxt, cs, ss);
 
ops-get_msr(ctxt, MSR_IA32_SYSENTER_CS, msr_data);
-   switch (ctxt-mode) {
-   case X86EMUL_MODE_PROT32:
-   if ((msr_data  0xfffc) == 0x0)
-   return emulate_gp(ctxt, 0);
-   break;
-   case X86EMUL_MODE_PROT64:
-   if (msr_data == 0x0)
-   return emulate_gp(ctxt, 0);
-   break;
-   }
+   if ((msr_data  0xfffc) == 0x0)
+   return emulate_gp(ctxt, 0);
 
ctxt-eflags = ~(EFLG_VM | EFLG_IF | EFLG_RF);
-   cs_sel = (u16)msr_data;
-   cs_sel = ~SELECTOR_RPL_MASK;
+   cs_sel = (u16)msr_data  ~SELECTOR_RPL_MASK;
ss_sel = cs_sel + 8;
-   ss_sel = ~SELECTOR_RPL_MASK;
-   if (ctxt-mode == X86EMUL_MODE_PROT64 || (efer  EFER_LMA)) {
+   if (efer  EFER_LMA) {
cs.d = 0;
cs.l = 1;
}
@@ -2121,10 +2111,11 @@ static int em_sysenter(struct x86_emulat
ops-set_segment(ctxt, ss_sel, ss, 0, VCPU_SREG_SS);
 
ops-get_msr(ctxt, MSR_IA32_SYSENTER_EIP, msr_data);
-   ctxt-_eip = msr_data;
+   ctxt-_eip = (efer  EFER_LMA) ? msr_data : (u32)msr_data;
 
ops-get_msr(ctxt, MSR_IA32_SYSENTER_ESP, msr_data);
-   ctxt-regs[VCPU_REGS_RSP] = msr_data;
+   ctxt-regs[VCPU_REGS_RSP] = (efer  EFER_LMA) ? msr_data :
+   (u32)msr_data;
 
return X86EMUL_CONTINUE;
 }

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/