1
2
3
4
5#include <linux/kallsyms.h>
6#include <linux/kprobes.h>
7#include <linux/uaccess.h>
8#include <linux/hardirq.h>
9#include <linux/kdebug.h>
10#include <linux/module.h>
11#include <linux/ptrace.h>
12#include <linux/kexec.h>
13#include <linux/sysfs.h>
14#include <linux/bug.h>
15#include <linux/nmi.h>
16
17#include <asm/stacktrace.h>
18
19static char *exception_stack_names[N_EXCEPTION_STACKS] = {
20 [ DOUBLEFAULT_STACK-1 ] = "#DF",
21 [ NMI_STACK-1 ] = "NMI",
22 [ DEBUG_STACK-1 ] = "#DB",
23 [ MCE_STACK-1 ] = "#MC",
24};
25
26static unsigned long exception_stack_sizes[N_EXCEPTION_STACKS] = {
27 [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STKSZ,
28 [DEBUG_STACK - 1] = DEBUG_STKSZ
29};
30
31void stack_type_str(enum stack_type type, const char **begin, const char **end)
32{
33 BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
34
35 switch (type) {
36 case STACK_TYPE_IRQ:
37 *begin = "IRQ";
38 *end = "EOI";
39 break;
40 case STACK_TYPE_EXCEPTION ... STACK_TYPE_EXCEPTION_LAST:
41 *begin = exception_stack_names[type - STACK_TYPE_EXCEPTION];
42 *end = "EOE";
43 break;
44 default:
45 *begin = NULL;
46 *end = NULL;
47 }
48}
49
50static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
51{
52 unsigned long *begin, *end;
53 struct pt_regs *regs;
54 unsigned k;
55
56 BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
57
58 for (k = 0; k < N_EXCEPTION_STACKS; k++) {
59 end = (unsigned long *)__this_cpu_ptr(&orig_ist)->ist[k];
60 begin = end - (exception_stack_sizes[k] / sizeof(long));
61 regs = (struct pt_regs *)end - 1;
62
63 if (stack <= begin || stack >= end)
64 continue;
65
66 info->type = STACK_TYPE_EXCEPTION + k;
67 info->begin = begin;
68 info->end = end;
69 info->next_sp = (unsigned long *)regs->sp;
70
71 return true;
72 }
73
74 return false;
75}
76
77static bool in_irq_stack(unsigned long *stack, struct stack_info *info)
78{
79 unsigned long *end = (unsigned long *)this_cpu_read(irq_stack_ptr);
80 unsigned long *begin = end - (IRQ_STACK_SIZE / sizeof(long));
81
82
83
84
85
86 if (stack <= begin || stack > end)
87 return false;
88
89 info->type = STACK_TYPE_IRQ;
90 info->begin = begin;
91 info->end = end;
92
93
94
95
96
97 info->next_sp = (unsigned long *)*(end - 1);
98
99 return true;
100}
101
102int get_stack_info(unsigned long *stack, struct task_struct *task,
103 struct stack_info *info, unsigned long *visit_mask)
104{
105 if (!stack)
106 goto unknown;
107
108 task = task ? : current;
109
110 if (in_task_stack(stack, task, info))
111 goto recursion_check;
112
113 if (task != current)
114 goto unknown;
115
116 if (in_exception_stack(stack, info))
117 goto recursion_check;
118
119 if (in_irq_stack(stack, info))
120 goto recursion_check;
121
122 goto unknown;
123
124recursion_check:
125
126
127
128
129
130 if (visit_mask) {
131 if (*visit_mask & (1UL << info->type))
132 goto unknown;
133 *visit_mask |= 1UL << info->type;
134 }
135
136 return 0;
137
138unknown:
139 info->type = STACK_TYPE_UNKNOWN;
140 return -EINVAL;
141}
142
143void show_regs(struct pt_regs *regs)
144{
145 int i;
146
147 show_regs_print_info(KERN_DEFAULT);
148 __show_regs(regs, 1);
149
150
151
152
153
154 if (!user_mode(regs)) {
155 unsigned int code_prologue = code_bytes * 43 / 64;
156 unsigned int code_len = code_bytes;
157 unsigned char c;
158 u8 *ip;
159
160 show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
161
162 printk(KERN_DEFAULT "Code: ");
163
164 ip = (u8 *)regs->ip - code_prologue;
165 if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
166
167 ip = (u8 *)regs->ip;
168 code_len = code_len - code_prologue + 1;
169 }
170 for (i = 0; i < code_len; i++, ip++) {
171 if (ip < (u8 *)PAGE_OFFSET ||
172 probe_kernel_address(ip, c)) {
173 pr_cont(" Bad RIP value.");
174 break;
175 }
176 if (ip == (u8 *)regs->ip)
177 pr_cont("<%02x> ", c);
178 else
179 pr_cont("%02x ", c);
180 }
181 }
182 pr_cont("\n");
183}
184
185int is_valid_bugaddr(unsigned long ip)
186{
187 unsigned short ud2;
188
189 if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2)))
190 return 0;
191
192 return ud2 == 0x0b0f;
193}
194