Branch data Line data Source code
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 : 13 : const char *stack_type_name(enum stack_type type) 32 : : { 33 : 13 : BUILD_BUG_ON(N_EXCEPTION_STACKS != 6); 34 : : 35 [ + - ]: 13 : if (type == STACK_TYPE_IRQ) 36 : : return "IRQ"; 37 : : 38 [ + - ]: 13 : 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 [ - + ]: 13 : if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST) 48 : 0 : return exception_stack_names[type - STACK_TYPE_EXCEPTION]; 49 : : 50 : : return NULL; 51 : : } 52 : : 53 : : /** 54 : : * struct estack_pages - Page descriptor for exception stacks 55 : : * @offs: Offset from the start of the exception stack area 56 : : * @size: Size of the exception stack 57 : : * @type: Type to store in the stack_info struct 58 : : */ 59 : : struct estack_pages { 60 : : u32 offs; 61 : : u16 size; 62 : : u16 type; 63 : : }; 64 : : 65 : : #define EPAGERANGE(st) \ 66 : : [PFN_DOWN(CEA_ESTACK_OFFS(st)) ... \ 67 : : PFN_DOWN(CEA_ESTACK_OFFS(st) + CEA_ESTACK_SIZE(st) - 1)] = { \ 68 : : .offs = CEA_ESTACK_OFFS(st), \ 69 : : .size = CEA_ESTACK_SIZE(st), \ 70 : : .type = STACK_TYPE_EXCEPTION + ESTACK_ ##st, } 71 : : 72 : : /* 73 : : * Array of exception stack page descriptors. If the stack is larger than 74 : : * PAGE_SIZE, all pages covering a particular stack will have the same 75 : : * info. The guard pages including the not mapped DB2 stack are zeroed 76 : : * out. 77 : : */ 78 : : static const 79 : : struct estack_pages estack_pages[CEA_ESTACK_PAGES] ____cacheline_aligned = { 80 : : EPAGERANGE(DF), 81 : : EPAGERANGE(NMI), 82 : : EPAGERANGE(DB1), 83 : : EPAGERANGE(DB), 84 : : EPAGERANGE(MCE), 85 : : }; 86 : : 87 : 0 : static bool in_exception_stack(unsigned long *stack, struct stack_info *info) 88 : : { 89 : 0 : unsigned long begin, end, stk = (unsigned long)stack; 90 : 0 : const struct estack_pages *ep; 91 : 0 : struct pt_regs *regs; 92 : 0 : unsigned int k; 93 : : 94 : 0 : BUILD_BUG_ON(N_EXCEPTION_STACKS != 6); 95 : : 96 [ # # ]: 0 : begin = (unsigned long)__this_cpu_read(cea_exception_stacks); 97 : : /* 98 : : * Handle the case where stack trace is collected _before_ 99 : : * cea_exception_stacks had been initialized. 100 : : */ 101 [ # # ]: 0 : if (!begin) 102 : : return false; 103 : : 104 : 0 : end = begin + sizeof(struct cea_exception_stacks); 105 : : /* Bail if @stack is outside the exception stack area. */ 106 [ # # ]: 0 : if (stk < begin || stk >= end) 107 : : return false; 108 : : 109 : : /* Calc page offset from start of exception stacks */ 110 : 0 : k = (stk - begin) >> PAGE_SHIFT; 111 : : /* Lookup the page descriptor */ 112 : 0 : ep = &estack_pages[k]; 113 : : /* Guard page? */ 114 [ # # ]: 0 : if (!ep->size) 115 : : return false; 116 : : 117 : 0 : begin += (unsigned long)ep->offs; 118 : 0 : end = begin + (unsigned long)ep->size; 119 : 0 : regs = (struct pt_regs *)end - 1; 120 : : 121 : 0 : info->type = ep->type; 122 : 0 : info->begin = (unsigned long *)begin; 123 : 0 : info->end = (unsigned long *)end; 124 : 0 : info->next_sp = (unsigned long *)regs->sp; 125 : 0 : return true; 126 : : } 127 : : 128 : 0 : static bool in_irq_stack(unsigned long *stack, struct stack_info *info) 129 : : { 130 : 0 : unsigned long *end = (unsigned long *)this_cpu_read(hardirq_stack_ptr); 131 : 0 : unsigned long *begin = end - (IRQ_STACK_SIZE / sizeof(long)); 132 : : 133 : : /* 134 : : * This is a software stack, so 'end' can be a valid stack pointer. 135 : : * It just means the stack is empty. 136 : : */ 137 [ # # ]: 0 : if (stack < begin || stack >= end) 138 : : return false; 139 : : 140 : 0 : info->type = STACK_TYPE_IRQ; 141 : 0 : info->begin = begin; 142 : 0 : info->end = end; 143 : : 144 : : /* 145 : : * The next stack pointer is the first thing pushed by the entry code 146 : : * after switching to the irq stack. 147 : : */ 148 : 0 : info->next_sp = (unsigned long *)*(end - 1); 149 : : 150 : 0 : return true; 151 : : } 152 : : 153 : 68487 : int get_stack_info(unsigned long *stack, struct task_struct *task, 154 : : struct stack_info *info, unsigned long *visit_mask) 155 : : { 156 [ - + ]: 68487 : if (!stack) 157 : 0 : goto unknown; 158 : : 159 [ - + ]: 68487 : task = task ? : current; 160 : : 161 [ + - ]: 68487 : if (in_task_stack(stack, task, info)) 162 : 68487 : goto recursion_check; 163 : : 164 [ # # ]: 0 : if (task != current) 165 : 0 : goto unknown; 166 : : 167 [ # # ]: 0 : if (in_exception_stack(stack, info)) 168 : 0 : goto recursion_check; 169 : : 170 : 0 : if (in_irq_stack(stack, info)) 171 : 0 : goto recursion_check; 172 : : 173 [ # # ]: 0 : if (in_entry_stack(stack, info)) 174 : 0 : goto recursion_check; 175 : : 176 : 0 : goto unknown; 177 : : 178 : 68487 : recursion_check: 179 : : /* 180 : : * Make sure we don't iterate through any given stack more than once. 181 : : * If it comes up a second time then there's something wrong going on: 182 : : * just break out and report an unknown stack type. 183 : : */ 184 [ + - ]: 68487 : if (visit_mask) { 185 [ - + ]: 68487 : if (*visit_mask & (1UL << info->type)) { 186 [ # # ]: 0 : printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type); 187 : 0 : goto unknown; 188 : : } 189 : 68487 : *visit_mask |= 1UL << info->type; 190 : : } 191 : : 192 : : return 0; 193 : : 194 : 0 : unknown: 195 : 0 : info->type = STACK_TYPE_UNKNOWN; 196 : 0 : return -EINVAL; 197 : : }