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