Re: [PATCH 0/3][RFC] tracing/kprobes: prevent jprobes fromcrashing function graph tracer

From: Frederic Weisbecker
Date: Sun Nov 01 2009 - 19:37:41 EST


On Thu, Oct 29, 2009 at 06:02:20PM -0400, Masami Hiramatsu wrote:
> Steven Rostedt wrote:
> > Lately I've been testing with an allyesconfig. When I ran the function graph
> > tracer, it immediately crashed the kernel. Thanks to the new frame pointer
> > test in function graph, it reported directly what the issue was and then
> > panicked the kernel to prevent any unexpected damage from happening.
> >
> > It pointed the error to be with jtcp_rcv_established. Which is a jprobe
> > function added to tcp_rcv_established at bootup when CONFIG_NET_TCPPROBE
> > is enabled.
> >
> > Jprobes and the function graph tracer use the same mechanism to trace
> > the exit of a function. Unfortunately, only one can be done at a time.
> > The function graph tracer replaces the return address with its own handler,
> > but so does jprobes. The two are not compatible.
>
> AFAIK, Jprobe doesn't trace the exit of a function. I assume that
> jprobe's user handler causes the problem, since the handler never
> returns normal way.
> Instead of that, it just calls jprobe_return() which causes
> int3 to be trapped by kprobe's break handler. And the break handler
> fixup regs->ip to back to traced function.
>
> Actually, this will cause a problem with function graph tracer.
> The f-g-tracer push the return address into the special stack and replaces
> it with fixup function (This is similar (not same) mechanism of kretprobe.)
> And then the traced function returns, it returns to the fixup function and
> it pops the return address up and back to the real caller.
>
> So, if the f-g-tracer traces jprobe user handler, the pop operation
> will be skipped because the the handler never returns.


I'm not sure I've well understood how is performed the call to the jprobe
handler.
But if I understand well we have:

func() {
int3() {
jprobe_handler() {
(-)
set ip after iret to user_handler()
}
}
user_handler() {
jprobe_return() {
(+)
int3() {
set ip after iret to func+...()
}
|
|
|
<--------------
(execute the rest of func())
}

If we replace (-) with pause_graph_tracing() and (+) with
unpause_graph_tracing(), this should do the trick...I hope.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/