Skip to content

Commit f374737

Browse files
anadavbonzini
authored andcommitted
KVM: x86: SYSENTER emulation is broken
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: stable@vger.linux.org Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 63ea0a4 commit f374737

File tree

1 file changed

+8
-19
lines changed

1 file changed

+8
-19
lines changed

Diff for: arch/x86/kvm/emulate.c

+8-19
Original file line numberDiff line numberDiff line change
@@ -2348,7 +2348,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
23482348
* Not recognized on AMD in compat mode (but is recognized in legacy
23492349
* mode).
23502350
*/
2351-
if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
2351+
if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA)
23522352
&& !vendor_intel(ctxt))
23532353
return emulate_ud(ctxt);
23542354

@@ -2359,25 +2359,13 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
23592359
setup_syscalls_segments(ctxt, &cs, &ss);
23602360

23612361
ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
2362-
switch (ctxt->mode) {
2363-
case X86EMUL_MODE_PROT32:
2364-
if ((msr_data & 0xfffc) == 0x0)
2365-
return emulate_gp(ctxt, 0);
2366-
break;
2367-
case X86EMUL_MODE_PROT64:
2368-
if (msr_data == 0x0)
2369-
return emulate_gp(ctxt, 0);
2370-
break;
2371-
default:
2372-
break;
2373-
}
2362+
if ((msr_data & 0xfffc) == 0x0)
2363+
return emulate_gp(ctxt, 0);
23742364

23752365
ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
2376-
cs_sel = (u16)msr_data;
2377-
cs_sel &= ~SELECTOR_RPL_MASK;
2366+
cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK;
23782367
ss_sel = cs_sel + 8;
2379-
ss_sel &= ~SELECTOR_RPL_MASK;
2380-
if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) {
2368+
if (efer & EFER_LMA) {
23812369
cs.d = 0;
23822370
cs.l = 1;
23832371
}
@@ -2386,10 +2374,11 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
23862374
ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
23872375

23882376
ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data);
2389-
ctxt->_eip = msr_data;
2377+
ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data;
23902378

23912379
ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
2392-
*reg_write(ctxt, VCPU_REGS_RSP) = msr_data;
2380+
*reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data :
2381+
(u32)msr_data;
23932382

23942383
return X86EMUL_CONTINUE;
23952384
}

0 commit comments

Comments
 (0)