Fix user space retprobe disarming
authorVasiliy Ulyanov <v.ulyanov@samsung.com>
Wed, 27 Feb 2013 07:53:00 +0000 (11:53 +0400)
committerVasiliy Ulyanov <v.ulyanov@samsung.com>
Wed, 27 Feb 2013 07:53:00 +0000 (11:53 +0400)
For functions which do not push return address on stack

kprobe/arch/asm-arm/dbi_kprobes.h
kprobe/arch/asm-x86/dbi_kprobes.h
kprobe/dbi_uprobes.c

index 250f823..ff7dd5f 100644 (file)
@@ -101,6 +101,11 @@ static inline unsigned long dbi_get_ret_addr(struct pt_regs *regs)
        return regs->ARM_lr;
 }
 
+static inline void dbi_set_ret_addr(struct pt_regs *regs, unsigned long val)
+{
+       regs->ARM_lr = val;
+}
+
 static inline unsigned long dbi_get_arg(struct pt_regs *regs, int num)
 {
        return regs->uregs[num];
index 75193f8..c3b1741 100644 (file)
@@ -128,6 +128,11 @@ static inline unsigned long dbi_get_ret_addr(struct pt_regs *regs)
        return addr;
 }
 
+static inline void dbi_set_ret_addr(struct pt_regs *regs, unsigned long val)
+{
+       write_proc_vm_atomic(current, regs->EREG(sp), &val, sizeof(val));
+}
+
 static inline unsigned long dbi_get_arg(struct pt_regs *regs, int num)
 {
        unsigned long arg = 0;
index 1f3209a..3e6d394 100644 (file)
@@ -299,7 +299,8 @@ int dbi_disarm_urp_inst(struct kretprobe_instance *ri, struct task_struct *rm_ta
        if (found) {
                printk("---> %s (%d/%d): trampoline found at %08lx (%08lx /%+d) - %p\n",
                                task->comm, task->tgid, task->pid,
-                               (unsigned long)found, (unsigned long)ri->sp, found - ri->sp, ri->rp->kp.addr);
+                               (unsigned long)found, (unsigned long)ri->sp,
+                               found - ri->sp, ri->rp->kp.addr);
                retval = write_proc_vm_atomic(task, (unsigned long)found, &ri->ret_addr,
                                sizeof(ri->ret_addr));
                if (retval != sizeof(ri->ret_addr)) {
@@ -310,9 +311,19 @@ int dbi_disarm_urp_inst(struct kretprobe_instance *ri, struct task_struct *rm_ta
                        retval = 0;
                }
        } else {
-               printk("---> %s (%d/%d): trampoline NOT found at sp = %08lx - %p\n",
-                               task->comm, task->tgid, task->pid, (unsigned long)ri->sp, ri->rp->kp.addr);
-               retval = -ENOENT;
+               struct pt_regs *uregs = task_pt_regs(ri->task);
+               unsigned long ra = dbi_get_ret_addr(uregs);
+               if (ra == (unsigned long)tramp) {
+                       printk("---> %s (%d/%d): trampoline found at lr = %08lx - %p\n",
+                                       task->comm, task->tgid, task->pid, ra, ri->rp->kp.addr);
+                       dbi_set_ret_addr(uregs, (unsigned long)tramp);
+                       retval = 0;
+               } else {
+                       printk("---> %s (%d/%d): trampoline NOT found at sp = %08lx, lr = %08lx - %p\n",
+                                       task->comm, task->tgid, task->pid,
+                                       (unsigned long)ri->sp, ra, ri->rp->kp.addr);
+                       retval = -ENOENT;
+               }
        }
 
 out: