blob: 9c625257023d295cc0d5946ca1186a2792e10a06 [file] [log] [blame]
Thomas Gleixner457c8992019-05-19 13:08:55 +01001// SPDX-License-Identifier: GPL-2.0-only
Ingo Molnar8637c092006-07-03 00:24:38 -07002/*
3 * kernel/stacktrace.c
4 *
5 * Stack trace management functions
6 *
7 * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
8 */
Thomas Gleixner214d8ca2019-04-25 11:45:21 +02009#include <linux/sched/task_stack.h>
10#include <linux/sched/debug.h>
Ingo Molnar8637c092006-07-03 00:24:38 -070011#include <linux/sched.h>
Ingo Molnar9212ddb2008-12-25 11:21:20 +010012#include <linux/kernel.h>
Paul Gortmaker9984de12011-05-23 14:51:41 -040013#include <linux/export.h>
Ingo Molnar8637c092006-07-03 00:24:38 -070014#include <linux/kallsyms.h>
15#include <linux/stacktrace.h>
Marco Elverf39f21b2021-11-05 13:45:25 -070016#include <linux/interrupt.h>
Ingo Molnar8637c092006-07-03 00:24:38 -070017
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020018/**
19 * stack_trace_print - Print the entries in the stack trace
20 * @entries: Pointer to storage array
21 * @nr_entries: Number of entries in the storage array
22 * @spaces: Number of leading spaces to print
23 */
Bart Van Asschea2970422019-07-22 11:24:41 -070024void stack_trace_print(const unsigned long *entries, unsigned int nr_entries,
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020025 int spaces)
Ingo Molnar8637c092006-07-03 00:24:38 -070026{
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020027 unsigned int i;
Ingo Molnar8637c092006-07-03 00:24:38 -070028
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020029 if (WARN_ON(!entries))
Johannes Bergbfeeeeb2008-05-12 21:21:14 +020030 return;
31
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020032 for (i = 0; i < nr_entries; i++)
33 printk("%*c%pS\n", 1 + spaces, ' ', (void *)entries[i]);
34}
35EXPORT_SYMBOL_GPL(stack_trace_print);
36
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020037/**
38 * stack_trace_snprint - Print the entries in the stack trace into a buffer
39 * @buf: Pointer to the print buffer
40 * @size: Size of the print buffer
41 * @entries: Pointer to storage array
42 * @nr_entries: Number of entries in the storage array
43 * @spaces: Number of leading spaces to print
44 *
45 * Return: Number of bytes printed.
46 */
Bart Van Asschea2970422019-07-22 11:24:41 -070047int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries,
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020048 unsigned int nr_entries, int spaces)
Joonsoo Kim9a92a6c2014-12-12 16:55:58 -080049{
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020050 unsigned int generated, i, total = 0;
Joonsoo Kim9a92a6c2014-12-12 16:55:58 -080051
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020052 if (WARN_ON(!entries))
Joonsoo Kim9a92a6c2014-12-12 16:55:58 -080053 return 0;
54
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020055 for (i = 0; i < nr_entries && size; i++) {
Omar Sandovalbfeda412017-02-07 15:33:20 -080056 generated = snprintf(buf, size, "%*c%pS\n", 1 + spaces, ' ',
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020057 (void *)entries[i]);
Joonsoo Kim9a92a6c2014-12-12 16:55:58 -080058
59 total += generated;
Joonsoo Kim9a92a6c2014-12-12 16:55:58 -080060 if (generated >= size) {
61 buf += size;
62 size = 0;
63 } else {
64 buf += generated;
65 size -= generated;
66 }
67 }
68
69 return total;
70}
Thomas Gleixnere9b98e12019-04-25 11:44:55 +020071EXPORT_SYMBOL_GPL(stack_trace_snprint);
72
Thomas Gleixner214d8ca2019-04-25 11:45:21 +020073#ifdef CONFIG_ARCH_STACKWALK
74
75struct stacktrace_cookie {
76 unsigned long *store;
77 unsigned int size;
78 unsigned int skip;
79 unsigned int len;
80};
81
Mark Brown264c03a2020-09-14 16:34:07 +010082static bool stack_trace_consume_entry(void *cookie, unsigned long addr)
Thomas Gleixner214d8ca2019-04-25 11:45:21 +020083{
84 struct stacktrace_cookie *c = cookie;
85
86 if (c->len >= c->size)
87 return false;
88
89 if (c->skip > 0) {
90 c->skip--;
91 return true;
92 }
93 c->store[c->len++] = addr;
94 return c->len < c->size;
95}
96
Mark Brown264c03a2020-09-14 16:34:07 +010097static bool stack_trace_consume_entry_nosched(void *cookie, unsigned long addr)
Thomas Gleixner214d8ca2019-04-25 11:45:21 +020098{
99 if (in_sched_functions(addr))
100 return true;
Mark Brown264c03a2020-09-14 16:34:07 +0100101 return stack_trace_consume_entry(cookie, addr);
Thomas Gleixner214d8ca2019-04-25 11:45:21 +0200102}
103
104/**
105 * stack_trace_save - Save a stack trace into a storage array
106 * @store: Pointer to storage array
107 * @size: Size of the storage array
108 * @skipnr: Number of entries to skip at the start of the stack trace
109 *
110 * Return: Number of trace entries stored.
111 */
112unsigned int stack_trace_save(unsigned long *store, unsigned int size,
113 unsigned int skipnr)
114{
115 stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
116 struct stacktrace_cookie c = {
117 .store = store,
118 .size = size,
119 .skip = skipnr + 1,
120 };
121
122 arch_stack_walk(consume_entry, &c, current, NULL);
123 return c.len;
124}
125EXPORT_SYMBOL_GPL(stack_trace_save);
126
127/**
128 * stack_trace_save_tsk - Save a task stack trace into a storage array
129 * @task: The task to examine
130 * @store: Pointer to storage array
131 * @size: Size of the storage array
132 * @skipnr: Number of entries to skip at the start of the stack trace
133 *
134 * Return: Number of trace entries stored.
135 */
136unsigned int stack_trace_save_tsk(struct task_struct *tsk, unsigned long *store,
137 unsigned int size, unsigned int skipnr)
138{
139 stack_trace_consume_fn consume_entry = stack_trace_consume_entry_nosched;
140 struct stacktrace_cookie c = {
141 .store = store,
142 .size = size,
Jiri Slabyb0c51f12019-10-30 08:25:45 +0100143 /* skip this function if they are tracing us */
Jiri Slaby4b485122019-11-11 10:26:47 +0100144 .skip = skipnr + (current == tsk),
Thomas Gleixner214d8ca2019-04-25 11:45:21 +0200145 };
146
147 if (!try_get_task_stack(tsk))
148 return 0;
149
150 arch_stack_walk(consume_entry, &c, tsk, NULL);
151 put_task_stack(tsk);
152 return c.len;
153}
154
155/**
156 * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array
157 * @regs: Pointer to pt_regs to examine
158 * @store: Pointer to storage array
159 * @size: Size of the storage array
160 * @skipnr: Number of entries to skip at the start of the stack trace
161 *
162 * Return: Number of trace entries stored.
163 */
164unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store,
165 unsigned int size, unsigned int skipnr)
166{
167 stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
168 struct stacktrace_cookie c = {
169 .store = store,
170 .size = size,
171 .skip = skipnr,
172 };
173
174 arch_stack_walk(consume_entry, &c, current, regs);
175 return c.len;
176}
177
178#ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
179/**
180 * stack_trace_save_tsk_reliable - Save task stack with verification
181 * @tsk: Pointer to the task to examine
182 * @store: Pointer to storage array
183 * @size: Size of the storage array
184 *
185 * Return: An error if it detects any unreliable features of the
186 * stack. Otherwise it guarantees that the stack trace is
187 * reliable and returns the number of entries stored.
188 *
189 * If the task is not 'current', the caller *must* ensure the task is inactive.
190 */
191int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store,
192 unsigned int size)
193{
194 stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
195 struct stacktrace_cookie c = {
196 .store = store,
197 .size = size,
198 };
199 int ret;
200
201 /*
202 * If the task doesn't have a stack (e.g., a zombie), the stack is
203 * "reliably" empty.
204 */
205 if (!try_get_task_stack(tsk))
206 return 0;
207
208 ret = arch_stack_walk_reliable(consume_entry, &c, tsk);
209 put_task_stack(tsk);
Joe Lawrence7eaf51a2019-05-17 14:51:17 -0400210 return ret ? ret : c.len;
Thomas Gleixner214d8ca2019-04-25 11:45:21 +0200211}
212#endif
213
214#ifdef CONFIG_USER_STACKTRACE_SUPPORT
215/**
216 * stack_trace_save_user - Save a user space stack trace into a storage array
217 * @store: Pointer to storage array
218 * @size: Size of the storage array
219 *
220 * Return: Number of trace entries stored.
221 */
222unsigned int stack_trace_save_user(unsigned long *store, unsigned int size)
223{
224 stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
225 struct stacktrace_cookie c = {
226 .store = store,
227 .size = size,
228 };
Peter Zijlstracac9b9a2019-07-18 10:47:47 +0200229 mm_segment_t fs;
Thomas Gleixner214d8ca2019-04-25 11:45:21 +0200230
231 /* Trace user stack if not a kernel thread */
Thomas Gleixner7e8e6812019-07-02 17:53:35 +0200232 if (current->flags & PF_KTHREAD)
Thomas Gleixner214d8ca2019-04-25 11:45:21 +0200233 return 0;
234
Christoph Hellwig3d13f312020-08-11 18:33:47 -0700235 fs = force_uaccess_begin();
Thomas Gleixner214d8ca2019-04-25 11:45:21 +0200236 arch_stack_walk_user(consume_entry, &c, task_pt_regs(current));
Christoph Hellwig3d13f312020-08-11 18:33:47 -0700237 force_uaccess_end(fs);
Peter Zijlstracac9b9a2019-07-18 10:47:47 +0200238
Thomas Gleixner214d8ca2019-04-25 11:45:21 +0200239 return c.len;
240}
241#endif
242
243#else /* CONFIG_ARCH_STACKWALK */
244
Ingo Molnar9212ddb2008-12-25 11:21:20 +0100245/*
Josh Poimboeufaf085d92017-02-13 19:42:28 -0600246 * Architectures that do not implement save_stack_trace_*()
247 * get these weak aliases and once-per-bootup warnings
Masami Hiramatsuc624d332011-06-08 16:09:27 +0900248 * (whenever this facility is utilized - for example by procfs):
Ingo Molnar9212ddb2008-12-25 11:21:20 +0100249 */
250__weak void
251save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
252{
253 WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n");
254}
Masami Hiramatsuc624d332011-06-08 16:09:27 +0900255
256__weak void
257save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
258{
259 WARN_ONCE(1, KERN_INFO "save_stack_trace_regs() not implemented yet.\n");
260}
Josh Poimboeufaf085d92017-02-13 19:42:28 -0600261
Thomas Gleixnere9b98e12019-04-25 11:44:55 +0200262/**
263 * stack_trace_save - Save a stack trace into a storage array
264 * @store: Pointer to storage array
265 * @size: Size of the storage array
266 * @skipnr: Number of entries to skip at the start of the stack trace
267 *
268 * Return: Number of trace entries stored
269 */
270unsigned int stack_trace_save(unsigned long *store, unsigned int size,
271 unsigned int skipnr)
272{
273 struct stack_trace trace = {
274 .entries = store,
275 .max_entries = size,
276 .skip = skipnr + 1,
277 };
278
279 save_stack_trace(&trace);
280 return trace.nr_entries;
281}
282EXPORT_SYMBOL_GPL(stack_trace_save);
283
284/**
285 * stack_trace_save_tsk - Save a task stack trace into a storage array
286 * @task: The task to examine
287 * @store: Pointer to storage array
288 * @size: Size of the storage array
289 * @skipnr: Number of entries to skip at the start of the stack trace
290 *
291 * Return: Number of trace entries stored
292 */
293unsigned int stack_trace_save_tsk(struct task_struct *task,
294 unsigned long *store, unsigned int size,
295 unsigned int skipnr)
296{
297 struct stack_trace trace = {
298 .entries = store,
299 .max_entries = size,
Jiri Slabyb0c51f12019-10-30 08:25:45 +0100300 /* skip this function if they are tracing us */
Jiri Slaby4b485122019-11-11 10:26:47 +0100301 .skip = skipnr + (current == task),
Thomas Gleixnere9b98e12019-04-25 11:44:55 +0200302 };
303
304 save_stack_trace_tsk(task, &trace);
305 return trace.nr_entries;
306}
307
308/**
309 * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array
310 * @regs: Pointer to pt_regs to examine
311 * @store: Pointer to storage array
312 * @size: Size of the storage array
313 * @skipnr: Number of entries to skip at the start of the stack trace
314 *
315 * Return: Number of trace entries stored
316 */
317unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store,
318 unsigned int size, unsigned int skipnr)
319{
320 struct stack_trace trace = {
321 .entries = store,
322 .max_entries = size,
323 .skip = skipnr,
324 };
325
326 save_stack_trace_regs(regs, &trace);
327 return trace.nr_entries;
328}
329
330#ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
331/**
332 * stack_trace_save_tsk_reliable - Save task stack with verification
333 * @tsk: Pointer to the task to examine
334 * @store: Pointer to storage array
335 * @size: Size of the storage array
336 *
337 * Return: An error if it detects any unreliable features of the
338 * stack. Otherwise it guarantees that the stack trace is
339 * reliable and returns the number of entries stored.
340 *
341 * If the task is not 'current', the caller *must* ensure the task is inactive.
342 */
343int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store,
344 unsigned int size)
345{
346 struct stack_trace trace = {
347 .entries = store,
348 .max_entries = size,
349 };
350 int ret = save_stack_trace_tsk_reliable(tsk, &trace);
351
352 return ret ? ret : trace.nr_entries;
353}
354#endif
355
356#ifdef CONFIG_USER_STACKTRACE_SUPPORT
357/**
358 * stack_trace_save_user - Save a user space stack trace into a storage array
359 * @store: Pointer to storage array
360 * @size: Size of the storage array
361 *
362 * Return: Number of trace entries stored
363 */
364unsigned int stack_trace_save_user(unsigned long *store, unsigned int size)
365{
366 struct stack_trace trace = {
367 .entries = store,
368 .max_entries = size,
369 };
370
371 save_stack_trace_user(&trace);
372 return trace.nr_entries;
373}
374#endif /* CONFIG_USER_STACKTRACE_SUPPORT */
Thomas Gleixner214d8ca2019-04-25 11:45:21 +0200375
376#endif /* !CONFIG_ARCH_STACKWALK */
Marco Elverf39f21b2021-11-05 13:45:25 -0700377
378static inline bool in_irqentry_text(unsigned long ptr)
379{
380 return (ptr >= (unsigned long)&__irqentry_text_start &&
381 ptr < (unsigned long)&__irqentry_text_end) ||
382 (ptr >= (unsigned long)&__softirqentry_text_start &&
383 ptr < (unsigned long)&__softirqentry_text_end);
384}
385
386/**
387 * filter_irq_stacks - Find first IRQ stack entry in trace
388 * @entries: Pointer to stack trace array
389 * @nr_entries: Number of entries in the storage array
390 *
391 * Return: Number of trace entries until IRQ stack starts.
392 */
393unsigned int filter_irq_stacks(unsigned long *entries, unsigned int nr_entries)
394{
395 unsigned int i;
396
397 for (i = 0; i < nr_entries; i++) {
398 if (in_irqentry_text(entries[i])) {
399 /* Include the irqentry function into the stack. */
400 return i + 1;
401 }
402 }
403 return nr_entries;
404}
405EXPORT_SYMBOL_GPL(filter_irq_stacks);