Skip to content

Commit

Permalink
x86/unwind: Disable KASAN checks for non-current tasks
Browse files Browse the repository at this point in the history
There are a handful of callers to save_stack_trace_tsk() and
show_stack() which try to unwind the stack of a task other than current.
In such cases, it's remotely possible that the task is running on one
CPU while the unwinder is reading its stack from another CPU, causing
the unwinder to see stack corruption.

These cases seem to be mostly harmless.  The unwinder has checks which
prevent it from following bad pointers beyond the bounds of the stack.
So it's not really a bug as long as the caller understands that
unwinding another task will not always succeed.

In such cases, it's possible that the unwinder may read a KASAN-poisoned
region of the stack.  Account for that by using READ_ONCE_NOCHECK() when
reading the stack of another task.

Use READ_ONCE() when reading the stack of the current task, since KASAN
warnings can still be useful for finding bugs in that case.

Reported-by: Dmitry Vyukov <[email protected]>
Signed-off-by: Josh Poimboeuf <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: Dave Jones <[email protected]>
Cc: Denys Vlasenko <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Miroslav Benes <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/r/4c575eb288ba9f73d498dfe0acde2f58674598f1.1483978430.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
jpoimboe authored and Ingo Molnar committed Jan 12, 2017
1 parent 900742d commit 8493611
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
5 changes: 4 additions & 1 deletion arch/x86/include/asm/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ static inline bool on_stack(struct stack_info *info, void *addr, size_t len)
static inline unsigned long *
get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
{
struct inactive_task_frame *frame;

if (regs)
return (unsigned long *)regs->bp;

if (task == current)
return __builtin_frame_address(0);

return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
frame = (struct inactive_task_frame *)task->thread.sp;
return (unsigned long *)READ_ONCE_NOCHECK(frame->bp);
}
#else
static inline unsigned long *
Expand Down
20 changes: 18 additions & 2 deletions arch/x86/kernel/unwind_frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@

#define FRAME_HEADER_SIZE (sizeof(long) * 2)

/*
* This disables KASAN checking when reading a value from another task's stack,
* since the other task could be running on another CPU and could have poisoned
* the stack in the meantime.
*/
#define READ_ONCE_TASK_STACK(task, x) \
({ \
unsigned long val; \
if (task == current) \
val = READ_ONCE(x); \
else \
val = READ_ONCE_NOCHECK(x); \
val; \
})

static void unwind_dump(struct unwind_state *state, unsigned long *sp)
{
static bool dumped_before = false;
Expand Down Expand Up @@ -48,7 +63,8 @@ unsigned long unwind_get_return_address(struct unwind_state *state)
if (state->regs && user_mode(state->regs))
return 0;

addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, *addr_p,
addr = READ_ONCE_TASK_STACK(state->task, *addr_p);
addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, addr,
addr_p);

return __kernel_text_address(addr) ? addr : 0;
Expand Down Expand Up @@ -162,7 +178,7 @@ bool unwind_next_frame(struct unwind_state *state)
if (state->regs)
next_bp = (unsigned long *)state->regs->bp;
else
next_bp = (unsigned long *)*state->bp;
next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task,*state->bp);

/* is the next frame pointer an encoded pointer to pt_regs? */
regs = decode_frame_pointer(next_bp);
Expand Down

0 comments on commit 8493611

Please sign in to comment.