From f9a519157b5f2f2a34d4ec3a8aaba1fbec896917 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 4 Dec 2014 13:54:07 -0500 Subject: [PATCH] CVE-2014-9090 local DoS via do_double_fault due to improper SS faults (rhbz 1170691) --- kernel.spec | 9 ++ x86_64-traps-Stop-using-IST-for-SS.patch | 146 +++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 x86_64-traps-Stop-using-IST-for-SS.patch diff --git a/kernel.spec b/kernel.spec index f91d7fae6..8c7091116 100644 --- a/kernel.spec +++ b/kernel.spec @@ -756,6 +756,9 @@ Patch25111: 0002-ideapad-laptop-Change-Lenovo-Yoga-2-series-rfkill-ha.patch # CVE-2014-3690 rhbz 1153322 1155372 Patch26060: x86-kvm-vmx-Preserve-CR4-across-VM-entry.patch +#CVE-2014-9090 rhbz 1170691 +Patch26075: x86_64-traps-Stop-using-IST-for-SS.patch + # END OF PATCH DEFINITIONS %endif @@ -1454,6 +1457,9 @@ ApplyPatch 0002-ideapad-laptop-Change-Lenovo-Yoga-2-series-rfkill-ha.patch # CVE-2014-3690 rhbz 1153322 1155372 ApplyPatch x86-kvm-vmx-Preserve-CR4-across-VM-entry.patch +#CVE-2014-9090 rhbz 1170691 +ApplyPatch x86_64-traps-Stop-using-IST-for-SS.patch + # END OF PATCH APPLICATIONS %endif @@ -2266,6 +2272,9 @@ fi # and build. %changelog +* Thu Dec 04 2014 Josh Boyer +- CVE-2014-9090 local DoS via do_double_fault due to improper SS faults (rhbz 1170691) + * Fri Nov 21 2014 Justin M. Forbes - 3.14.25-100 - Linux v3.14.25 diff --git a/x86_64-traps-Stop-using-IST-for-SS.patch b/x86_64-traps-Stop-using-IST-for-SS.patch new file mode 100644 index 000000000..1b317ac94 --- /dev/null +++ b/x86_64-traps-Stop-using-IST-for-SS.patch @@ -0,0 +1,146 @@ +From f4c2632940c4e767d622c109f9cbcb046d432961 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Sat, 22 Nov 2014 18:00:32 -0800 +Subject: [PATCH] x86_64, traps: Stop using IST for #SS + +On a 32-bit kernel, this has no effect, since there are no IST stacks. + +On a 64-bit kernel, #SS can only happen in user code, on a failed iret +to user space, a canonical violation on access via RSP or RBP, or a +genuine stack segment violation in 32-bit kernel code. The first two +cases don't need IST, and the latter two cases are unlikely fatal bugs, +and promoting them to double faults would be fine. + +This fixes a bug in which the espfix64 code mishandles a stack segment +violation. + +This saves 4k of memory per CPU and a tiny bit of code. + +Signed-off-by: Andy Lutomirski +Reviewed-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +--- + arch/x86/include/asm/page_32_types.h | 1 - + arch/x86/include/asm/page_64_types.h | 11 +++++------ + arch/x86/include/asm/traps.h | 1 + + arch/x86/kernel/dumpstack_64.c | 1 - + arch/x86/kernel/entry_64.S | 2 +- + arch/x86/kernel/traps.c | 18 +----------------- + 6 files changed, 8 insertions(+), 26 deletions(-) + +diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h +index f48b17df4224..3a52ee0e726d 100644 +--- a/arch/x86/include/asm/page_32_types.h ++++ b/arch/x86/include/asm/page_32_types.h +@@ -20,7 +20,6 @@ + #define THREAD_SIZE_ORDER 1 + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + +-#define STACKFAULT_STACK 0 + #define DOUBLEFAULT_STACK 1 + #define NMI_STACK 0 + #define DEBUG_STACK 0 +diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h +index 8de6d9cf3b95..d54d1eebeffe 100644 +--- a/arch/x86/include/asm/page_64_types.h ++++ b/arch/x86/include/asm/page_64_types.h +@@ -14,12 +14,11 @@ + #define IRQ_STACK_ORDER 2 + #define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER) + +-#define STACKFAULT_STACK 1 +-#define DOUBLEFAULT_STACK 2 +-#define NMI_STACK 3 +-#define DEBUG_STACK 4 +-#define MCE_STACK 5 +-#define N_EXCEPTION_STACKS 5 /* hw limit: 7 */ ++#define DOUBLEFAULT_STACK 1 ++#define NMI_STACK 2 ++#define DEBUG_STACK 3 ++#define MCE_STACK 4 ++#define N_EXCEPTION_STACKS 4 /* hw limit: 7 */ + + #define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT) + #define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1)) +diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h +index 58d66fe06b61..b409b17efb48 100644 +--- a/arch/x86/include/asm/traps.h ++++ b/arch/x86/include/asm/traps.h +@@ -39,6 +39,7 @@ asmlinkage void simd_coprocessor_error(void); + + #ifdef CONFIG_TRACING + asmlinkage void trace_page_fault(void); ++#define trace_stack_segment stack_segment + #define trace_divide_error divide_error + #define trace_bounds bounds + #define trace_invalid_op invalid_op +diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c +index addb207dab92..66e274a3d968 100644 +--- a/arch/x86/kernel/dumpstack_64.c ++++ b/arch/x86/kernel/dumpstack_64.c +@@ -24,7 +24,6 @@ static char x86_stack_ids[][8] = { + [ DEBUG_STACK-1 ] = "#DB", + [ NMI_STACK-1 ] = "NMI", + [ DOUBLEFAULT_STACK-1 ] = "#DF", +- [ STACKFAULT_STACK-1 ] = "#SS", + [ MCE_STACK-1 ] = "#MC", + #if DEBUG_STKSZ > EXCEPTION_STKSZ + [ N_EXCEPTION_STACKS ... +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index 03cd2a8f6009..d41418880506 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -1549,7 +1549,7 @@ apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \ + + paranoidzeroentry_ist debug do_debug DEBUG_STACK + paranoidzeroentry_ist int3 do_int3 DEBUG_STACK +-paranoiderrorentry stack_segment do_stack_segment ++errorentry stack_segment do_stack_segment + #ifdef CONFIG_XEN + zeroentry xen_debug do_debug + zeroentry xen_int3 do_int3 +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 57409f6b8c62..f208d879a81a 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -218,27 +218,11 @@ DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL + DO_ERROR (X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun ) + DO_ERROR (X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS ) + DO_ERROR (X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present ) +-#ifdef CONFIG_X86_32 + DO_ERROR (X86_TRAP_SS, SIGBUS, "stack segment", stack_segment ) +-#endif + DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0 ) + + #ifdef CONFIG_X86_64 + /* Runs on IST stack */ +-dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) +-{ +- enum ctx_state prev_state; +- +- prev_state = exception_enter(); +- if (notify_die(DIE_TRAP, "stack segment", regs, error_code, +- X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) { +- preempt_conditional_sti(regs); +- do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); +- preempt_conditional_cli(regs); +- } +- exception_exit(prev_state); +-} +- + dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) + { + static const char str[] = "double fault"; +@@ -748,7 +732,7 @@ void __init trap_init(void) + set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun); + set_intr_gate(X86_TRAP_TS, invalid_TSS); + set_intr_gate(X86_TRAP_NP, segment_not_present); +- set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK); ++ set_intr_gate(X86_TRAP_SS, stack_segment); + set_intr_gate(X86_TRAP_GP, general_protection); + set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug); + set_intr_gate(X86_TRAP_MF, coprocessor_error); +-- +1.9.3 +