hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/s390/kernel/stacktrace.c
....@@ -6,70 +6,62 @@
66 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
77 */
88
9
-#include <linux/sched.h>
10
-#include <linux/sched/debug.h>
119 #include <linux/stacktrace.h>
12
-#include <linux/kallsyms.h>
13
-#include <linux/export.h>
10
+#include <asm/stacktrace.h>
11
+#include <asm/unwind.h>
12
+#include <asm/kprobes.h>
1413
15
-static int __save_address(void *data, unsigned long address, int nosched)
14
+void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
15
+ struct task_struct *task, struct pt_regs *regs)
1616 {
17
- struct stack_trace *trace = data;
17
+ struct unwind_state state;
18
+ unsigned long addr;
1819
19
- if (nosched && in_sched_functions(address))
20
- return 0;
21
- if (trace->skip > 0) {
22
- trace->skip--;
23
- return 0;
20
+ unwind_for_each_frame(&state, task, regs, 0) {
21
+ addr = unwind_get_return_address(&state);
22
+ if (!addr || !consume_entry(cookie, addr))
23
+ break;
2424 }
25
- if (trace->nr_entries < trace->max_entries) {
26
- trace->entries[trace->nr_entries++] = address;
27
- return 0;
25
+}
26
+
27
+/*
28
+ * This function returns an error if it detects any unreliable features of the
29
+ * stack. Otherwise it guarantees that the stack trace is reliable.
30
+ *
31
+ * If the task is not 'current', the caller *must* ensure the task is inactive.
32
+ */
33
+int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
34
+ void *cookie, struct task_struct *task)
35
+{
36
+ struct unwind_state state;
37
+ unsigned long addr;
38
+
39
+ unwind_for_each_frame(&state, task, NULL, 0) {
40
+ if (state.stack_info.type != STACK_TYPE_TASK)
41
+ return -EINVAL;
42
+
43
+ if (state.regs)
44
+ return -EINVAL;
45
+
46
+ addr = unwind_get_return_address(&state);
47
+ if (!addr)
48
+ return -EINVAL;
49
+
50
+#ifdef CONFIG_KPROBES
51
+ /*
52
+ * Mark stacktraces with kretprobed functions on them
53
+ * as unreliable.
54
+ */
55
+ if (state.ip == (unsigned long)kretprobe_trampoline)
56
+ return -EINVAL;
57
+#endif
58
+
59
+ if (!consume_entry(cookie, addr))
60
+ return -EINVAL;
2861 }
29
- return 1;
62
+
63
+ /* Check for stack corruption */
64
+ if (unwind_error(&state))
65
+ return -EINVAL;
66
+ return 0;
3067 }
31
-
32
-static int save_address(void *data, unsigned long address, int reliable)
33
-{
34
- return __save_address(data, address, 0);
35
-}
36
-
37
-static int save_address_nosched(void *data, unsigned long address, int reliable)
38
-{
39
- return __save_address(data, address, 1);
40
-}
41
-
42
-void save_stack_trace(struct stack_trace *trace)
43
-{
44
- unsigned long sp;
45
-
46
- sp = current_stack_pointer();
47
- dump_trace(save_address, trace, NULL, sp);
48
- if (trace->nr_entries < trace->max_entries)
49
- trace->entries[trace->nr_entries++] = ULONG_MAX;
50
-}
51
-EXPORT_SYMBOL_GPL(save_stack_trace);
52
-
53
-void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
54
-{
55
- unsigned long sp;
56
-
57
- sp = tsk->thread.ksp;
58
- if (tsk == current)
59
- sp = current_stack_pointer();
60
- dump_trace(save_address_nosched, trace, tsk, sp);
61
- if (trace->nr_entries < trace->max_entries)
62
- trace->entries[trace->nr_entries++] = ULONG_MAX;
63
-}
64
-EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
65
-
66
-void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
67
-{
68
- unsigned long sp;
69
-
70
- sp = kernel_stack_pointer(regs);
71
- dump_trace(save_address, trace, NULL, sp);
72
- if (trace->nr_entries < trace->max_entries)
73
- trace->entries[trace->nr_entries++] = ULONG_MAX;
74
-}
75
-EXPORT_SYMBOL_GPL(save_stack_trace_regs);