Skip to content

Commit

Permalink
function-graph: enable the stack after initialization of other variables
Browse files Browse the repository at this point in the history
The function graph tracer checks if the task_struct has ret_stack defined
to know if it is OK or not to use it. The initialization is done for
all tasks by one process, but the idle tasks use the same initialization
used by new tasks.

If an interrupt happens on an idle task that just had the ret_stack
created, but before the rest of the initialization took place, then
we can corrupt the return address of the functions.

This patch moves the setting of the task_struct's ret_stack to after
the other variables have been initialized.

[ Impact: prevent kernel panic on idle task when starting function graph ]

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Jun 2, 2009
1 parent 179c498 commit 82310a3
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 2 deletions.
9 changes: 7 additions & 2 deletions kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -2739,15 +2739,20 @@ void unregister_ftrace_graph(void)
void ftrace_graph_init_task(struct task_struct *t)
{
if (atomic_read(&ftrace_graph_active)) {
t->ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
struct ftrace_ret_stack *ret_stack;

ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
* sizeof(struct ftrace_ret_stack),
GFP_KERNEL);
if (!t->ret_stack)
if (!ret_stack)
return;
t->curr_ret_stack = -1;
atomic_set(&t->tracing_graph_pause, 0);
atomic_set(&t->trace_overrun, 0);
t->ftrace_timestamp = 0;
/* make curr_ret_stack visable before we add the ret_stack */
smp_wmb();
t->ret_stack = ret_stack;
} else
t->ret_stack = NULL;
}
Expand Down
6 changes: 6 additions & 0 deletions kernel/trace/trace_functions_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth)
if (!current->ret_stack)
return -EBUSY;

/*
* We must make sure the ret_stack is tested before we read
* anything else.
*/
smp_rmb();

/* The return trace stack is full */
if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) {
atomic_inc(&current->trace_overrun);
Expand Down

0 comments on commit 82310a3

Please sign in to comment.