1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 1991, 1992 Linus Torvalds 4 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs 5 */ 6 #include <linux/sched/debug.h> 7 #include <linux/kallsyms.h> 8 #include <linux/kprobes.h> 9 #include <linux/uaccess.h> 10 #include <linux/hardirq.h> 11 #include <linux/kdebug.h> 12 #include <linux/export.h> 13 #include <linux/ptrace.h> 14 #include <linux/kexec.h> 15 #include <linux/sysfs.h> 16 #include <linux/bug.h> 17 #include <linux/nmi.h> 18 19 #include <asm/cpu_entry_area.h> 20 #include <asm/stacktrace.h> 21 22 static const char *exception_stack_names[N_EXCEPTION_STACKS] = { 23 [ ESTACK_DF ] = "#DF", 24 [ ESTACK_NMI ] = "NMI", 25 [ ESTACK_DB ] = "#DB", 26 [ ESTACK_MCE ] = "#MC", 27 }; 28 29 const char *stack_type_name(enum stack_type type) 30 { 31 BUILD_BUG_ON(N_EXCEPTION_STACKS != 4); 32 33 if (type == STACK_TYPE_IRQ) 34 return "IRQ"; 35 36 if (type == STACK_TYPE_ENTRY) { 37 /* 38 * On 64-bit, we have a generic entry stack that we 39 * use for all the kernel entry points, including 40 * SYSENTER. 41 */ 42 return "ENTRY_TRAMPOLINE"; 43 } 44 45 if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST) 46 return exception_stack_names[type - STACK_TYPE_EXCEPTION]; 47 48 return NULL; 49 } 50 51 struct estack_layout { 52 unsigned int begin; 53 unsigned int end; 54 }; 55 56 #define ESTACK_ENTRY(x) { \ 57 .begin = offsetof(struct cea_exception_stacks, x## _stack), \ 58 .end = offsetof(struct cea_exception_stacks, x## _stack_guard) \ 59 } 60 61 static const struct estack_layout layout[N_EXCEPTION_STACKS] = { 62 [ ESTACK_DF ] = ESTACK_ENTRY(DF), 63 [ ESTACK_NMI ] = ESTACK_ENTRY(NMI), 64 [ ESTACK_DB ] = ESTACK_ENTRY(DB), 65 [ ESTACK_MCE ] = ESTACK_ENTRY(MCE), 66 }; 67 68 static bool in_exception_stack(unsigned long *stack, struct stack_info *info) 69 { 70 unsigned long estacks, begin, end, stk = (unsigned long)stack; 71 struct pt_regs *regs; 72 unsigned int k; 73 74 BUILD_BUG_ON(N_EXCEPTION_STACKS != 4); 75 76 estacks = (unsigned long)__this_cpu_read(cea_exception_stacks); 77 78 for (k = 0; k < N_EXCEPTION_STACKS; k++) { 79 begin = estacks + layout[k].begin; 80 end = estacks + layout[k].end; 81 regs = (struct pt_regs *)end - 1; 82 83 if (stk < begin || stk >= end) 84 continue; 85 86 info->type = STACK_TYPE_EXCEPTION + k; 87 info->begin = (unsigned long *)begin; 88 info->end = (unsigned long *)end; 89 info->next_sp = (unsigned long *)regs->sp; 90 91 return true; 92 } 93 94 return false; 95 } 96 97 static bool in_irq_stack(unsigned long *stack, struct stack_info *info) 98 { 99 unsigned long *end = (unsigned long *)this_cpu_read(irq_stack_ptr); 100 unsigned long *begin = end - (IRQ_STACK_SIZE / sizeof(long)); 101 102 /* 103 * This is a software stack, so 'end' can be a valid stack pointer. 104 * It just means the stack is empty. 105 */ 106 if (stack < begin || stack >= end) 107 return false; 108 109 info->type = STACK_TYPE_IRQ; 110 info->begin = begin; 111 info->end = end; 112 113 /* 114 * The next stack pointer is the first thing pushed by the entry code 115 * after switching to the irq stack. 116 */ 117 info->next_sp = (unsigned long *)*(end - 1); 118 119 return true; 120 } 121 122 int get_stack_info(unsigned long *stack, struct task_struct *task, 123 struct stack_info *info, unsigned long *visit_mask) 124 { 125 if (!stack) 126 goto unknown; 127 128 task = task ? : current; 129 130 if (in_task_stack(stack, task, info)) 131 goto recursion_check; 132 133 if (task != current) 134 goto unknown; 135 136 if (in_exception_stack(stack, info)) 137 goto recursion_check; 138 139 if (in_irq_stack(stack, info)) 140 goto recursion_check; 141 142 if (in_entry_stack(stack, info)) 143 goto recursion_check; 144 145 goto unknown; 146 147 recursion_check: 148 /* 149 * Make sure we don't iterate through any given stack more than once. 150 * If it comes up a second time then there's something wrong going on: 151 * just break out and report an unknown stack type. 152 */ 153 if (visit_mask) { 154 if (*visit_mask & (1UL << info->type)) { 155 printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type); 156 goto unknown; 157 } 158 *visit_mask |= 1UL << info->type; 159 } 160 161 return 0; 162 163 unknown: 164 info->type = STACK_TYPE_UNKNOWN; 165 return -EINVAL; 166 } 167