summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2015-09-24 18:33:49 +0300
committerDmitry Kovalenko <d.kovalenko@samsung.com>2015-09-24 08:36:24 -0700
commit41475215c33bb478822f97c6b9bd6aad5e517068 (patch)
tree36f1f150074d6c5e96ae8f39edf1f11a4eadc387
parentcf52234660faaa6592cd8c01cdef7d819ed35f55 (diff)
downloadswap-modules-41475215c33bb478822f97c6b9bd6aad5e517068.tar.gz
swap-modules-41475215c33bb478822f97c6b9bd6aad5e517068.tar.bz2
swap-modules-41475215c33bb478822f97c6b9bd6aad5e517068.zip
[FIX] uprobe: memory access to US for x86
Change-Id: Ib24db9b392855a82ace15dfe282119c1047e4470 Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
-rw-r--r--uprobe/arch/x86/swap-asm/swap_uprobes.c68
1 files 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 c743cdee..518c3046 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;
}