From cdef511985374dd042a40bb32c1c346c2662c9dc Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 15 Jan 2015 15:21:19 +0100 Subject: [PATCH 1/3] KVM: fix sparse warning in include/trace/events/kvm.h sparse complains about include/trace/events/kvm.h:163:1: error: directive in argument list include/trace/events/kvm.h:167:1: error: directive in argument list include/trace/events/kvm.h:169:1: error: directive in argument list and sparse is right. Preprocessing directives in an argument of a macro are undefined behaviour as of C99 6.10.3p11. Lets use an indirection to fix this. Signed-off-by: Christian Borntraeger Signed-off-by: Paolo Bonzini --- include/trace/events/kvm.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h index 6edf1f2028cd..86b399c66c3d 100644 --- a/include/trace/events/kvm.h +++ b/include/trace/events/kvm.h @@ -146,6 +146,14 @@ TRACE_EVENT(kvm_msi_set_irq, #if defined(CONFIG_HAVE_KVM_IRQFD) +#ifdef kvm_irqchips +#define kvm_ack_irq_string "irqchip %s pin %u" +#define kvm_ack_irq_parm __print_symbolic(__entry->irqchip, kvm_irqchips), __entry->pin +#else +#define kvm_ack_irq_string "irqchip %d pin %u" +#define kvm_ack_irq_parm __entry->irqchip, __entry->pin +#endif + TRACE_EVENT(kvm_ack_irq, TP_PROTO(unsigned int irqchip, unsigned int pin), TP_ARGS(irqchip, pin), @@ -160,13 +168,7 @@ TRACE_EVENT(kvm_ack_irq, __entry->pin = pin; ), -#ifdef kvm_irqchips - TP_printk("irqchip %s pin %u", - __print_symbolic(__entry->irqchip, kvm_irqchips), - __entry->pin) -#else - TP_printk("irqchip %d pin %u", __entry->irqchip, __entry->pin) -#endif + TP_printk(kvm_ack_irq_string, kvm_ack_irq_parm) ); #endif /* defined(CONFIG_HAVE_KVM_IRQFD) */ From 63ea0a49ae0b145b91ff2b070c01b66fc75854b9 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 8 Jan 2015 11:59:03 +0100 Subject: [PATCH 2/3] KVM: x86: Fix of previously incomplete fix for CVE-2014-8480 STR and SLDT with rip-relative operand can cause a host kernel oops. Mark them as DstMem as well. Cc: stable@vger.linux.org Signed-off-by: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 169b09d76ddd..817c6ca2c4fb 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3791,8 +3791,8 @@ static const struct opcode group5[] = { }; static const struct opcode group6[] = { - DI(Prot, sldt), - DI(Prot, str), + DI(Prot | DstMem, sldt), + DI(Prot | DstMem, str), II(Prot | Priv | SrcMem16, em_lldt, lldt), II(Prot | Priv | SrcMem16, em_ltr, ltr), N, N, N, N, From f3747379accba8e95d70cec0eae0582c8c182050 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 1 Jan 2015 23:11:11 +0200 Subject: [PATCH 3/3] 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 Signed-off-by: Paolo Bonzini --- 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 817c6ca2c4fb..de12c1d379f1 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2348,7 +2348,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); @@ -2359,25 +2359,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); - 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; } @@ -2386,10 +2374,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; }