diff options
author | Josh Poimboeuf <jpoimboe@redhat.com> | 2016-11-28 00:13:07 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-11-28 01:47:54 -0500 |
commit | 55f856e640560494518eaf24fe9d2d2089fba71a (patch) | |
tree | 196efed69de7c9567795e9f0daf163851eb4b9ac /arch/x86 | |
parent | adee8705d2517f0e163ffc45e8d7f9e97a58f1f6 (diff) |
x86/unwind: Fix guess-unwinder regression
My attempt at fixing some KASAN false positive warnings was rather brain
dead, and it broke the guess unwinder. With frame pointers disabled,
/proc/<pid>/stack is broken:
# cat /proc/1/stack
[<ffffffffffffffff>] 0xffffffffffffffff
Restore the code flow to more closely resemble its previous state, while
still using READ_ONCE_NOCHECK() macros to silence KASAN false positives.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: c2d75e03d630 ("x86/unwind: Prevent KASAN false positive warnings in guess unwinder")
Link: http://lkml.kernel.org/r/b824f92c2c22eca5ec95ac56bd2a7c84cf0b9df9.1480309971.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/unwind_guess.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/arch/x86/kernel/unwind_guess.c b/arch/x86/kernel/unwind_guess.c index b80e8bf43cc6..22881ddcbb9f 100644 --- a/arch/x86/kernel/unwind_guess.c +++ b/arch/x86/kernel/unwind_guess.c | |||
@@ -7,11 +7,13 @@ | |||
7 | 7 | ||
8 | unsigned long unwind_get_return_address(struct unwind_state *state) | 8 | unsigned long unwind_get_return_address(struct unwind_state *state) |
9 | { | 9 | { |
10 | unsigned long addr = READ_ONCE_NOCHECK(*state->sp); | 10 | unsigned long addr; |
11 | 11 | ||
12 | if (unwind_done(state)) | 12 | if (unwind_done(state)) |
13 | return 0; | 13 | return 0; |
14 | 14 | ||
15 | addr = READ_ONCE_NOCHECK(*state->sp); | ||
16 | |||
15 | return ftrace_graph_ret_addr(state->task, &state->graph_idx, | 17 | return ftrace_graph_ret_addr(state->task, &state->graph_idx, |
16 | addr, state->sp); | 18 | addr, state->sp); |
17 | } | 19 | } |
@@ -25,11 +27,12 @@ bool unwind_next_frame(struct unwind_state *state) | |||
25 | return false; | 27 | return false; |
26 | 28 | ||
27 | do { | 29 | do { |
28 | unsigned long addr = READ_ONCE_NOCHECK(*state->sp); | 30 | for (state->sp++; state->sp < info->end; state->sp++) { |
31 | unsigned long addr = READ_ONCE_NOCHECK(*state->sp); | ||
29 | 32 | ||
30 | for (state->sp++; state->sp < info->end; state->sp++) | ||
31 | if (__kernel_text_address(addr)) | 33 | if (__kernel_text_address(addr)) |
32 | return true; | 34 | return true; |
35 | } | ||
33 | 36 | ||
34 | state->sp = info->next_sp; | 37 | state->sp = info->next_sp; |
35 | 38 | ||