[PATCH] kprobes: Fix return probes on x86_64 __switch_to

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch against 2.6.16-rc1-mm3 fixes a bug in the x86_64
implementation of kprobes that can cause an Oops or crash when a return
probe is installed on __switch_to().  On x86_64, when __switch_to()
is called, we're running on the next task's stack but current points
to the previous task.  The fix handles this special case, causing the
kretprobe_instance to be hashed with the next task, where it will be
sought when __switch_to() returns.  Please apply.

Acked-by: Prasanna S Panchamukhi <[email protected]>
Signed-off-by: Jim Keniston <[email protected]>

Fixes a bug in the x86_64 implementation of kprobes that can cause
an Oops or crash when a return probe is installed on __switch_to().
On x86_64, when __switch_to() is called, we're running on one task's
stack but current points to a different task.  The fix adds code to
handle this special case.

---

 arch/x86_64/kernel/kprobes.c |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletion(-)

diff -puN arch/x86_64/kernel/kprobes.c~kretprobes-x86_64-switch_to arch/x86_64/kernel/kprobes.c
--- linux-2.6.16-rc1/arch/x86_64/kernel/kprobes.c~kretprobes-x86_64-switch_to	2006-01-25 10:26:56.000000000 -0800
+++ linux-2.6.16-rc1-jimk/arch/x86_64/kernel/kprobes.c	2006-01-25 10:27:17.000000000 -0800
@@ -272,8 +272,20 @@ void __kprobes arch_prepare_kretprobe(st
         struct kretprobe_instance *ri;
 
         if ((ri = get_free_rp_inst(rp)) != NULL) {
+		extern struct task_struct *__switch_to(
+			struct task_struct *prev_p, struct task_struct *next_p);
                 ri->rp = rp;
-                ri->task = current;
+		if (unlikely(rp->kp.addr == (kprobe_opcode_t*) __switch_to)) {
+			/*
+			 * We're entering __switch_to().
+			 * We've already switched to the next task's stack.
+			 * At this point, current = prev_p (%rdi), but when
+			 * we return, current = next_p (%rsi).  So point ri
+			 * at the next task so we can find ri upon return.
+			 */
+			ri->task = (struct task_struct *) regs->rsi;
+		} else
+			ri->task = current;
 		ri->ret_addr = (kprobe_opcode_t *) *sara;
 
 		/* Replace the return addr with trampoline addr */
_

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux