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

3.12-stable review patch.  If anyone has any objections, please let me know.

===============

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.

Signed-off-by: Nadav Amit <na...@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[zhangzhiqiang: backport to 3.10:
 - adjust context
 - in 3.10 context "ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF)" is replaced 
by
   "ctxt->eflags &= ~(EFLG_VM | EFLG_IF)" in upstream, which was changed by 
another commit.
 - After the above adjustments, becomes same to the original patch:
       
https://github.com/torvalds/linux/commit/f3747379accba8e95d70cec0eae0582c8c182050
]
Signed-off-by: Zhiqiang Zhang <zhangzhiqiang.zh...@huawei.com>
Signed-off-by: Jiri Slaby <jsl...@suse.cz>
---
 arch/x86/kvm/emulate.c | 27 ++++++++-------------------
 1 file changed, 8 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c412bab82d1f..8216f484398f 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2292,7 +2292,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
         * 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);
 
@@ -2305,25 +2305,13 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        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;
-       default:
-               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;
        }
@@ -2332,10 +2320,11 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        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);
-       *reg_write(ctxt, VCPU_REGS_RSP) = msr_data;
+       *reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data :
+                                                             (u32)msr_data;
 
        return X86EMUL_CONTINUE;
 }
-- 
2.3.5

--
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/

Reply via email to