Skip to content

Commit 6c8ef58

Browse files
Dmitry MonakhovPeter Zijlstra
authored andcommitted
x86/unwind/orc: Recheck address range after stack info was updated
A crash was observed in the ORC unwinder: BUG: stack guard page was hit at 000000000dd984a2 (stack is 00000000d1caafca..00000000613712f0) kernel stack overflow (page fault): 0000 [#1] SMP NOPTI CPU: 93 PID: 23787 Comm: context_switch1 Not tainted 5.4.145 #1 RIP: 0010:unwind_next_frame Call Trace: <NMI> perf_callchain_kernel get_perf_callchain perf_callchain perf_prepare_sample perf_event_output_forward __perf_event_overflow perf_ibs_handle_irq perf_ibs_nmi_handler nmi_handle default_do_nmi do_nmi end_repeat_nmi This was really two bugs: 1) The perf IBS code passed inconsistent regs to the unwinder. 2) The unwinder didn't handle the bad input gracefully. Fix the latter bug. The ORC unwinder needs to be immune against bad inputs. The problem is that stack_access_ok() doesn't recheck the validity of the full range of registers after switching to the next valid stack with get_stack_info(). Fix that. [ jpoimboe: rewrote commit log ] Signed-off-by: Dmitry Monakhov <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Peter Zijlstra <[email protected]>
1 parent f9e14db commit 6c8ef58

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

arch/x86/kernel/unwind_orc.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,11 @@ static bool stack_access_ok(struct unwind_state *state, unsigned long _addr,
339339
struct stack_info *info = &state->stack_info;
340340
void *addr = (void *)_addr;
341341

342-
if (!on_stack(info, addr, len) &&
343-
(get_stack_info(addr, state->task, info, &state->stack_mask)))
344-
return false;
342+
if (on_stack(info, addr, len))
343+
return true;
345344

346-
return true;
345+
return !get_stack_info(addr, state->task, info, &state->stack_mask) &&
346+
on_stack(info, addr, len);
347347
}
348348

349349
static bool deref_stack_reg(struct unwind_state *state, unsigned long addr,

0 commit comments

Comments
 (0)