From 158c3f3acba667f99c4e7b38b1f4e764a412ccae Mon Sep 17 00:00:00 2001 From: Vasiliy Ulyanov Date: Wed, 27 Feb 2013 11:53:00 +0400 Subject: [PATCH] Fix user space retprobe disarming For functions which do not push return address on stack --- kprobe/arch/asm-arm/dbi_kprobes.h | 5 +++++ kprobe/arch/asm-x86/dbi_kprobes.h | 5 +++++ kprobe/dbi_uprobes.c | 19 +++++++++++++++---- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/kprobe/arch/asm-arm/dbi_kprobes.h b/kprobe/arch/asm-arm/dbi_kprobes.h index 250f823..ff7dd5f 100644 --- a/kprobe/arch/asm-arm/dbi_kprobes.h +++ b/kprobe/arch/asm-arm/dbi_kprobes.h @@ -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]; diff --git a/kprobe/arch/asm-x86/dbi_kprobes.h b/kprobe/arch/asm-x86/dbi_kprobes.h index 75193f8..c3b1741 100644 --- a/kprobe/arch/asm-x86/dbi_kprobes.h +++ b/kprobe/arch/asm-x86/dbi_kprobes.h @@ -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; diff --git a/kprobe/dbi_uprobes.c b/kprobe/dbi_uprobes.c index 1f3209a..3e6d394 100644 --- a/kprobe/dbi_uprobes.c +++ b/kprobe/dbi_uprobes.c @@ -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: -- 2.7.4