Commit 91e86e56 authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt

tracing: Fix recursive user stack trace

The user stack trace can fault when examining the trace. Which
would call the do_page_fault handler, which would trace again,
which would do the user stack trace, which would fault and call
do_page_fault again ...

Thus this is causing a recursive bug. We need to have a recursion
detector here.

[ Resubmitted by Jiri Olsa ]

[ Eric Dumazet recommended using __this_cpu_* instead of __get_cpu_* ]

Cc: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarJiri Olsa <jolsa@redhat.com>
LKML-Reference: <1289390172-9730-3-git-send-email-jolsa@redhat.com>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent b5908548
...@@ -1284,6 +1284,8 @@ void trace_dump_stack(void) ...@@ -1284,6 +1284,8 @@ void trace_dump_stack(void)
__ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count()); __ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count());
} }
static DEFINE_PER_CPU(int, user_stack_count);
void void
ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
{ {
...@@ -1302,6 +1304,18 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) ...@@ -1302,6 +1304,18 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
if (unlikely(in_nmi())) if (unlikely(in_nmi()))
return; return;
/*
* prevent recursion, since the user stack tracing may
* trigger other kernel events.
*/
preempt_disable();
if (__this_cpu_read(user_stack_count))
goto out;
__this_cpu_inc(user_stack_count);
event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK, event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK,
sizeof(*entry), flags, pc); sizeof(*entry), flags, pc);
if (!event) if (!event)
...@@ -1319,6 +1333,11 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) ...@@ -1319,6 +1333,11 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
save_stack_trace_user(&trace); save_stack_trace_user(&trace);
if (!filter_check_discard(call, entry, buffer, event)) if (!filter_check_discard(call, entry, buffer, event))
ring_buffer_unlock_commit(buffer, event); ring_buffer_unlock_commit(buffer, event);
__this_cpu_dec(user_stack_count);
out:
preempt_enable();
} }
#ifdef UNUSED #ifdef UNUSED
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment