diff options
author | Jim Keniston <jkenisto@us.ibm.com> | 2005-11-23 16:37:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-23 19:08:39 -0500 |
commit | 8bf1101bd52573e0573e374d56d2feecdbb5e444 (patch) | |
tree | 235bb46afaee00d5f97090d6e32fb779174d518c | |
parent | 7c72aaf29621d29ed19fd68c44edb45321645049 (diff) |
[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: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Signed-off-by: Jim Keniston <jkenisto@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/i386/kernel/process.c | 7 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/process.c | 1 | ||||
-rw-r--r-- | arch/x86_64/kernel/process.c | 7 |
4 files changed, 0 insertions, 22 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 1cb261f225d5..df6c2bcde067 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -393,13 +393,6 @@ void flush_thread(void) | |||
393 | { | 393 | { |
394 | struct task_struct *tsk = current; | 394 | struct task_struct *tsk = current; |
395 | 395 | ||
396 | /* | ||
397 | * Remove function-return probe instances associated with this task | ||
398 | * and put them back on the free list. Do not insert an exit probe for | ||
399 | * this function, it will be disabled by kprobe_flush_task if you do. | ||
400 | */ | ||
401 | kprobe_flush_task(tsk); | ||
402 | |||
403 | memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); | 396 | memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); |
404 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | 397 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); |
405 | /* | 398 | /* |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 4305d2ba76f6..2e33665d9c18 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -718,13 +718,6 @@ kernel_thread_helper (int (*fn)(void *), void *arg) | |||
718 | void | 718 | void |
719 | flush_thread (void) | 719 | flush_thread (void) |
720 | { | 720 | { |
721 | /* | ||
722 | * Remove function-return probe instances associated with this task | ||
723 | * and put them back on the free list. Do not insert an exit probe for | ||
724 | * this function, it will be disabled by kprobe_flush_task if you do. | ||
725 | */ | ||
726 | kprobe_flush_task(current); | ||
727 | |||
728 | /* drop floating-point and debug-register state if it exists: */ | 721 | /* drop floating-point and debug-register state if it exists: */ |
729 | current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); | 722 | current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); |
730 | ia64_drop_fpu(current); | 723 | ia64_drop_fpu(current); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index de69fb37c731..a5a7542a8ff3 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -457,7 +457,6 @@ void flush_thread(void) | |||
457 | if (t->flags & _TIF_ABI_PENDING) | 457 | if (t->flags & _TIF_ABI_PENDING) |
458 | t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); | 458 | t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); |
459 | #endif | 459 | #endif |
460 | kprobe_flush_task(current); | ||
461 | 460 | ||
462 | #ifndef CONFIG_SMP | 461 | #ifndef CONFIG_SMP |
463 | if (last_task_used_math == current) | 462 | if (last_task_used_math == current) |
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 5afd63e8cef7..7519fc520eb3 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -351,13 +351,6 @@ void flush_thread(void) | |||
351 | struct task_struct *tsk = current; | 351 | struct task_struct *tsk = current; |
352 | struct thread_info *t = current_thread_info(); | 352 | struct thread_info *t = current_thread_info(); |
353 | 353 | ||
354 | /* | ||
355 | * Remove function-return probe instances associated with this task | ||
356 | * and put them back on the free list. Do not insert an exit probe for | ||
357 | * this function, it will be disabled by kprobe_flush_task if you do. | ||
358 | */ | ||
359 | kprobe_flush_task(tsk); | ||
360 | |||
361 | if (t->flags & _TIF_ABI_PENDING) | 354 | if (t->flags & _TIF_ABI_PENDING) |
362 | t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32); | 355 | t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32); |
363 | 356 | ||