Commit cb2567bf3eed3c7fe5fd914d827e3088d21e565f
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 | } |