[PATCH 3.2 152/152] KVM: x86: SYSENTER emulation is broken
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
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/