From 41475215c33bb478822f97c6b9bd6aad5e517068 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Thu, 24 Sep 2015 18:33:49 +0300 Subject: [PATCH] [FIX] uprobe: memory access to US for x86 Change-Id: Ib24db9b392855a82ace15dfe282119c1047e4470 Signed-off-by: Vyacheslav Cherkashin --- uprobe/arch/x86/swap-asm/swap_uprobes.c | 68 +++++++++++---------------------- 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/uprobe/arch/x86/swap-asm/swap_uprobes.c b/uprobe/arch/x86/swap-asm/swap_uprobes.c index c743cde..518c304 100644 --- a/uprobe/arch/x86/swap-asm/swap_uprobes.c +++ b/uprobe/arch/x86/swap-asm/swap_uprobes.c @@ -189,21 +189,22 @@ int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs) { /* Replace the return addr with trampoline addr */ unsigned long ra = trampoline_addr(&ri->rp->up); + unsigned long ret_addr; ri->sp = (kprobe_opcode_t *)regs->sp; - if (!read_proc_vm_atomic(current, regs->EREG(sp), &(ri->ret_addr), - sizeof(ri->ret_addr))) { - printk(KERN_ERR "failed to read user space func ra %lx addr=%p!\n", - regs->EREG(sp), ri->rp->up.kp.addr); + if (get_user(ret_addr, (unsigned long *)regs->sp)) { + pr_err("failed to read user space func ra %lx addr=%p!\n", + regs->sp, ri->rp->up.kp.addr); return -EINVAL; } - if (!write_proc_vm_atomic(current, regs->EREG(sp), &ra, sizeof(ra))) { - printk(KERN_ERR "failed to write user space func ra %lx!\n", - regs->EREG(sp)); + if (put_user(ra, (unsigned long *)regs->sp)) { + pr_err("failed to write user space func ra %lx!\n", regs->sp); return -EINVAL; } + ri->ret_addr = (kprobe_opcode_t *)ret_addr; + return 0; } @@ -218,7 +219,6 @@ int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs) int arch_disarm_urp_inst(struct uretprobe_instance *ri, struct task_struct *task, unsigned long tr) { - int len; unsigned long ret_addr; unsigned long sp = (unsigned long)ri->sp; unsigned long tramp_addr; @@ -228,17 +228,14 @@ int arch_disarm_urp_inst(struct uretprobe_instance *ri, else tramp_addr = tr; /* ri - invalid */ - len = read_proc_vm_atomic(task, sp, &ret_addr, sizeof(ret_addr)); - if (len != sizeof(ret_addr)) { + if (get_user(ret_addr, (unsigned long *)sp)) { printk(KERN_INFO "---> %s (%d/%d): failed to read stack from %08lx\n", task->comm, task->tgid, task->pid, sp); return -EFAULT; } if (tramp_addr == ret_addr) { - len = write_proc_vm_atomic(task, sp, &ri->ret_addr, - sizeof(ri->ret_addr)); - if (len != sizeof(ri->ret_addr)) { + if (put_user((unsigned long)ri->ret_addr, (unsigned long *)sp)) { printk(KERN_INFO "---> %s (%d/%d): failed to write " "orig_ret_addr to %08lx", task->comm, task->tgid, task->pid, sp); @@ -329,10 +326,9 @@ static void set_user_jmp_op(void *from, void *to) jop.raddr = (long)(to) - ((long)(from) + 5); jop.op = RELATIVEJUMP_INSTRUCTION; - if (!write_proc_vm_atomic(current, (unsigned long)from, &jop, - sizeof(jop))) - printk(KERN_WARNING - "failed to write jump opcode to user space %p\n", from); + if (put_user(jop.op, (char *)from) || + put_user(jop.raddr, (long *)(from + 1))) + pr_err("failed to write jump opcode to user space %p\n", from); } static void resume_execution(struct kprobe *p, @@ -347,19 +343,13 @@ static void resume_execution(struct kprobe *p, regs->EREG(flags) &= ~TF_MASK; tos = (unsigned long *)&tos_dword; - if (!read_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, - sizeof(tos_dword))) { - printk(KERN_WARNING - "failed to read dword from top of the user space stack %lx!\n", - regs->sp); + if (get_user(tos_dword, (unsigned long *)regs->sp)) { + pr_err("failed to read from user space sp=%lx!\n", regs->sp); return; } - if (!read_proc_vm_atomic(current, (unsigned long)p->ainsn.insn, insns, - 2 * sizeof(kprobe_opcode_t))) { - printk(KERN_WARNING - "failed to read first 2 opcodes of instruction copy from user space %p!\n", - p->ainsn.insn); + if (get_user(*(unsigned short *)insns, (unsigned short *)p->ainsn.insn)) { + pr_err("failed to read first 2 opcodes %p!\n", p->ainsn.insn); return; } @@ -383,13 +373,8 @@ static void resume_execution(struct kprobe *p, case 0x9a: /* call absolute -- same as call absolute, indirect */ *tos = orig_eip + (*tos - copy_eip); - if (!write_proc_vm_atomic(current, - regs->EREG(sp), - &tos_dword, - sizeof(tos_dword))) { - printk(KERN_WARNING - "failed to write dword to top of the user space stack %lx!\n", - regs->sp); + if (put_user(tos_dword, (unsigned long *)regs->sp)) { + pr_err("failed to write dword to sp=%lx\n", regs->sp); return; } @@ -403,12 +388,8 @@ static void resume_execution(struct kprobe *p, */ *tos = orig_eip + (*tos - copy_eip); - if (!write_proc_vm_atomic(current, regs->EREG(sp), - &tos_dword, - sizeof(tos_dword))) { - printk(KERN_WARNING - "failed to write dword to top of the user space stack %lx!\n", - regs->EREG(sp)); + if (put_user(tos_dword, (unsigned long *)regs->sp)) { + pr_err("failed to write dword to sp=%lx\n", regs->sp); return; } @@ -430,11 +411,8 @@ static void resume_execution(struct kprobe *p, break; } - if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, - sizeof(tos_dword))) { - printk(KERN_WARNING - "failed to write dword to top of the user space stack %lx!\n", - regs->EREG(sp)); + if (put_user(tos_dword, (unsigned long *)regs->sp)) { + pr_err("failed to write dword to sp=%lx\n", regs->sp); return; } -- 2.7.4