Commit cb2567bf3eed3c7fe5fd914d827e3088d21e565f

Authored by Nadav Amit
Committed by Greg Kroah-Hartman
1 parent c546e47591

KVM: x86: SYSENTER emulation is broken

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 <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 8 additions and 19 deletions Side-by-side Diff

arch/x86/kvm/emulate.c
... ... @@ -2345,7 +2345,7 @@
2345 2345 * Not recognized on AMD in compat mode (but is recognized in legacy
2346 2346 * mode).
2347 2347 */
2348   - if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
  2348 + if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA)
2349 2349 && !vendor_intel(ctxt))
2350 2350 return emulate_ud(ctxt);
2351 2351  
2352 2352  
2353 2353  
... ... @@ -2358,25 +2358,13 @@
2358 2358 setup_syscalls_segments(ctxt, &cs, &ss);
2359 2359  
2360 2360 ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
2361   - switch (ctxt->mode) {
2362   - case X86EMUL_MODE_PROT32:
2363   - if ((msr_data & 0xfffc) == 0x0)
2364   - return emulate_gp(ctxt, 0);
2365   - break;
2366   - case X86EMUL_MODE_PROT64:
2367   - if (msr_data == 0x0)
2368   - return emulate_gp(ctxt, 0);
2369   - break;
2370   - default:
2371   - break;
2372   - }
  2361 + if ((msr_data & 0xfffc) == 0x0)
  2362 + return emulate_gp(ctxt, 0);
2373 2363  
2374 2364 ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
2375   - cs_sel = (u16)msr_data;
2376   - cs_sel &= ~SELECTOR_RPL_MASK;
  2365 + cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK;
2377 2366 ss_sel = cs_sel + 8;
2378   - ss_sel &= ~SELECTOR_RPL_MASK;
2379   - if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) {
  2367 + if (efer & EFER_LMA) {
2380 2368 cs.d = 0;
2381 2369 cs.l = 1;
2382 2370 }
2383 2371  
... ... @@ -2385,10 +2373,11 @@
2385 2373 ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
2386 2374  
2387 2375 ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data);
2388   - ctxt->_eip = msr_data;
  2376 + ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data;
2389 2377  
2390 2378 ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
2391   - *reg_write(ctxt, VCPU_REGS_RSP) = msr_data;
  2379 + *reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data :
  2380 + (u32)msr_data;
2392 2381  
2393 2382 return X86EMUL_CONTINUE;
2394 2383 }