Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/stacktrace: Clarify the reliable success paths

Make clear which path is for user tasks and for kthreads and idle
tasks. This will allow easier plug-in of the ORC unwinder in the next
patches.

Note that we added a check for unwind error to the top of the loop, so
that an error is returned also for user tasks (the 'goto success' would
skip the check after the loop otherwise).

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/lkml/20180518064713.26440-3-jslaby@suse.cz
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Jiri Slaby and committed by
Ingo Molnar
441ccc35 17426923

+12 -4
+12 -4
arch/x86/kernel/stacktrace.c
··· 89 89 struct pt_regs *regs; 90 90 unsigned long addr; 91 91 92 - for (unwind_start(&state, task, NULL, NULL); !unwind_done(&state); 92 + for (unwind_start(&state, task, NULL, NULL); 93 + !unwind_done(&state) && !unwind_error(&state); 93 94 unwind_next_frame(&state)) { 94 95 95 96 regs = unwind_get_entry_regs(&state, NULL); 96 97 if (regs) { 98 + /* Success path for user tasks */ 99 + if (user_mode(regs)) 100 + goto success; 101 + 97 102 /* 98 103 * Kernel mode registers on the stack indicate an 99 104 * in-kernel interrupt or exception (e.g., preemption 100 105 * or a page fault), which can make frame pointers 101 106 * unreliable. 102 107 */ 103 - if (!user_mode(regs)) 104 - return -EINVAL; 105 108 106 - break; 109 + return -EINVAL; 107 110 } 108 111 109 112 addr = unwind_get_return_address(&state); ··· 127 124 if (unwind_error(&state)) 128 125 return -EINVAL; 129 126 127 + /* Success path for non-user tasks, i.e. kthreads and idle tasks */ 128 + if (!(task->flags & (PF_KTHREAD | PF_IDLE))) 129 + return -EINVAL; 130 + 131 + success: 130 132 if (trace->nr_entries < trace->max_entries) 131 133 trace->entries[trace->nr_entries++] = ULONG_MAX; 132 134