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/stacktrace.h> |
20 | |
21 | const char *stack_type_name(enum stack_type type) |
22 | { |
23 | if (type == STACK_TYPE_IRQ) |
24 | return "IRQ" ; |
25 | |
26 | if (type == STACK_TYPE_SOFTIRQ) |
27 | return "SOFTIRQ" ; |
28 | |
29 | if (type == STACK_TYPE_ENTRY) |
30 | return "ENTRY_TRAMPOLINE" ; |
31 | |
32 | if (type == STACK_TYPE_EXCEPTION) |
33 | return "#DF" ; |
34 | |
35 | return NULL; |
36 | } |
37 | |
38 | static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info) |
39 | { |
40 | unsigned long *begin = (unsigned long *)this_cpu_read(pcpu_hot.hardirq_stack_ptr); |
41 | unsigned long *end = begin + (THREAD_SIZE / sizeof(long)); |
42 | |
43 | /* |
44 | * This is a software stack, so 'end' can be a valid stack pointer. |
45 | * It just means the stack is empty. |
46 | */ |
47 | if (stack < begin || stack > end) |
48 | return false; |
49 | |
50 | info->type = STACK_TYPE_IRQ; |
51 | info->begin = begin; |
52 | info->end = end; |
53 | |
54 | /* |
55 | * See irq_32.c -- the next stack pointer is stored at the beginning of |
56 | * the stack. |
57 | */ |
58 | info->next_sp = (unsigned long *)*begin; |
59 | |
60 | return true; |
61 | } |
62 | |
63 | static bool in_softirq_stack(unsigned long *stack, struct stack_info *info) |
64 | { |
65 | unsigned long *begin = (unsigned long *)this_cpu_read(pcpu_hot.softirq_stack_ptr); |
66 | unsigned long *end = begin + (THREAD_SIZE / sizeof(long)); |
67 | |
68 | /* |
69 | * This is a software stack, so 'end' can be a valid stack pointer. |
70 | * It just means the stack is empty. |
71 | */ |
72 | if (stack < begin || stack > end) |
73 | return false; |
74 | |
75 | info->type = STACK_TYPE_SOFTIRQ; |
76 | info->begin = begin; |
77 | info->end = end; |
78 | |
79 | /* |
80 | * The next stack pointer is stored at the beginning of the stack. |
81 | * See irq_32.c. |
82 | */ |
83 | info->next_sp = (unsigned long *)*begin; |
84 | |
85 | return true; |
86 | } |
87 | |
88 | static bool in_doublefault_stack(unsigned long *stack, struct stack_info *info) |
89 | { |
90 | struct cpu_entry_area *cea = get_cpu_entry_area(raw_smp_processor_id()); |
91 | struct doublefault_stack *ss = &cea->doublefault_stack; |
92 | |
93 | void *begin = ss->stack; |
94 | void *end = begin + sizeof(ss->stack); |
95 | |
96 | if ((void *)stack < begin || (void *)stack >= end) |
97 | return false; |
98 | |
99 | info->type = STACK_TYPE_EXCEPTION; |
100 | info->begin = begin; |
101 | info->end = end; |
102 | info->next_sp = (unsigned long *)this_cpu_read(cpu_tss_rw.x86_tss.sp); |
103 | |
104 | return true; |
105 | } |
106 | |
107 | |
108 | int get_stack_info(unsigned long *stack, struct task_struct *task, |
109 | struct stack_info *info, unsigned long *visit_mask) |
110 | { |
111 | if (!stack) |
112 | goto unknown; |
113 | |
114 | task = task ? : current; |
115 | |
116 | if (in_task_stack(stack, task, info)) |
117 | goto recursion_check; |
118 | |
119 | if (task != current) |
120 | goto unknown; |
121 | |
122 | if (in_entry_stack(stack, info)) |
123 | goto recursion_check; |
124 | |
125 | if (in_hardirq_stack(stack, info)) |
126 | goto recursion_check; |
127 | |
128 | if (in_softirq_stack(stack, info)) |
129 | goto recursion_check; |
130 | |
131 | if (in_doublefault_stack(stack, info)) |
132 | goto recursion_check; |
133 | |
134 | goto unknown; |
135 | |
136 | recursion_check: |
137 | /* |
138 | * Make sure we don't iterate through any given stack more than once. |
139 | * If it comes up a second time then there's something wrong going on: |
140 | * just break out and report an unknown stack type. |
141 | */ |
142 | if (visit_mask) { |
143 | if (*visit_mask & (1UL << info->type)) { |
144 | printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n" , info->type); |
145 | goto unknown; |
146 | } |
147 | *visit_mask |= 1UL << info->type; |
148 | } |
149 | |
150 | return 0; |
151 | |
152 | unknown: |
153 | info->type = STACK_TYPE_UNKNOWN; |
154 | return -EINVAL; |
155 | } |
156 | |