Re: [PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-15 Thread Steven Rostedt
On Thu, 15 Jan 2015 20:57:29 +0900
Masami Hiramatsu  wrote:
> 
> > If the function tracer traces the jprobe handler, the hook function
> > for that handler will not be called, and its saved return address
> > will be used for the next function. This will result in a kernel
> > crash.
> 
> Actually, both jprobe (user-defined) handler and jprobe_return()
> doesn't execute "ret".

Yep I new that. But a notrace on jprobe_return isn't that big of a
deal. It's not a function we really need to trace, as it really doesn't
do anything but being a 'hack' for jprobes to return properly.

> So, right after run out the jprobe handler with function-graph tracer,
> on the top of its hidden stack, there are at least 2(*) unused return
> addresses, one is for jprobe handler (this should be same as the
> probed function's return address) and other is jprobe_return()'s
> return address. (*: this can be more than 2 if jprobe_return is
> called from a function which is called from jprobe handler)
> 
> So, the hidden stack may be as below;
> 
> [jprobe_return() return address]
> [probed function return address]
> [probed function return address]
> 
> After jumping back to the probed function, the function return is
> trapped by the function-graph tracer, and it uses jprobe_return()'s
> return address. Since usually jprobe_return() is called at the end of
> the function, CPU will execute "ret" soon again(if someone puts a BUG
> right after jprobe_return(), the kernel will show that BUG), and it
> returns to the caller of the probed function.
> However, there still be the probed function return address on the
> hidden stack! This means that the next "ret" will go back to the same
> address but with modified register and stacks.

Yep, I discovered all this with my patch that allows function tracing
with jprobes.

> 
> > To solve this, pause function tracing before the jprobe handler is
> > called and unpause it before it returns back to the function it
> > probed.
> 
> Agreed, but it also could drop some NMI events. That is downside.
> 
> > Some other updates:
> > 
> > Used a variable "saved_sp" to hold kcb->jprobe_saved_sp. This makes
> > the code look a bit cleaner and easier to understand (various tries
> > to fix this bug required this change).
> 
> OK.
> 
> > Note, if fentry is being used, jprobes will change the ip address
> > before the function graph tracer runs and it will not be able to
> > trace the function that the jprobe is probing.
> 
> yes, it should be fixed.
> 
> BTW, my last part of IPMODIFY patches (which is not yet merged)
> can solve this a different way. It sets IPMODIFY flag only to jprobe.
> So, if function-graph tracer sets IPMODIFY flag, user can not enable
> function-graph tracer when jprobe is used.

Nah, I don't want to stop jprobes due to function graph tracing or vice
versa.

function graph tracer doesn't change the regs->ip, so it doesn't need
the flag. But I sent out a patch that fixes this for this case. Let me
know what you think of that one.


> 
> https://lkml.org/lkml/2014/10/9/210
> 
> Anyway, this patch is better to go stable trees.
> 
> Acked-by: Masami Hiramatsu 
> 

Thanks!

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


Re: [PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-15 Thread Masami Hiramatsu
Hi Steven,

Thank you for fixing this bug!

(2015/01/15 0:40), Steven Rostedt wrote:
> From: "Steven Rostedt (Red Hat)" 
> 
> If the function graph tracer traces a jprobe callback, the system will
> crash. This can easily be demonstrated by compiling the jprobe
> sample module that is in the kernel tree, loading it and running the
> function graph tracer.
> 
>  # modprobe jprobe_example.ko
>  # echo function_graph > /sys/kernel/debug/tracing/current_tracer
>  # ls
> 
> The first two commands end up in a nice crash after the first fork.
> (do_fork has a jprobe attached to it, so "ls" just triggers that fork)
> 
> The problem is caused by the jprobe_return() that all jprobe callbacks
> must end with. The way jprobes works is that the function a jprobe
> is attached to has a breakpoint placed at the start of it (or it uses
> ftrace if fentry is supported). The breakpoint handler (or ftrace callback)
> will copy the stack frame and change the ip address to return to the
> jprobe handler instead of the function. The jprobe handler must end
> with jprobe_return() which swaps the stack and does an int3 (breakpoint).
> This breakpoint handler will then put back the saved stack frame,
> simulate the instruction at the beginning of the function it added
> a breakpoint to, and then continue on.
> 
> For function tracing to work, it hijakes the return address from the
> stack frame, and replaces it with a hook function that will trace
> the end of the call. This hook function will restore the return
> address of the function call.

Yeah, function-graph tracer makes a hidden return-address stack for
each thread for storing the return address.

> If the function tracer traces the jprobe handler, the hook function
> for that handler will not be called, and its saved return address
> will be used for the next function. This will result in a kernel crash.

Actually, both jprobe (user-defined) handler and jprobe_return() doesn't
execute "ret".
So, right after run out the jprobe handler with function-graph tracer,
on the top of its hidden stack, there are at least 2(*) unused return
addresses, one is for jprobe handler (this should be same as the probed
function's return address) and other is jprobe_return()'s return address.
(*: this can be more than 2 if jprobe_return is called from a function
 which is called from jprobe handler)

So, the hidden stack may be as below;

[jprobe_return() return address]
[probed function return address]
[probed function return address]

After jumping back to the probed function, the function return is
trapped by the function-graph tracer, and it uses jprobe_return()'s
return address. Since usually jprobe_return() is called at the end of
the function, CPU will execute "ret" soon again(if someone puts a BUG
right after jprobe_return(), the kernel will show that BUG), and it
returns to the caller of the probed function.
However, there still be the probed function return address on the
hidden stack! This means that the next "ret" will go back to the same
address but with modified register and stacks.

> To solve this, pause function tracing before the jprobe handler is called
> and unpause it before it returns back to the function it probed.

Agreed, but it also could drop some NMI events. That is downside.

> Some other updates:
> 
> Used a variable "saved_sp" to hold kcb->jprobe_saved_sp. This makes the
> code look a bit cleaner and easier to understand (various tries to fix
> this bug required this change).

OK.

> Note, if fentry is being used, jprobes will change the ip address before
> the function graph tracer runs and it will not be able to trace the
> function that the jprobe is probing.

yes, it should be fixed.

BTW, my last part of IPMODIFY patches (which is not yet merged)
can solve this a different way. It sets IPMODIFY flag only to jprobe.
So, if function-graph tracer sets IPMODIFY flag, user can not enable
function-graph tracer when jprobe is used.

https://lkml.org/lkml/2014/10/9/210

Anyway, this patch is better to go stable trees.

Acked-by: Masami Hiramatsu 

Thank you,

> 
> Cc: sta...@vger.kernel.org # 2.6.30+
> Cc: Masami Hiramatsu 
> Signed-off-by: Steven Rostedt 
> ---
>  arch/x86/kernel/kprobes/core.c | 20 +++-
>  1 file changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
> index f7e3cd50ece0..98f654d466e5 100644
> --- a/arch/x86/kernel/kprobes/core.c
> +++ b/arch/x86/kernel/kprobes/core.c
> @@ -1020,6 +1020,15 @@ int setjmp_pre_handler(struct kprobe *p, struct 
> pt_regs *regs)
>   regs->flags &= ~X86_EFLAGS_IF;
>   trace_hardirqs_off();
>   regs->ip = (unsigned long)(jp->entry);
> +
> + /*
> +  * jprobes use jprobe_return() which skips the normal return
> +  * path of the function, and this messes up the accounting of the
> +  * function graph tracer to get messed up.
> +  *
> +  * Pause function graph tracing while performing the jprobe 

Re: [PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-15 Thread Masami Hiramatsu
Hi Steven,

Thank you for fixing this bug!

(2015/01/15 0:40), Steven Rostedt wrote:
 From: Steven Rostedt (Red Hat) rost...@goodmis.org
 
 If the function graph tracer traces a jprobe callback, the system will
 crash. This can easily be demonstrated by compiling the jprobe
 sample module that is in the kernel tree, loading it and running the
 function graph tracer.
 
  # modprobe jprobe_example.ko
  # echo function_graph  /sys/kernel/debug/tracing/current_tracer
  # ls
 
 The first two commands end up in a nice crash after the first fork.
 (do_fork has a jprobe attached to it, so ls just triggers that fork)
 
 The problem is caused by the jprobe_return() that all jprobe callbacks
 must end with. The way jprobes works is that the function a jprobe
 is attached to has a breakpoint placed at the start of it (or it uses
 ftrace if fentry is supported). The breakpoint handler (or ftrace callback)
 will copy the stack frame and change the ip address to return to the
 jprobe handler instead of the function. The jprobe handler must end
 with jprobe_return() which swaps the stack and does an int3 (breakpoint).
 This breakpoint handler will then put back the saved stack frame,
 simulate the instruction at the beginning of the function it added
 a breakpoint to, and then continue on.
 
 For function tracing to work, it hijakes the return address from the
 stack frame, and replaces it with a hook function that will trace
 the end of the call. This hook function will restore the return
 address of the function call.

Yeah, function-graph tracer makes a hidden return-address stack for
each thread for storing the return address.

 If the function tracer traces the jprobe handler, the hook function
 for that handler will not be called, and its saved return address
 will be used for the next function. This will result in a kernel crash.

Actually, both jprobe (user-defined) handler and jprobe_return() doesn't
execute ret.
So, right after run out the jprobe handler with function-graph tracer,
on the top of its hidden stack, there are at least 2(*) unused return
addresses, one is for jprobe handler (this should be same as the probed
function's return address) and other is jprobe_return()'s return address.
(*: this can be more than 2 if jprobe_return is called from a function
 which is called from jprobe handler)

So, the hidden stack may be as below;

[jprobe_return() return address]
[probed function return address]
[probed function return address]

After jumping back to the probed function, the function return is
trapped by the function-graph tracer, and it uses jprobe_return()'s
return address. Since usually jprobe_return() is called at the end of
the function, CPU will execute ret soon again(if someone puts a BUG
right after jprobe_return(), the kernel will show that BUG), and it
returns to the caller of the probed function.
However, there still be the probed function return address on the
hidden stack! This means that the next ret will go back to the same
address but with modified register and stacks.

 To solve this, pause function tracing before the jprobe handler is called
 and unpause it before it returns back to the function it probed.

Agreed, but it also could drop some NMI events. That is downside.

 Some other updates:
 
 Used a variable saved_sp to hold kcb-jprobe_saved_sp. This makes the
 code look a bit cleaner and easier to understand (various tries to fix
 this bug required this change).

OK.

 Note, if fentry is being used, jprobes will change the ip address before
 the function graph tracer runs and it will not be able to trace the
 function that the jprobe is probing.

yes, it should be fixed.

BTW, my last part of IPMODIFY patches (which is not yet merged)
can solve this a different way. It sets IPMODIFY flag only to jprobe.
So, if function-graph tracer sets IPMODIFY flag, user can not enable
function-graph tracer when jprobe is used.

https://lkml.org/lkml/2014/10/9/210

Anyway, this patch is better to go stable trees.

Acked-by: Masami Hiramatsu masami.hiramatsu...@hitachi.com

Thank you,

 
 Cc: sta...@vger.kernel.org # 2.6.30+
 Cc: Masami Hiramatsu masami.hiramatsu...@hitachi.com
 Signed-off-by: Steven Rostedt rost...@goodmis.org
 ---
  arch/x86/kernel/kprobes/core.c | 20 +++-
  1 file changed, 15 insertions(+), 5 deletions(-)
 
 diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
 index f7e3cd50ece0..98f654d466e5 100644
 --- a/arch/x86/kernel/kprobes/core.c
 +++ b/arch/x86/kernel/kprobes/core.c
 @@ -1020,6 +1020,15 @@ int setjmp_pre_handler(struct kprobe *p, struct 
 pt_regs *regs)
   regs-flags = ~X86_EFLAGS_IF;
   trace_hardirqs_off();
   regs-ip = (unsigned long)(jp-entry);
 +
 + /*
 +  * jprobes use jprobe_return() which skips the normal return
 +  * path of the function, and this messes up the accounting of the
 +  * function graph tracer to get messed up.
 +  *
 +  * Pause function graph tracing while performing 

Re: [PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-15 Thread Steven Rostedt
On Thu, 15 Jan 2015 20:57:29 +0900
Masami Hiramatsu masami.hiramatsu...@hitachi.com wrote:
 
  If the function tracer traces the jprobe handler, the hook function
  for that handler will not be called, and its saved return address
  will be used for the next function. This will result in a kernel
  crash.
 
 Actually, both jprobe (user-defined) handler and jprobe_return()
 doesn't execute ret.

Yep I new that. But a notrace on jprobe_return isn't that big of a
deal. It's not a function we really need to trace, as it really doesn't
do anything but being a 'hack' for jprobes to return properly.

 So, right after run out the jprobe handler with function-graph tracer,
 on the top of its hidden stack, there are at least 2(*) unused return
 addresses, one is for jprobe handler (this should be same as the
 probed function's return address) and other is jprobe_return()'s
 return address. (*: this can be more than 2 if jprobe_return is
 called from a function which is called from jprobe handler)
 
 So, the hidden stack may be as below;
 
 [jprobe_return() return address]
 [probed function return address]
 [probed function return address]
 
 After jumping back to the probed function, the function return is
 trapped by the function-graph tracer, and it uses jprobe_return()'s
 return address. Since usually jprobe_return() is called at the end of
 the function, CPU will execute ret soon again(if someone puts a BUG
 right after jprobe_return(), the kernel will show that BUG), and it
 returns to the caller of the probed function.
 However, there still be the probed function return address on the
 hidden stack! This means that the next ret will go back to the same
 address but with modified register and stacks.

Yep, I discovered all this with my patch that allows function tracing
with jprobes.

 
  To solve this, pause function tracing before the jprobe handler is
  called and unpause it before it returns back to the function it
  probed.
 
 Agreed, but it also could drop some NMI events. That is downside.
 
  Some other updates:
  
  Used a variable saved_sp to hold kcb-jprobe_saved_sp. This makes
  the code look a bit cleaner and easier to understand (various tries
  to fix this bug required this change).
 
 OK.
 
  Note, if fentry is being used, jprobes will change the ip address
  before the function graph tracer runs and it will not be able to
  trace the function that the jprobe is probing.
 
 yes, it should be fixed.
 
 BTW, my last part of IPMODIFY patches (which is not yet merged)
 can solve this a different way. It sets IPMODIFY flag only to jprobe.
 So, if function-graph tracer sets IPMODIFY flag, user can not enable
 function-graph tracer when jprobe is used.

Nah, I don't want to stop jprobes due to function graph tracing or vice
versa.

function graph tracer doesn't change the regs-ip, so it doesn't need
the flag. But I sent out a patch that fixes this for this case. Let me
know what you think of that one.


 
 https://lkml.org/lkml/2014/10/9/210
 
 Anyway, this patch is better to go stable trees.
 
 Acked-by: Masami Hiramatsu masami.hiramatsu...@hitachi.com
 

Thanks!

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


Re: [PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-14 Thread Steven Rostedt
On Wed, 14 Jan 2015 17:55:37 +0100
Borislav Petkov  wrote:

 
> Err, stupid question: marking the jprobe handler "notrace" doesn't help?
> 

A few reasons.

One, that would require all users to make their handler as "notrace".
That's not very reliable. Not to mention, I still work at Red Hat and
we have this KABI thingy, where the jprobe modules don't need to change
and we still need to fix it.

This change is much more robust that expecting jprobe callers to add
notrace.

Two, I HATE when a notrace is added for function graph tracing that
is not needed for function tracing. As I told Masami, every "notrace"
added to the kernel makes function tracing that much more useless.

Function tracing should be allowed to debug jprobes.

Three, I have a patch that lets this all work if the kprobe/jprobes
uses the ftrace fentry infrastructure (the work I original did). Why
break everything for something the requires jprobe users to do things
correctly?

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


Re: [PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-14 Thread Borislav Petkov
On Wed, Jan 14, 2015 at 10:40:01AM -0500, Steven Rostedt wrote:
> From: "Steven Rostedt (Red Hat)" 
> 
> If the function graph tracer traces a jprobe callback, the system will
> crash. This can easily be demonstrated by compiling the jprobe
> sample module that is in the kernel tree, loading it and running the
> function graph tracer.
> 
>  # modprobe jprobe_example.ko
>  # echo function_graph > /sys/kernel/debug/tracing/current_tracer
>  # ls
> 
> The first two commands end up in a nice crash after the first fork.
> (do_fork has a jprobe attached to it, so "ls" just triggers that fork)
> 
> The problem is caused by the jprobe_return() that all jprobe callbacks
> must end with. The way jprobes works is that the function a jprobe
> is attached to has a breakpoint placed at the start of it (or it uses
> ftrace if fentry is supported). The breakpoint handler (or ftrace callback)
> will copy the stack frame and change the ip address to return to the
> jprobe handler instead of the function. The jprobe handler must end
> with jprobe_return() which swaps the stack and does an int3 (breakpoint).
> This breakpoint handler will then put back the saved stack frame,
> simulate the instruction at the beginning of the function it added
> a breakpoint to, and then continue on.
> 
> For function tracing to work, it hijakes the return address from the
> stack frame, and replaces it with a hook function that will trace
> the end of the call. This hook function will restore the return
> address of the function call.
> 
> If the function tracer traces the jprobe handler, the hook function
> for that handler will not be called, and its saved return address
> will be used for the next function. This will result in a kernel crash.
> 
> To solve this, pause function tracing before the jprobe handler is called
> and unpause it before it returns back to the function it probed.

Err, stupid question: marking the jprobe handler "notrace" doesn't help?

-- 
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-14 Thread Steven Rostedt
From: "Steven Rostedt (Red Hat)" 

If the function graph tracer traces a jprobe callback, the system will
crash. This can easily be demonstrated by compiling the jprobe
sample module that is in the kernel tree, loading it and running the
function graph tracer.

 # modprobe jprobe_example.ko
 # echo function_graph > /sys/kernel/debug/tracing/current_tracer
 # ls

The first two commands end up in a nice crash after the first fork.
(do_fork has a jprobe attached to it, so "ls" just triggers that fork)

The problem is caused by the jprobe_return() that all jprobe callbacks
must end with. The way jprobes works is that the function a jprobe
is attached to has a breakpoint placed at the start of it (or it uses
ftrace if fentry is supported). The breakpoint handler (or ftrace callback)
will copy the stack frame and change the ip address to return to the
jprobe handler instead of the function. The jprobe handler must end
with jprobe_return() which swaps the stack and does an int3 (breakpoint).
This breakpoint handler will then put back the saved stack frame,
simulate the instruction at the beginning of the function it added
a breakpoint to, and then continue on.

For function tracing to work, it hijakes the return address from the
stack frame, and replaces it with a hook function that will trace
the end of the call. This hook function will restore the return
address of the function call.

If the function tracer traces the jprobe handler, the hook function
for that handler will not be called, and its saved return address
will be used for the next function. This will result in a kernel crash.

To solve this, pause function tracing before the jprobe handler is called
and unpause it before it returns back to the function it probed.

Some other updates:

Used a variable "saved_sp" to hold kcb->jprobe_saved_sp. This makes the
code look a bit cleaner and easier to understand (various tries to fix
this bug required this change).

Note, if fentry is being used, jprobes will change the ip address before
the function graph tracer runs and it will not be able to trace the
function that the jprobe is probing.

Cc: sta...@vger.kernel.org # 2.6.30+
Cc: Masami Hiramatsu 
Signed-off-by: Steven Rostedt 
---
 arch/x86/kernel/kprobes/core.c | 20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index f7e3cd50ece0..98f654d466e5 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -1020,6 +1020,15 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs 
*regs)
regs->flags &= ~X86_EFLAGS_IF;
trace_hardirqs_off();
regs->ip = (unsigned long)(jp->entry);
+
+   /*
+* jprobes use jprobe_return() which skips the normal return
+* path of the function, and this messes up the accounting of the
+* function graph tracer to get messed up.
+*
+* Pause function graph tracing while performing the jprobe function.
+*/
+   pause_graph_tracing();
return 1;
 }
 NOKPROBE_SYMBOL(setjmp_pre_handler);
@@ -1048,24 +1057,25 @@ int longjmp_break_handler(struct kprobe *p, struct 
pt_regs *regs)
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
u8 *addr = (u8 *) (regs->ip - 1);
struct jprobe *jp = container_of(p, struct jprobe, kp);
+   void *saved_sp = kcb->jprobe_saved_sp;
 
if ((addr > (u8 *) jprobe_return) &&
(addr < (u8 *) jprobe_return_end)) {
-   if (stack_addr(regs) != kcb->jprobe_saved_sp) {
+   if (stack_addr(regs) != saved_sp) {
struct pt_regs *saved_regs = >jprobe_saved_regs;
printk(KERN_ERR
   "current sp %p does not match saved sp %p\n",
-  stack_addr(regs), kcb->jprobe_saved_sp);
+  stack_addr(regs), saved_sp);
printk(KERN_ERR "Saved registers for jprobe %p\n", jp);
show_regs(saved_regs);
printk(KERN_ERR "Current registers\n");
show_regs(regs);
BUG();
}
+   /* It's OK to start function graph tracing again */
+   unpause_graph_tracing();
*regs = kcb->jprobe_saved_regs;
-   memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp),
-  kcb->jprobes_stack,
-  MIN_STACK_SIZE(kcb->jprobe_saved_sp));
+   memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp));
preempt_enable_no_resched();
return 1;
}
-- 
2.1.4


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


[PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-14 Thread Steven Rostedt
From: Steven Rostedt (Red Hat) rost...@goodmis.org

If the function graph tracer traces a jprobe callback, the system will
crash. This can easily be demonstrated by compiling the jprobe
sample module that is in the kernel tree, loading it and running the
function graph tracer.

 # modprobe jprobe_example.ko
 # echo function_graph  /sys/kernel/debug/tracing/current_tracer
 # ls

The first two commands end up in a nice crash after the first fork.
(do_fork has a jprobe attached to it, so ls just triggers that fork)

The problem is caused by the jprobe_return() that all jprobe callbacks
must end with. The way jprobes works is that the function a jprobe
is attached to has a breakpoint placed at the start of it (or it uses
ftrace if fentry is supported). The breakpoint handler (or ftrace callback)
will copy the stack frame and change the ip address to return to the
jprobe handler instead of the function. The jprobe handler must end
with jprobe_return() which swaps the stack and does an int3 (breakpoint).
This breakpoint handler will then put back the saved stack frame,
simulate the instruction at the beginning of the function it added
a breakpoint to, and then continue on.

For function tracing to work, it hijakes the return address from the
stack frame, and replaces it with a hook function that will trace
the end of the call. This hook function will restore the return
address of the function call.

If the function tracer traces the jprobe handler, the hook function
for that handler will not be called, and its saved return address
will be used for the next function. This will result in a kernel crash.

To solve this, pause function tracing before the jprobe handler is called
and unpause it before it returns back to the function it probed.

Some other updates:

Used a variable saved_sp to hold kcb-jprobe_saved_sp. This makes the
code look a bit cleaner and easier to understand (various tries to fix
this bug required this change).

Note, if fentry is being used, jprobes will change the ip address before
the function graph tracer runs and it will not be able to trace the
function that the jprobe is probing.

Cc: sta...@vger.kernel.org # 2.6.30+
Cc: Masami Hiramatsu masami.hiramatsu...@hitachi.com
Signed-off-by: Steven Rostedt rost...@goodmis.org
---
 arch/x86/kernel/kprobes/core.c | 20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index f7e3cd50ece0..98f654d466e5 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -1020,6 +1020,15 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs 
*regs)
regs-flags = ~X86_EFLAGS_IF;
trace_hardirqs_off();
regs-ip = (unsigned long)(jp-entry);
+
+   /*
+* jprobes use jprobe_return() which skips the normal return
+* path of the function, and this messes up the accounting of the
+* function graph tracer to get messed up.
+*
+* Pause function graph tracing while performing the jprobe function.
+*/
+   pause_graph_tracing();
return 1;
 }
 NOKPROBE_SYMBOL(setjmp_pre_handler);
@@ -1048,24 +1057,25 @@ int longjmp_break_handler(struct kprobe *p, struct 
pt_regs *regs)
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
u8 *addr = (u8 *) (regs-ip - 1);
struct jprobe *jp = container_of(p, struct jprobe, kp);
+   void *saved_sp = kcb-jprobe_saved_sp;
 
if ((addr  (u8 *) jprobe_return) 
(addr  (u8 *) jprobe_return_end)) {
-   if (stack_addr(regs) != kcb-jprobe_saved_sp) {
+   if (stack_addr(regs) != saved_sp) {
struct pt_regs *saved_regs = kcb-jprobe_saved_regs;
printk(KERN_ERR
   current sp %p does not match saved sp %p\n,
-  stack_addr(regs), kcb-jprobe_saved_sp);
+  stack_addr(regs), saved_sp);
printk(KERN_ERR Saved registers for jprobe %p\n, jp);
show_regs(saved_regs);
printk(KERN_ERR Current registers\n);
show_regs(regs);
BUG();
}
+   /* It's OK to start function graph tracing again */
+   unpause_graph_tracing();
*regs = kcb-jprobe_saved_regs;
-   memcpy((kprobe_opcode_t *)(kcb-jprobe_saved_sp),
-  kcb-jprobes_stack,
-  MIN_STACK_SIZE(kcb-jprobe_saved_sp));
+   memcpy(saved_sp, kcb-jprobes_stack, MIN_STACK_SIZE(saved_sp));
preempt_enable_no_resched();
return 1;
}
-- 
2.1.4


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

Re: [PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-14 Thread Steven Rostedt
On Wed, 14 Jan 2015 17:55:37 +0100
Borislav Petkov b...@alien8.de wrote:

 
 Err, stupid question: marking the jprobe handler notrace doesn't help?
 

A few reasons.

One, that would require all users to make their handler as notrace.
That's not very reliable. Not to mention, I still work at Red Hat and
we have this KABI thingy, where the jprobe modules don't need to change
and we still need to fix it.

This change is much more robust that expecting jprobe callers to add
notrace.

Two, I HATE when a notrace is added for function graph tracing that
is not needed for function tracing. As I told Masami, every notrace
added to the kernel makes function tracing that much more useless.

Function tracing should be allowed to debug jprobes.

Three, I have a patch that lets this all work if the kprobe/jprobes
uses the ftrace fentry infrastructure (the work I original did). Why
break everything for something the requires jprobe users to do things
correctly?

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


Re: [PATCH 3/3] ftrace/jprobes/x86: Fix conflict between jprobes and function graph tracing

2015-01-14 Thread Borislav Petkov
On Wed, Jan 14, 2015 at 10:40:01AM -0500, Steven Rostedt wrote:
 From: Steven Rostedt (Red Hat) rost...@goodmis.org
 
 If the function graph tracer traces a jprobe callback, the system will
 crash. This can easily be demonstrated by compiling the jprobe
 sample module that is in the kernel tree, loading it and running the
 function graph tracer.
 
  # modprobe jprobe_example.ko
  # echo function_graph  /sys/kernel/debug/tracing/current_tracer
  # ls
 
 The first two commands end up in a nice crash after the first fork.
 (do_fork has a jprobe attached to it, so ls just triggers that fork)
 
 The problem is caused by the jprobe_return() that all jprobe callbacks
 must end with. The way jprobes works is that the function a jprobe
 is attached to has a breakpoint placed at the start of it (or it uses
 ftrace if fentry is supported). The breakpoint handler (or ftrace callback)
 will copy the stack frame and change the ip address to return to the
 jprobe handler instead of the function. The jprobe handler must end
 with jprobe_return() which swaps the stack and does an int3 (breakpoint).
 This breakpoint handler will then put back the saved stack frame,
 simulate the instruction at the beginning of the function it added
 a breakpoint to, and then continue on.
 
 For function tracing to work, it hijakes the return address from the
 stack frame, and replaces it with a hook function that will trace
 the end of the call. This hook function will restore the return
 address of the function call.
 
 If the function tracer traces the jprobe handler, the hook function
 for that handler will not be called, and its saved return address
 will be used for the next function. This will result in a kernel crash.
 
 To solve this, pause function tracing before the jprobe handler is called
 and unpause it before it returns back to the function it probed.

Err, stupid question: marking the jprobe handler notrace doesn't help?

-- 
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/