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:af085d9084
("stacktrace/x86: add function for detecting reliable stack traces") Fixes:d3a0910401
("x86/unwinder/orc: Dont bail on stack overflow") Fixes:98d0c8ebf7
("x86/unwind/orc: Prevent unwinding before ORC initialization") Reported-by: Pavel Machek <pavel@denx.de> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/d6ac7215a84ca92b895fdd2e1aa546729417e6e6.1589487277.git.jpoimboe@redhat.com
This commit is contained in:
parent
2ef96a5bb1
commit
71c9582528
@ -617,23 +617,23 @@ EXPORT_SYMBOL_GPL(unwind_next_frame);
|
||||
void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
||||
struct pt_regs *regs, unsigned long *first_frame)
|
||||
{
|
||||
if (!orc_init)
|
||||
goto done;
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
state->task = task;
|
||||
|
||||
if (!orc_init)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Refuse to unwind the stack of a task while it's executing on another
|
||||
* CPU. This check is racy, but that's ok: the unwinder has other
|
||||
* checks to prevent it from going off the rails.
|
||||
*/
|
||||
if (task_on_another_cpu(task))
|
||||
goto done;
|
||||
goto err;
|
||||
|
||||
if (regs) {
|
||||
if (user_mode(regs))
|
||||
goto done;
|
||||
goto the_end;
|
||||
|
||||
state->ip = regs->ip;
|
||||
state->sp = regs->sp;
|
||||
@ -666,6 +666,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
||||
* generate some kind of backtrace if this happens.
|
||||
*/
|
||||
void *next_page = (void *)PAGE_ALIGN((unsigned long)state->sp);
|
||||
state->error = true;
|
||||
if (get_stack_info(next_page, state->task, &state->stack_info,
|
||||
&state->stack_mask))
|
||||
return;
|
||||
@ -691,8 +692,9 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
||||
|
||||
return;
|
||||
|
||||
done:
|
||||
err:
|
||||
state->error = true;
|
||||
the_end:
|
||||
state->stack_info.type = STACK_TYPE_UNKNOWN;
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__unwind_start);
|
||||
|
Loading…
Reference in New Issue
Block a user