1// SPDX-License-Identifier: GPL-2.0
2/*
3* Generic interfaces for unwinding user space
4*/
5#include <linux/kernel.h>
6#include <linux/sched.h>
7#include <linux/sched/task_stack.h>
8#include <linux/unwind_user.h>
9#include <linux/uaccess.h>
10
11#define for_each_user_frame(state) \
12 for (unwind_user_start(state); !(state)->done; unwind_user_next(state))
13
14static inline int
15get_user_word(unsigned long *word, unsigned long base, int off, unsigned int ws)
16{
17 unsigned long __user *addr = (void __user *)base + off;
18#ifdef CONFIG_COMPAT
19 if (ws == sizeof(int)) {
20 unsigned int data;
21 int ret = get_user(data, (unsigned int __user *)addr);
22 *word = data;
23 return ret;
24 }
25#endif
26 return get_user(*word, addr);
27}
28
29static int unwind_user_next_common(struct unwind_user_state *state,
30 const struct unwind_user_frame *frame)
31{
32 unsigned long cfa, fp, ra;
33
34 if (frame->use_fp) {
35 if (state->fp < state->sp)
36 return -EINVAL;
37 cfa = state->fp;
38 } else {
39 cfa = state->sp;
40 }
41
42 /* Get the Canonical Frame Address (CFA) */
43 cfa += frame->cfa_off;
44
45 /* stack going in wrong direction? */
46 if (cfa <= state->sp)
47 return -EINVAL;
48
49 /* Make sure that the address is word aligned */
50 if (cfa & (state->ws - 1))
51 return -EINVAL;
52
53 /* Find the Return Address (RA) */
54 if (get_user_word(word: &ra, base: cfa, off: frame->ra_off, ws: state->ws))
55 return -EINVAL;
56
57 if (frame->fp_off && get_user_word(word: &fp, base: cfa, off: frame->fp_off, ws: state->ws))
58 return -EINVAL;
59
60 state->ip = ra;
61 state->sp = cfa;
62 if (frame->fp_off)
63 state->fp = fp;
64 state->topmost = false;
65 return 0;
66}
67
68static int unwind_user_next_fp(struct unwind_user_state *state)
69{
70#ifdef CONFIG_HAVE_UNWIND_USER_FP
71 struct pt_regs *regs = task_pt_regs(current);
72
73 if (state->topmost && unwind_user_at_function_start(regs)) {
74 const struct unwind_user_frame fp_entry_frame = {
75 ARCH_INIT_USER_FP_ENTRY_FRAME(state->ws)
76 };
77 return unwind_user_next_common(state, frame: &fp_entry_frame);
78 }
79
80 const struct unwind_user_frame fp_frame = {
81 ARCH_INIT_USER_FP_FRAME(state->ws)
82 };
83 return unwind_user_next_common(state, frame: &fp_frame);
84#else
85 return -EINVAL;
86#endif
87}
88
89static int unwind_user_next(struct unwind_user_state *state)
90{
91 unsigned long iter_mask = state->available_types;
92 unsigned int bit;
93
94 if (state->done)
95 return -EINVAL;
96
97 for_each_set_bit(bit, &iter_mask, NR_UNWIND_USER_TYPE_BITS) {
98 enum unwind_user_type type = BIT(bit);
99
100 state->current_type = type;
101 switch (type) {
102 case UNWIND_USER_TYPE_FP:
103 if (!unwind_user_next_fp(state))
104 return 0;
105 continue;
106 default:
107 WARN_ONCE(1, "Undefined unwind bit %d", bit);
108 break;
109 }
110 break;
111 }
112
113 /* No successful unwind method. */
114 state->current_type = UNWIND_USER_TYPE_NONE;
115 state->done = true;
116 return -EINVAL;
117}
118
119static int unwind_user_start(struct unwind_user_state *state)
120{
121 struct pt_regs *regs = task_pt_regs(current);
122
123 memset(state, 0, sizeof(*state));
124
125 if ((current->flags & PF_KTHREAD) || !user_mode(regs)) {
126 state->done = true;
127 return -EINVAL;
128 }
129
130 if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP))
131 state->available_types |= UNWIND_USER_TYPE_FP;
132
133 state->ip = instruction_pointer(regs);
134 state->sp = user_stack_pointer(regs);
135 state->fp = frame_pointer(regs);
136 state->ws = unwind_user_word_size(regs);
137 if (!state->ws) {
138 state->done = true;
139 return -EINVAL;
140 }
141 state->topmost = true;
142
143 return 0;
144}
145
146int unwind_user(struct unwind_stacktrace *trace, unsigned int max_entries)
147{
148 struct unwind_user_state state;
149
150 trace->nr = 0;
151
152 if (!max_entries)
153 return -EINVAL;
154
155 if (current->flags & PF_KTHREAD)
156 return 0;
157
158 for_each_user_frame(&state) {
159 trace->entries[trace->nr++] = state.ip;
160 if (trace->nr >= max_entries)
161 break;
162 }
163
164 return 0;
165}
166

source code of linux/kernel/unwind/user.c