aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@redhat.com>2017-04-12 14:47:10 -0400
committerIngo Molnar <mingo@kernel.org>2017-04-14 04:19:49 -0400
commit5ed8d8bb38c5dcd78de540182cedb0fb19399aab (patch)
tree8a8fa0f779e57d4e7b35f918062268d2c6c893a1
parentb5effd3815ccbe3df1a015a6d67d8a24a27813d5 (diff)
x86/unwind: Move common code into update_stack_state()
The __unwind_start() and unwind_next_frame() functions have some duplicated functionality. They both call decode_frame_pointer() and set state->regs and state->bp accordingly. Move that functionality to a common place in update_stack_state(). Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: Dave Jones <davej@codemonkey.org.uk> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/a2ee4801113f6d2300d58f08f6b69f85edf4eb43.1492020577.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/unwind_frame.c119
1 files changed, 55 insertions, 64 deletions
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index 08339262b666..9098ef1da8f8 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -135,26 +135,59 @@ static struct pt_regs *decode_frame_pointer(unsigned long *bp)
135 return (struct pt_regs *)(regs & ~0x1); 135 return (struct pt_regs *)(regs & ~0x1);
136} 136}
137 137
138static bool update_stack_state(struct unwind_state *state, void *addr, 138static bool update_stack_state(struct unwind_state *state,
139 size_t len) 139 unsigned long *next_bp)
140{ 140{
141 struct stack_info *info = &state->stack_info; 141 struct stack_info *info = &state->stack_info;
142 enum stack_type orig_type = info->type; 142 enum stack_type prev_type = info->type;
143 struct pt_regs *regs;
144 unsigned long *frame, *prev_frame_end;
145 size_t len;
146
147 if (state->regs)
148 prev_frame_end = (void *)state->regs + regs_size(state->regs);
149 else
150 prev_frame_end = (void *)state->bp + FRAME_HEADER_SIZE;
151
152 /* Is the next frame pointer an encoded pointer to pt_regs? */
153 regs = decode_frame_pointer(next_bp);
154 if (regs) {
155 frame = (unsigned long *)regs;
156 len = regs_size(regs);
157 } else {
158 frame = next_bp;
159 len = FRAME_HEADER_SIZE;
160 }
143 161
144 /* 162 /*
145 * If addr isn't on the current stack, switch to the next one. 163 * If the next bp isn't on the current stack, switch to the next one.
146 * 164 *
147 * We may have to traverse multiple stacks to deal with the possibility 165 * We may have to traverse multiple stacks to deal with the possibility
148 * that 'info->next_sp' could point to an empty stack and 'addr' could 166 * that info->next_sp could point to an empty stack and the next bp
149 * be on a subsequent stack. 167 * could be on a subsequent stack.
150 */ 168 */
151 while (!on_stack(info, addr, len)) 169 while (!on_stack(info, frame, len))
152 if (get_stack_info(info->next_sp, state->task, info, 170 if (get_stack_info(info->next_sp, state->task, info,
153 &state->stack_mask)) 171 &state->stack_mask))
154 return false; 172 return false;
155 173
156 if (!state->orig_sp || info->type != orig_type) 174 /* Make sure it only unwinds up and doesn't overlap the prev frame: */
157 state->orig_sp = addr; 175 if (state->orig_sp && state->stack_info.type == prev_type &&
176 frame < prev_frame_end)
177 return false;
178
179 /* Move state to the next frame: */
180 if (regs) {
181 state->regs = regs;
182 state->bp = NULL;
183 } else {
184 state->bp = next_bp;
185 state->regs = NULL;
186 }
187
188 /* Save the original stack pointer for unwind_dump(): */
189 if (!state->orig_sp || info->type != prev_type)
190 state->orig_sp = frame;
158 191
159 return true; 192 return true;
160} 193}
@@ -162,14 +195,12 @@ static bool update_stack_state(struct unwind_state *state, void *addr,
162bool unwind_next_frame(struct unwind_state *state) 195bool unwind_next_frame(struct unwind_state *state)
163{ 196{
164 struct pt_regs *regs; 197 struct pt_regs *regs;
165 unsigned long *next_bp, *next_frame; 198 unsigned long *next_bp;
166 size_t next_len;
167 enum stack_type prev_type = state->stack_info.type;
168 199
169 if (unwind_done(state)) 200 if (unwind_done(state))
170 return false; 201 return false;
171 202
172 /* have we reached the end? */ 203 /* Have we reached the end? */
173 if (state->regs && user_mode(state->regs)) 204 if (state->regs && user_mode(state->regs))
174 goto the_end; 205 goto the_end;
175 206
@@ -200,24 +231,14 @@ bool unwind_next_frame(struct unwind_state *state)
200 return true; 231 return true;
201 } 232 }
202 233
203 /* get the next frame pointer */ 234 /* Get the next frame pointer: */
204 if (state->regs) 235 if (state->regs)
205 next_bp = (unsigned long *)state->regs->bp; 236 next_bp = (unsigned long *)state->regs->bp;
206 else 237 else
207 next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task,*state->bp); 238 next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task, *state->bp);
208 239
209 /* is the next frame pointer an encoded pointer to pt_regs? */ 240 /* Move to the next frame if it's safe: */
210 regs = decode_frame_pointer(next_bp); 241 if (!update_stack_state(state, next_bp)) {
211 if (regs) {
212 next_frame = (unsigned long *)regs;
213 next_len = sizeof(*regs);
214 } else {
215 next_frame = next_bp;
216 next_len = FRAME_HEADER_SIZE;
217 }
218
219 /* make sure the next frame's data is accessible */
220 if (!update_stack_state(state, next_frame, next_len)) {
221 /* 242 /*
222 * Don't warn on bad regs->bp. An interrupt in entry code 243 * Don't warn on bad regs->bp. An interrupt in entry code
223 * might cause a false positive warning. 244 * might cause a false positive warning.
@@ -228,24 +249,6 @@ bool unwind_next_frame(struct unwind_state *state)
228 goto bad_address; 249 goto bad_address;
229 } 250 }
230 251
231 /* Make sure it only unwinds up and doesn't overlap the last frame: */
232 if (state->stack_info.type == prev_type) {
233 if (state->regs && (void *)next_frame < (void *)state->regs + regs_size(state->regs))
234 goto bad_address;
235
236 if (state->bp && (void *)next_frame < (void *)state->bp + FRAME_HEADER_SIZE)
237 goto bad_address;
238 }
239
240 /* move to the next frame */
241 if (regs) {
242 state->regs = regs;
243 state->bp = NULL;
244 } else {
245 state->bp = next_bp;
246 state->regs = NULL;
247 }
248
249 return true; 252 return true;
250 253
251bad_address: 254bad_address:
@@ -263,13 +266,13 @@ bad_address:
263 printk_deferred_once(KERN_WARNING 266 printk_deferred_once(KERN_WARNING
264 "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n", 267 "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
265 state->regs, state->task->comm, 268 state->regs, state->task->comm,
266 state->task->pid, next_frame); 269 state->task->pid, next_bp);
267 unwind_dump(state, (unsigned long *)state->regs); 270 unwind_dump(state, (unsigned long *)state->regs);
268 } else { 271 } else {
269 printk_deferred_once(KERN_WARNING 272 printk_deferred_once(KERN_WARNING
270 "WARNING: kernel stack frame pointer at %p in %s:%d has bad value %p\n", 273 "WARNING: kernel stack frame pointer at %p in %s:%d has bad value %p\n",
271 state->bp, state->task->comm, 274 state->bp, state->task->comm,
272 state->task->pid, next_frame); 275 state->task->pid, next_bp);
273 unwind_dump(state, state->bp); 276 unwind_dump(state, state->bp);
274 } 277 }
275the_end: 278the_end:
@@ -281,35 +284,23 @@ EXPORT_SYMBOL_GPL(unwind_next_frame);
281void __unwind_start(struct unwind_state *state, struct task_struct *task, 284void __unwind_start(struct unwind_state *state, struct task_struct *task,
282 struct pt_regs *regs, unsigned long *first_frame) 285 struct pt_regs *regs, unsigned long *first_frame)
283{ 286{
284 unsigned long *bp, *frame; 287 unsigned long *bp;
285 size_t len;
286 288
287 memset(state, 0, sizeof(*state)); 289 memset(state, 0, sizeof(*state));
288 state->task = task; 290 state->task = task;
289 291
290 /* don't even attempt to start from user mode regs */ 292 /* Don't even attempt to start from user mode regs: */
291 if (regs && user_mode(regs)) { 293 if (regs && user_mode(regs)) {
292 state->stack_info.type = STACK_TYPE_UNKNOWN; 294 state->stack_info.type = STACK_TYPE_UNKNOWN;
293 return; 295 return;
294 } 296 }
295 297
296 /* set up the starting stack frame */
297 bp = get_frame_pointer(task, regs); 298 bp = get_frame_pointer(task, regs);
298 regs = decode_frame_pointer(bp);
299 if (regs) {
300 state->regs = regs;
301 frame = (unsigned long *)regs;
302 len = sizeof(*regs);
303 } else {
304 state->bp = bp;
305 frame = bp;
306 len = FRAME_HEADER_SIZE;
307 }
308 299
309 /* initialize stack info and make sure the frame data is accessible */ 300 /* Initialize stack info and make sure the frame data is accessible: */
310 get_stack_info(frame, state->task, &state->stack_info, 301 get_stack_info(bp, state->task, &state->stack_info,
311 &state->stack_mask); 302 &state->stack_mask);
312 update_stack_state(state, frame, len); 303 update_stack_state(state, bp);
313 304
314 /* 305 /*
315 * The caller can provide the address of the first frame directly 306 * The caller can provide the address of the first frame directly