Re: [PATCH] tracing: Fix oops caused by graph notrace filter

From: Steven Rostedt
Date: Wed Jun 22 2016 - 09:08:22 EST


On Tue, 21 Jun 2016 18:57:46 +0800
Chunyu Hu <chuhu@xxxxxxxxxx> wrote:

> wakeup tracer can use function_graph trace when display_graph trace
> option is setup by user via tracefs, and bypass the set_graph_function
> and set_graph_notrace. But the bypass of set_graph_notrace is not clean.
> Although wakeup_graph_entry does most of the bypass, and both the enry
> and exit event will be submitted to the trace ring buffer, the ret_stack
> index, which will be assigned to depth field of graph enrty event is not
> handled. The issue is that the depth is used as the array index of
> fgraph_cpu_data and can cause an oops when it's negative. irqsoff tracer
> has same issue. To see the oops:
>
> echo 1 > options/display_graph
> echo schedule > set_graph_notrace
> echo wakeup > current_tracer
> cat trace
> cat trace

I'm not able to trigger an oops, but I do see them being traced.

>
> Making ftrace_graph_notrace_addr always return false when tracers need
> to bypass it is a proposed fix.

There's a lot of things wrong with this patch, but before we go there,
why should the latency tracers ignore set_graph_notrace?

What about this patch?

-- Steve

diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 03cdff84d026..68fcee5097d2 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -175,6 +175,9 @@ static int irqsoff_graph_entry(struct ftrace_graph_ent *trace)
int ret;
int pc;

+ if (trace->depth < 0)
+ return 0;
+
if (!func_prolog_dec(tr, &data, &flags))
return 0;

diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index 9d4399b553a3..ce9889bff8b4 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -239,6 +239,9 @@ static int wakeup_graph_entry(struct ftrace_graph_ent *trace)
unsigned long flags;
int pc, ret = 0;

+ if (trace->depth < 0)
+ return 0;
+
if (!func_prolog_preempt_disable(tr, &data, &pc))
return 0;