Commit 8bf1101b authored by Jim Keniston's avatar Jim Keniston Committed by Linus Torvalds

[PATCH] kprobes: Fix return probes on sys_execve

Fix a bug in kprobes that can cause an Oops or even a crash when a return
probe is installed on one of the following functions: sys_execve,
do_execve, load_*_binary, flush_old_exec, or flush_thread.  The fix is to
remove the call to kprobe_flush_task() in flush_thread().  This fix has
been tested on all architectures for which the return-probes feature has
been implemented (i386, x86_64, ppc64, ia64).  Please apply.

BACKGROUND

Up to now, we have called kprobe_flush_task() under two situations: when a
task exits, and when it execs.  Flushing kretprobe_instances on exit is
correct because (a) do_exit() doesn't return, and (b) one or more
return-probed functions may be active when a task calls do_exit().  Neither
is the case for sys_execve() and its callees.

Initially, the mistaken call to kprobe_flush_task() on exec was harmless
because we put the "real" return address of each active probed function
back in the stack, just to be safe, when we recycled its
kretprobe_instance.  When support for ppc64 and ia64 was added, this safety
measure couldn't be employed, and was eventually dropped even for i386 and
x86_64.  sys_execve() and its callees were informally blacklisted for
return probes until this fix was developed.
Acked-by: default avatarPrasanna S Panchamukhi <prasanna@in.ibm.com>
Signed-off-by: default avatarJim Keniston <jkenisto@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7c72aaf2
...@@ -393,13 +393,6 @@ void flush_thread(void) ...@@ -393,13 +393,6 @@ void flush_thread(void)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
/*
* Remove function-return probe instances associated with this task
* and put them back on the free list. Do not insert an exit probe for
* this function, it will be disabled by kprobe_flush_task if you do.
*/
kprobe_flush_task(tsk);
memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
/* /*
......
...@@ -718,13 +718,6 @@ kernel_thread_helper (int (*fn)(void *), void *arg) ...@@ -718,13 +718,6 @@ kernel_thread_helper (int (*fn)(void *), void *arg)
void void
flush_thread (void) flush_thread (void)
{ {
/*
* Remove function-return probe instances associated with this task
* and put them back on the free list. Do not insert an exit probe for
* this function, it will be disabled by kprobe_flush_task if you do.
*/
kprobe_flush_task(current);
/* drop floating-point and debug-register state if it exists: */ /* drop floating-point and debug-register state if it exists: */
current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
ia64_drop_fpu(current); ia64_drop_fpu(current);
......
...@@ -457,7 +457,6 @@ void flush_thread(void) ...@@ -457,7 +457,6 @@ void flush_thread(void)
if (t->flags & _TIF_ABI_PENDING) if (t->flags & _TIF_ABI_PENDING)
t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
#endif #endif
kprobe_flush_task(current);
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
if (last_task_used_math == current) if (last_task_used_math == current)
......
...@@ -351,13 +351,6 @@ void flush_thread(void) ...@@ -351,13 +351,6 @@ void flush_thread(void)
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct thread_info *t = current_thread_info(); struct thread_info *t = current_thread_info();
/*
* Remove function-return probe instances associated with this task
* and put them back on the free list. Do not insert an exit probe for
* this function, it will be disabled by kprobe_flush_task if you do.
*/
kprobe_flush_task(tsk);
if (t->flags & _TIF_ABI_PENDING) if (t->flags & _TIF_ABI_PENDING)
t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32); t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32);
......
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