diff options
| -rw-r--r-- | arch/x86/Kconfig | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/irq_64.c | 56 |
2 files changed, 1 insertions, 57 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5ad92419be19..fd06614b09a7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -14,6 +14,7 @@ config X86_32 | |||
| 14 | select ARCH_WANT_IPC_PARSE_VERSION | 14 | select ARCH_WANT_IPC_PARSE_VERSION |
| 15 | select CLKSRC_I8253 | 15 | select CLKSRC_I8253 |
| 16 | select CLONE_BACKWARDS | 16 | select CLONE_BACKWARDS |
| 17 | select HAVE_DEBUG_STACKOVERFLOW | ||
| 17 | select MODULES_USE_ELF_REL | 18 | select MODULES_USE_ELF_REL |
| 18 | select OLD_SIGACTION | 19 | select OLD_SIGACTION |
| 19 | 20 | ||
| @@ -138,7 +139,6 @@ config X86 | |||
| 138 | select HAVE_COPY_THREAD_TLS | 139 | select HAVE_COPY_THREAD_TLS |
| 139 | select HAVE_C_RECORDMCOUNT | 140 | select HAVE_C_RECORDMCOUNT |
| 140 | select HAVE_DEBUG_KMEMLEAK | 141 | select HAVE_DEBUG_KMEMLEAK |
| 141 | select HAVE_DEBUG_STACKOVERFLOW | ||
| 142 | select HAVE_DMA_CONTIGUOUS | 142 | select HAVE_DMA_CONTIGUOUS |
| 143 | select HAVE_DYNAMIC_FTRACE | 143 | select HAVE_DYNAMIC_FTRACE |
| 144 | select HAVE_DYNAMIC_FTRACE_WITH_REGS | 144 | select HAVE_DYNAMIC_FTRACE_WITH_REGS |
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index f107eb2021f6..6bf6517a05bb 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c | |||
| @@ -26,64 +26,8 @@ | |||
| 26 | DEFINE_PER_CPU_PAGE_ALIGNED(struct irq_stack, irq_stack_backing_store) __visible; | 26 | DEFINE_PER_CPU_PAGE_ALIGNED(struct irq_stack, irq_stack_backing_store) __visible; |
| 27 | DECLARE_INIT_PER_CPU(irq_stack_backing_store); | 27 | DECLARE_INIT_PER_CPU(irq_stack_backing_store); |
| 28 | 28 | ||
| 29 | int sysctl_panic_on_stackoverflow; | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Probabilistic stack overflow check: | ||
| 33 | * | ||
| 34 | * Regular device interrupts can enter on the following stacks: | ||
| 35 | * | ||
| 36 | * - User stack | ||
| 37 | * | ||
| 38 | * - Kernel task stack | ||
| 39 | * | ||
| 40 | * - Interrupt stack if a device driver reenables interrupts | ||
| 41 | * which should only happen in really old drivers. | ||
| 42 | * | ||
| 43 | * - Debug IST stack | ||
| 44 | * | ||
| 45 | * All other contexts are invalid. | ||
| 46 | */ | ||
| 47 | static inline void stack_overflow_check(struct pt_regs *regs) | ||
| 48 | { | ||
| 49 | #ifdef CONFIG_DEBUG_STACKOVERFLOW | ||
| 50 | #define STACK_MARGIN 128 | ||
| 51 | u64 irq_stack_top, irq_stack_bottom, estack_top, estack_bottom; | ||
| 52 | u64 curbase = (u64)task_stack_page(current); | ||
| 53 | struct cea_exception_stacks *estacks; | ||
| 54 | |||
| 55 | if (user_mode(regs)) | ||
| 56 | return; | ||
| 57 | |||
| 58 | if (regs->sp >= curbase + sizeof(struct pt_regs) + STACK_MARGIN && | ||
| 59 | regs->sp <= curbase + THREAD_SIZE) | ||
| 60 | return; | ||
| 61 | |||
| 62 | irq_stack_top = (u64)__this_cpu_read(hardirq_stack_ptr); | ||
| 63 | irq_stack_bottom = irq_stack_top - IRQ_STACK_SIZE + STACK_MARGIN; | ||
| 64 | if (regs->sp >= irq_stack_bottom && regs->sp <= irq_stack_top) | ||
| 65 | return; | ||
| 66 | |||
| 67 | estacks = __this_cpu_read(cea_exception_stacks); | ||
| 68 | estack_top = CEA_ESTACK_TOP(estacks, DB); | ||
| 69 | estack_bottom = CEA_ESTACK_BOT(estacks, DB) + STACK_MARGIN; | ||
| 70 | if (regs->sp >= estack_bottom && regs->sp <= estack_top) | ||
| 71 | return; | ||
| 72 | |||
| 73 | WARN_ONCE(1, "do_IRQ(): %s has overflown the kernel stack (cur:%Lx,sp:%lx, irq stack:%Lx-%Lx, exception stack: %Lx-%Lx, ip:%pF)\n", | ||
| 74 | current->comm, curbase, regs->sp, | ||
| 75 | irq_stack_bottom, irq_stack_top, | ||
| 76 | estack_bottom, estack_top, (void *)regs->ip); | ||
| 77 | |||
| 78 | if (sysctl_panic_on_stackoverflow) | ||
| 79 | panic("low stack detected by irq handler - check messages\n"); | ||
| 80 | #endif | ||
| 81 | } | ||
| 82 | |||
| 83 | bool handle_irq(struct irq_desc *desc, struct pt_regs *regs) | 29 | bool handle_irq(struct irq_desc *desc, struct pt_regs *regs) |
| 84 | { | 30 | { |
| 85 | stack_overflow_check(regs); | ||
| 86 | |||
| 87 | if (IS_ERR_OR_NULL(desc)) | 31 | if (IS_ERR_OR_NULL(desc)) |
| 88 | return false; | 32 | return false; |
| 89 | 33 | ||
