|
@@ -89,21 +89,24 @@ __save_stack_trace_reliable(struct stack_trace *trace,
|
|
|
struct pt_regs *regs;
|
|
|
unsigned long addr;
|
|
|
|
|
|
- for (unwind_start(&state, task, NULL, NULL); !unwind_done(&state);
|
|
|
+ for (unwind_start(&state, task, NULL, NULL);
|
|
|
+ !unwind_done(&state) && !unwind_error(&state);
|
|
|
unwind_next_frame(&state)) {
|
|
|
|
|
|
regs = unwind_get_entry_regs(&state, NULL);
|
|
|
if (regs) {
|
|
|
+ /* Success path for user tasks */
|
|
|
+ if (user_mode(regs))
|
|
|
+ goto success;
|
|
|
+
|
|
|
/*
|
|
|
* Kernel mode registers on the stack indicate an
|
|
|
* in-kernel interrupt or exception (e.g., preemption
|
|
|
* or a page fault), which can make frame pointers
|
|
|
* unreliable.
|
|
|
*/
|
|
|
- if (!user_mode(regs))
|
|
|
- return -EINVAL;
|
|
|
|
|
|
- break;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
addr = unwind_get_return_address(&state);
|
|
@@ -124,6 +127,11 @@ __save_stack_trace_reliable(struct stack_trace *trace,
|
|
|
if (unwind_error(&state))
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ /* Success path for non-user tasks, i.e. kthreads and idle tasks */
|
|
|
+ if (!(task->flags & (PF_KTHREAD | PF_IDLE)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+success:
|
|
|
if (trace->nr_entries < trace->max_entries)
|
|
|
trace->entries[trace->nr_entries++] = ULONG_MAX;
|
|
|
|