Skip to content

Commit 71c9582

Browse files
jpoimboePeter Zijlstra
authored andcommitted
x86/unwind/orc: Fix error handling in __unwind_start()
The unwind_state 'error' field is used to inform the reliable unwinding code that the stack trace can't be trusted. Set this field for all errors in __unwind_start(). Also, move the zeroing out of the unwind_state struct to before the ORC table initialization check, to prevent the caller from reading uninitialized data if the ORC table is corrupted. Fixes: af085d9 ("stacktrace/x86: add function for detecting reliable stack traces") Fixes: d3a0910 ("x86/unwinder/orc: Dont bail on stack overflow") Fixes: 98d0c8e ("x86/unwind/orc: Prevent unwinding before ORC initialization") Reported-by: Pavel Machek <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/d6ac7215a84ca92b895fdd2e1aa546729417e6e6.1589487277.git.jpoimboe@redhat.com
1 parent 2ef96a5 commit 71c9582

File tree

1 file changed

+9
-7
lines changed

1 file changed

+9
-7
lines changed

arch/x86/kernel/unwind_orc.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -617,23 +617,23 @@ EXPORT_SYMBOL_GPL(unwind_next_frame);
617617
void __unwind_start(struct unwind_state *state, struct task_struct *task,
618618
struct pt_regs *regs, unsigned long *first_frame)
619619
{
620-
if (!orc_init)
621-
goto done;
622-
623620
memset(state, 0, sizeof(*state));
624621
state->task = task;
625622

623+
if (!orc_init)
624+
goto err;
625+
626626
/*
627627
* Refuse to unwind the stack of a task while it's executing on another
628628
* CPU. This check is racy, but that's ok: the unwinder has other
629629
* checks to prevent it from going off the rails.
630630
*/
631631
if (task_on_another_cpu(task))
632-
goto done;
632+
goto err;
633633

634634
if (regs) {
635635
if (user_mode(regs))
636-
goto done;
636+
goto the_end;
637637

638638
state->ip = regs->ip;
639639
state->sp = regs->sp;
@@ -666,6 +666,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
666666
* generate some kind of backtrace if this happens.
667667
*/
668668
void *next_page = (void *)PAGE_ALIGN((unsigned long)state->sp);
669+
state->error = true;
669670
if (get_stack_info(next_page, state->task, &state->stack_info,
670671
&state->stack_mask))
671672
return;
@@ -691,8 +692,9 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
691692

692693
return;
693694

694-
done:
695+
err:
696+
state->error = true;
697+
the_end:
695698
state->stack_info.type = STACK_TYPE_UNKNOWN;
696-
return;
697699
}
698700
EXPORT_SYMBOL_GPL(__unwind_start);

0 commit comments

Comments
 (0)