1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2ecea4ab6SPaul Gortmaker #include <linux/export.h> 3fed240d9SMasami Hiramatsu #include <linux/kprobes.h> 4f16fb1ecSRussell King #include <linux/sched.h> 5b17b0153SIngo Molnar #include <linux/sched/debug.h> 6f16fb1ecSRussell King #include <linux/stacktrace.h> 7f16fb1ecSRussell King 8c6089061SRussell King #include <asm/sections.h> 92d7c11bfSCatalin Marinas #include <asm/stacktrace.h> 1007b40341SRussell King #include <asm/traps.h> 11f16fb1ecSRussell King 125854e4d8SLi Huafei #include "reboot.h" 135854e4d8SLi Huafei 142d7c11bfSCatalin Marinas #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) 152d7c11bfSCatalin Marinas /* 162d7c11bfSCatalin Marinas * Unwind the current stack frame and store the new register values in the 172d7c11bfSCatalin Marinas * structure passed as argument. Unwinding is equivalent to a function return, 182d7c11bfSCatalin Marinas * hence the new PC value rather than LR should be used for backtrace. 192d7c11bfSCatalin Marinas * 202d7c11bfSCatalin Marinas * With framepointer enabled, a simple function prologue looks like this: 212d7c11bfSCatalin Marinas * mov ip, sp 222d7c11bfSCatalin Marinas * stmdb sp!, {fp, ip, lr, pc} 232d7c11bfSCatalin Marinas * sub fp, ip, #4 242d7c11bfSCatalin Marinas * 252d7c11bfSCatalin Marinas * A simple function epilogue looks like this: 262d7c11bfSCatalin Marinas * ldm sp, {fp, sp, pc} 272d7c11bfSCatalin Marinas * 28b4d5ec9bSNathan Huckleberry * When compiled with clang, pc and sp are not pushed. A simple function 29b4d5ec9bSNathan Huckleberry * prologue looks like this when built with clang: 30b4d5ec9bSNathan Huckleberry * 31b4d5ec9bSNathan Huckleberry * stmdb {..., fp, lr} 32b4d5ec9bSNathan Huckleberry * add fp, sp, #x 33b4d5ec9bSNathan Huckleberry * sub sp, sp, #y 34b4d5ec9bSNathan Huckleberry * 35b4d5ec9bSNathan Huckleberry * A simple function epilogue looks like this when built with clang: 36b4d5ec9bSNathan Huckleberry * 37b4d5ec9bSNathan Huckleberry * sub sp, fp, #x 38b4d5ec9bSNathan Huckleberry * ldm {..., fp, pc} 39b4d5ec9bSNathan Huckleberry * 40b4d5ec9bSNathan Huckleberry * 412d7c11bfSCatalin Marinas * Note that with framepointer enabled, even the leaf functions have the same 422d7c11bfSCatalin Marinas * prologue and epilogue, therefore we can ignore the LR value in this case. 432d7c11bfSCatalin Marinas */ 445854e4d8SLi Huafei 455854e4d8SLi Huafei extern unsigned long call_with_stack_end; 465854e4d8SLi Huafei 475854e4d8SLi Huafei static int frame_pointer_check(struct stackframe *frame) 482d7c11bfSCatalin Marinas { 492d7c11bfSCatalin Marinas unsigned long high, low; 502d7c11bfSCatalin Marinas unsigned long fp = frame->fp; 515854e4d8SLi Huafei unsigned long pc = frame->pc; 525854e4d8SLi Huafei 535854e4d8SLi Huafei /* 545854e4d8SLi Huafei * call_with_stack() is the only place we allow SP to jump from one 555854e4d8SLi Huafei * stack to another, with FP and SP pointing to different stacks, 565854e4d8SLi Huafei * skipping the FP boundary check at this point. 575854e4d8SLi Huafei */ 585854e4d8SLi Huafei if (pc >= (unsigned long)&call_with_stack && 595854e4d8SLi Huafei pc < (unsigned long)&call_with_stack_end) 605854e4d8SLi Huafei return 0; 612d7c11bfSCatalin Marinas 622d7c11bfSCatalin Marinas /* only go to a higher address on the stack */ 632d7c11bfSCatalin Marinas low = frame->sp; 64d33aadbfSWill Deacon high = ALIGN(low, THREAD_SIZE); 652d7c11bfSCatalin Marinas 66b4d5ec9bSNathan Huckleberry /* check current frame pointer is within bounds */ 675854e4d8SLi Huafei #ifdef CONFIG_CC_IS_CLANG 68b4d5ec9bSNathan Huckleberry if (fp < low + 4 || fp > high - 4) 69b4d5ec9bSNathan Huckleberry return -EINVAL; 705854e4d8SLi Huafei #else 715854e4d8SLi Huafei if (fp < low + 12 || fp > high - 4) 725854e4d8SLi Huafei return -EINVAL; 735854e4d8SLi Huafei #endif 74b4d5ec9bSNathan Huckleberry 755854e4d8SLi Huafei return 0; 765854e4d8SLi Huafei } 775854e4d8SLi Huafei 785854e4d8SLi Huafei int notrace unwind_frame(struct stackframe *frame) 795854e4d8SLi Huafei { 805854e4d8SLi Huafei unsigned long fp = frame->fp; 815854e4d8SLi Huafei 825854e4d8SLi Huafei if (frame_pointer_check(frame)) 835854e4d8SLi Huafei return -EINVAL; 845854e4d8SLi Huafei 85*752ec621SLi Huafei /* 86*752ec621SLi Huafei * When we unwind through an exception stack, include the saved PC 87*752ec621SLi Huafei * value into the stack trace. 88*752ec621SLi Huafei */ 89*752ec621SLi Huafei if (frame->ex_frame) { 90*752ec621SLi Huafei struct pt_regs *regs = (struct pt_regs *)frame->sp; 91*752ec621SLi Huafei 92*752ec621SLi Huafei /* 93*752ec621SLi Huafei * We check that 'regs + sizeof(struct pt_regs)' (that is, 94*752ec621SLi Huafei * ®s[1]) does not exceed the bottom of the stack to avoid 95*752ec621SLi Huafei * accessing data outside the task's stack. This may happen 96*752ec621SLi Huafei * when frame->ex_frame is a false positive. 97*752ec621SLi Huafei */ 98*752ec621SLi Huafei if ((unsigned long)®s[1] > ALIGN(frame->sp, THREAD_SIZE)) 99*752ec621SLi Huafei return -EINVAL; 100*752ec621SLi Huafei 101*752ec621SLi Huafei frame->pc = regs->ARM_pc; 102*752ec621SLi Huafei frame->ex_frame = false; 103*752ec621SLi Huafei return 0; 104*752ec621SLi Huafei } 105*752ec621SLi Huafei 1065854e4d8SLi Huafei /* restore the registers from the stack frame */ 1075854e4d8SLi Huafei #ifdef CONFIG_CC_IS_CLANG 108b4d5ec9bSNathan Huckleberry frame->sp = frame->fp; 1099be4c88bSlinyujun frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); 1109be4c88bSlinyujun frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4)); 111b4d5ec9bSNathan Huckleberry #else 1129be4c88bSlinyujun frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 12)); 1139be4c88bSlinyujun frame->sp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 8)); 1149be4c88bSlinyujun frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 4)); 115b4d5ec9bSNathan Huckleberry #endif 116fed240d9SMasami Hiramatsu #ifdef CONFIG_KRETPROBES 117fed240d9SMasami Hiramatsu if (is_kretprobe_trampoline(frame->pc)) 118fed240d9SMasami Hiramatsu frame->pc = kretprobe_find_ret_addr(frame->tsk, 119fed240d9SMasami Hiramatsu (void *)frame->fp, &frame->kr_cur); 120fed240d9SMasami Hiramatsu #endif 1212d7c11bfSCatalin Marinas 122*752ec621SLi Huafei if (in_entry_text(frame->pc)) 123*752ec621SLi Huafei frame->ex_frame = true; 124*752ec621SLi Huafei 1252d7c11bfSCatalin Marinas return 0; 1262d7c11bfSCatalin Marinas } 1272d7c11bfSCatalin Marinas #endif 1282d7c11bfSCatalin Marinas 1294bf1fa5aSUwe Kleine-König void notrace walk_stackframe(struct stackframe *frame, 130f16fb1ecSRussell King int (*fn)(struct stackframe *, void *), void *data) 131f16fb1ecSRussell King { 1322d7c11bfSCatalin Marinas while (1) { 1332d7c11bfSCatalin Marinas int ret; 134f16fb1ecSRussell King 135f16fb1ecSRussell King if (fn(frame, data)) 136f16fb1ecSRussell King break; 1372d7c11bfSCatalin Marinas ret = unwind_frame(frame); 1382d7c11bfSCatalin Marinas if (ret < 0) 1392d7c11bfSCatalin Marinas break; 1402d7c11bfSCatalin Marinas } 141f16fb1ecSRussell King } 1427b104bcbSAl Viro EXPORT_SYMBOL(walk_stackframe); 143f16fb1ecSRussell King 144f16fb1ecSRussell King #ifdef CONFIG_STACKTRACE 145f16fb1ecSRussell King struct stack_trace_data { 146f16fb1ecSRussell King struct stack_trace *trace; 147f76e9154SNicolas Pitre unsigned int no_sched_functions; 148f16fb1ecSRussell King unsigned int skip; 149f16fb1ecSRussell King }; 150f16fb1ecSRussell King 151f16fb1ecSRussell King static int save_trace(struct stackframe *frame, void *d) 152f16fb1ecSRussell King { 153f16fb1ecSRussell King struct stack_trace_data *data = d; 154f16fb1ecSRussell King struct stack_trace *trace = data->trace; 1552d7c11bfSCatalin Marinas unsigned long addr = frame->pc; 156f16fb1ecSRussell King 157f76e9154SNicolas Pitre if (data->no_sched_functions && in_sched_functions(addr)) 158f76e9154SNicolas Pitre return 0; 159f16fb1ecSRussell King if (data->skip) { 160f16fb1ecSRussell King data->skip--; 161f16fb1ecSRussell King return 0; 162f16fb1ecSRussell King } 163f16fb1ecSRussell King 164f76e9154SNicolas Pitre trace->entries[trace->nr_entries++] = addr; 165f16fb1ecSRussell King return trace->nr_entries >= trace->max_entries; 166f16fb1ecSRussell King } 167f16fb1ecSRussell King 1683683f44cSRussell King /* This must be noinline to so that our skip calculation works correctly */ 1693683f44cSRussell King static noinline void __save_stack_trace(struct task_struct *tsk, 1703683f44cSRussell King struct stack_trace *trace, unsigned int nosched) 171f16fb1ecSRussell King { 172f16fb1ecSRussell King struct stack_trace_data data; 1732d7c11bfSCatalin Marinas struct stackframe frame; 174f16fb1ecSRussell King 175f16fb1ecSRussell King data.trace = trace; 176f16fb1ecSRussell King data.skip = trace->skip; 1773683f44cSRussell King data.no_sched_functions = nosched; 178f76e9154SNicolas Pitre 179f76e9154SNicolas Pitre if (tsk != current) { 180f76e9154SNicolas Pitre #ifdef CONFIG_SMP 181f76e9154SNicolas Pitre /* 182d5996b2fSRussell King * What guarantees do we have here that 'tsk' is not 183d5996b2fSRussell King * running on another CPU? For now, ignore it as we 184d5996b2fSRussell King * can't guarantee we won't explode. 185f76e9154SNicolas Pitre */ 186d5996b2fSRussell King return; 187f76e9154SNicolas Pitre #else 1882d7c11bfSCatalin Marinas frame.fp = thread_saved_fp(tsk); 1892d7c11bfSCatalin Marinas frame.sp = thread_saved_sp(tsk); 1902d7c11bfSCatalin Marinas frame.lr = 0; /* recovered from the stack */ 1912d7c11bfSCatalin Marinas frame.pc = thread_saved_pc(tsk); 192f76e9154SNicolas Pitre #endif 193f76e9154SNicolas Pitre } else { 1943683f44cSRussell King /* We don't want this function nor the caller */ 1953683f44cSRussell King data.skip += 2; 1962d7c11bfSCatalin Marinas frame.fp = (unsigned long)__builtin_frame_address(0); 19774dbeee0SBehan Webster frame.sp = current_stack_pointer; 1982d7c11bfSCatalin Marinas frame.lr = (unsigned long)__builtin_return_address(0); 199c46c2c9bSRussell King (Oracle) here: 200c46c2c9bSRussell King (Oracle) frame.pc = (unsigned long)&&here; 201f76e9154SNicolas Pitre } 202fed240d9SMasami Hiramatsu #ifdef CONFIG_KRETPROBES 203fed240d9SMasami Hiramatsu frame.kr_cur = NULL; 204fed240d9SMasami Hiramatsu frame.tsk = tsk; 205fed240d9SMasami Hiramatsu #endif 206*752ec621SLi Huafei #ifdef CONFIG_UNWINDER_FRAME_POINTER 207*752ec621SLi Huafei frame.ex_frame = false; 208*752ec621SLi Huafei #endif 209f16fb1ecSRussell King 2102d7c11bfSCatalin Marinas walk_stackframe(&frame, save_trace, &data); 211f76e9154SNicolas Pitre } 212f76e9154SNicolas Pitre 2139c986661SLin Yongting void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) 2149c986661SLin Yongting { 2159c986661SLin Yongting struct stack_trace_data data; 2169c986661SLin Yongting struct stackframe frame; 2179c986661SLin Yongting 2189c986661SLin Yongting data.trace = trace; 2199c986661SLin Yongting data.skip = trace->skip; 2209c986661SLin Yongting data.no_sched_functions = 0; 2219c986661SLin Yongting 2229c986661SLin Yongting frame.fp = regs->ARM_fp; 2239c986661SLin Yongting frame.sp = regs->ARM_sp; 2249c986661SLin Yongting frame.lr = regs->ARM_lr; 2259c986661SLin Yongting frame.pc = regs->ARM_pc; 226fed240d9SMasami Hiramatsu #ifdef CONFIG_KRETPROBES 227fed240d9SMasami Hiramatsu frame.kr_cur = NULL; 228fed240d9SMasami Hiramatsu frame.tsk = current; 229fed240d9SMasami Hiramatsu #endif 230*752ec621SLi Huafei #ifdef CONFIG_UNWINDER_FRAME_POINTER 231*752ec621SLi Huafei frame.ex_frame = in_entry_text(frame.pc); 232*752ec621SLi Huafei #endif 2339c986661SLin Yongting 2349c986661SLin Yongting walk_stackframe(&frame, save_trace, &data); 2359c986661SLin Yongting } 2369c986661SLin Yongting 2373683f44cSRussell King void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 2383683f44cSRussell King { 2393683f44cSRussell King __save_stack_trace(tsk, trace, 1); 2403683f44cSRussell King } 2419a3dc318SDustin Brown EXPORT_SYMBOL(save_stack_trace_tsk); 2423683f44cSRussell King 243f76e9154SNicolas Pitre void save_stack_trace(struct stack_trace *trace) 244f76e9154SNicolas Pitre { 2453683f44cSRussell King __save_stack_trace(current, trace, 0); 246f16fb1ecSRussell King } 2477b4c9505SIngo Molnar EXPORT_SYMBOL_GPL(save_stack_trace); 248f16fb1ecSRussell King #endif 249