Implement funtions for kernel/user data access 22/111122/5
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 18 Jan 2017 09:32:57 +0000 (12:32 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 31 Jan 2017 07:21:26 +0000 (10:21 +0300)
for kernel space:
- swap_get_kpc
- swap_set_kpc

for user space:
- swap_get_upc
- swap_set_upc

- swap_get_uret_addr
- swap_set_uret_addr

Change-Id: I9014addba8b219803ba33c41c2a3c051b626c1a9
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
12 files changed:
arch/arm/uprobe/swap_uprobe.h
got_patcher/gt_module.c
kprobe/arch/arm/swap-asm/swap_kprobes.h
kprobe/arch/arm64/swap-asm/swap_kprobes.h
kprobe/arch/x86/swap-asm/swap_kprobes.h
loader/loader_module.c
preload/preload_module.c
uihv/uihv_module.c
uprobe/arch/arm/swap-asm/swap_uprobes.c
uprobe/arch/arm/swap-asm/swap_uprobes.h
uprobe/arch/arm64/swap-asm/swap_uprobes.h
uprobe/arch/x86/swap-asm/swap_uprobes.h

index 4ae91a8..86941d0 100644 (file)
@@ -34,6 +34,22 @@ struct uretprobe;
 struct uretprobe_instance;
 
 
+static inline unsigned long swap_get_upc_arm(struct pt_regs *regs)
+{
+       return regs->ARM_pc | !!thumb_mode(regs);
+}
+
+static inline void swap_set_upc_arm(struct pt_regs *regs, unsigned long val)
+{
+       if (val & 1) {
+               regs->ARM_pc = val & ~1UL;
+               regs->ARM_cpsr |= PSR_T_BIT;
+       } else {
+               regs->ARM_pc = val;
+               regs->ARM_cpsr &= ~PSR_T_BIT;
+       }
+}
+
 static inline unsigned long swap_get_uarg_arm(struct pt_regs *regs,
                                              unsigned long n)
 {
@@ -83,6 +99,16 @@ static inline void swap_put_uarg_arm(struct pt_regs *regs, unsigned long n,
        }
 }
 
+static inline unsigned long swap_get_uret_addr_arm(struct pt_regs *regs)
+{
+       return regs->ARM_lr;
+}
+
+static inline void swap_set_uret_addr_arm(struct pt_regs *regs, unsigned long v)
+{
+       regs->ARM_lr = v;
+}
+
 int arch_prepare_uprobe_arm(struct uprobe *p);
 int arch_arm_uprobe_arm(struct uprobe *p);
 void arch_disarm_uprobe_arm(struct uprobe *p, struct task_struct *task);
index fd9257c..40b8ea8 100644 (file)
@@ -240,7 +240,7 @@ static int _process_eh(struct uretprobe_instance *ri, struct pt_regs *regs,
        struct pd_t *pd = _get_process_data(ri->rp);
        struct hd_t *hd;
        unsigned long vaddr = 0;
-       unsigned long old_pc = swap_get_instr_ptr(regs);
+       unsigned long old_pc = swap_get_upc(regs);
 
        if ((dentry == NULL) || _is_in_handler())
                goto out_set_orig;
@@ -259,7 +259,7 @@ out_set_orig:
        loader_set_priv_origin(ri, vaddr);
 
        /* PC change check */
-       return old_pc != swap_get_instr_ptr(regs);
+       return old_pc != swap_get_upc(regs);
 }
 
 static int dl_fixup_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
index af69674..183cba8 100644 (file)
@@ -128,7 +128,7 @@ static inline void swap_set_stack_ptr(struct pt_regs *regs, unsigned long sp)
  * @param regs Pointer to CPU registers data.
  * @return Pointer to pc.
  */
-static inline unsigned long swap_get_instr_ptr(struct pt_regs *regs)
+static inline unsigned long swap_get_kpc(struct pt_regs *regs)
 {
        return regs->ARM_pc | !!thumb_mode(regs);
 }
@@ -140,7 +140,7 @@ static inline unsigned long swap_get_instr_ptr(struct pt_regs *regs)
  * @param val Address that should be stored in pc.
  * @return Void.
  */
-static inline void swap_set_instr_ptr(struct pt_regs *regs, unsigned long val)
+static inline void swap_set_kpc(struct pt_regs *regs, unsigned long val)
 {
        if (val & 1) {
                regs->ARM_pc = val & ~1;
@@ -152,29 +152,6 @@ static inline void swap_set_instr_ptr(struct pt_regs *regs, unsigned long val)
 }
 
 /**
- * @brief Gets return address.
- *
- * @param regs Pointer to CPU registers data.
- * @return Return address.
- */
-static inline unsigned long swap_get_ret_addr(struct pt_regs *regs)
-{
-       return regs->ARM_lr;
-}
-
-/**
- * @brief Sets return address.
- *
- * @param regs Pointer to CPU registers data.
- * @param val New return address.
- * @return Void.
- */
-static inline void swap_set_ret_addr(struct pt_regs *regs, unsigned long val)
-{
-       regs->ARM_lr = val;
-}
-
-/**
  * @brief Gets specified argument.
  *
  * @param regs Pointer to CPU registers data.
index a7708c6..4222501 100644 (file)
@@ -95,24 +95,13 @@ static inline unsigned long swap_get_sarg(struct pt_regs *regs,
        return swap_get_karg(regs, n);
 }
 
-static inline unsigned long swap_get_instr_ptr(struct pt_regs *regs)
+static inline unsigned long swap_get_kpc(struct pt_regs *regs)
 {
        WARN(1, "not implemented"); /* FIXME: to implement */
        return 0xdeadc0de;
 }
 
-static inline void swap_set_instr_ptr(struct pt_regs *regs, unsigned long val)
-{
-       WARN(1, "not implemented"); /* FIXME: to implement */
-}
-
-static inline unsigned long swap_get_ret_addr(struct pt_regs *regs)
-{
-       WARN(1, "not implemented"); /* FIXME: to implement */
-       return 0xdeadc0de;
-}
-
-static inline void swap_set_ret_addr(struct pt_regs *regs, unsigned long val)
+static inline void swap_set_kpc(struct pt_regs *regs, unsigned long val)
 {
        WARN(1, "not implemented"); /* FIXME: to implement */
 }
index 2a196ce..68f0f4c 100644 (file)
@@ -119,26 +119,14 @@ static inline void swap_set_stack_ptr(struct pt_regs *regs, unsigned long sp)
        regs->EREG(sp) = sp;
 }
 
-static inline unsigned long swap_get_instr_ptr(struct pt_regs *regs)
+static inline unsigned long swap_get_kpc(struct pt_regs *regs)
 {
-       return regs->EREG(ip);
+       return regs->ip;
 }
 
-static inline void swap_set_instr_ptr(struct pt_regs *regs, unsigned long val)
+static inline void swap_set_kpc(struct pt_regs *regs, unsigned long val)
 {
-       regs->EREG(ip) = val;
-}
-
-static inline unsigned long swap_get_ret_addr(struct pt_regs *regs)
-{
-       unsigned long addr = 0;
-       read_proc_vm_atomic(current, regs->EREG(sp), &addr, sizeof(addr));
-       return addr;
-}
-
-static inline void swap_set_ret_addr(struct pt_regs *regs, unsigned long val)
-{
-       write_proc_vm_atomic(current, regs->EREG(sp), &val, sizeof(val));
+       regs->ip = val;
 }
 
 static inline unsigned long swap_get_arg(struct pt_regs *regs, int num)
@@ -156,33 +144,6 @@ static inline void swap_set_arg(struct pt_regs *regs, int num,
                        &val, sizeof(val));
 }
 
-static inline int swap_fp_backtrace(struct task_struct *task,
-                                   unsigned long *buf, int max_cnt)
-{
-       int i = 0;
-       struct pt_regs *regs;
-
-       struct {
-               unsigned long next;
-               unsigned long raddr;
-       } frame;
-
-
-       regs = task_pt_regs(task);
-       frame.next = regs->EREG(bp);
-       frame.raddr = swap_get_ret_addr(regs);
-
-       while (frame.next && i < max_cnt) {
-               if (read_proc_vm_atomic(task, frame.next, &frame, sizeof(frame))
-                               == sizeof(frame))
-                       buf[i++] = frame.raddr;
-               else
-                       break;
-       }
-
-       return i;
-}
-
 /**
  * @struct prev_kp_core
  * @brief Stores previous kp_core.
index 53c38c5..ba04189 100644 (file)
@@ -116,7 +116,7 @@ static inline void __prepare_ujump(struct uretprobe_instance *ri,
        ri->preload.thumb = !!thumb_mode(regs);
 #endif /* CONFIG_ARM */
 
-       swap_set_instr_ptr(regs, vaddr);
+       swap_set_upc(regs, vaddr);
 }
 
 static inline void __save_uregs(struct uretprobe_instance *ri,
@@ -127,7 +127,7 @@ static inline void __save_uregs(struct uretprobe_instance *ri,
        memcpy(ri->data, regs, sizeof(*regs));
        priv->arg0 = swap_get_uarg(regs, 0);
        priv->arg1 = swap_get_uarg(regs, 1);
-       priv->raddr = swap_get_ret_addr(regs);
+       priv->raddr = swap_get_uret_addr(regs);
 }
 
 static inline void __restore_uregs(struct uretprobe_instance *ri,
@@ -138,7 +138,7 @@ static inline void __restore_uregs(struct uretprobe_instance *ri,
        memcpy(regs, ri->data, sizeof(*regs));
        swap_put_uarg(regs, 0, priv->arg0);
        swap_put_uarg(regs, 1, priv->arg1);
-       swap_set_ret_addr(regs, priv->raddr);
+       swap_set_uret_addr(regs, priv->raddr);
 #ifdef CONFIG_X86_32
        /* need to do it only on x86 */
        regs->EREG(ip) -= 1;
@@ -175,7 +175,7 @@ static inline void print_regs(const char *prefix, struct pt_regs *regs,
               (int)lpd_get_state(hd),
               prefix, (unsigned long)ri->rp->up.addr,
               regs->EREG(ip), swap_get_uarg(regs, 0), swap_get_uarg(regs, 1),
-              swap_get_ret_addr(regs));
+              swap_get_uret_addr(regs));
 #elif defined(CONFIG_ARM64)
        WARN(1, "not implemented"); /* FIXME: to implement */
        (void)dentry;
index 779f755..a58ffec 100644 (file)
@@ -175,7 +175,7 @@ static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
        struct pd_t *pd = __get_process_data(ri->rp);
        struct hd_t *hd;
-       unsigned long old_pc = swap_get_instr_ptr(regs);
+       unsigned long old_pc = swap_get_upc(regs);
        unsigned long flags = pt_get_flags(current);
        struct sspt_ip *ip = container_of(ri->rp, struct sspt_ip, retprobe);
        unsigned long vaddr = 0;
@@ -201,7 +201,7 @@ out_set_orig:
        loader_set_priv_origin(ri, vaddr);
 
        /* PC change check */
-       return old_pc != swap_get_instr_ptr(regs);
+       return old_pc != swap_get_upc(regs);
 }
 
 static void __do_preload_ret(struct uretprobe_instance *ri, struct hd_t *hd)
index dc6b501..b4d51c7 100644 (file)
@@ -138,7 +138,7 @@ static int uihv_main_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
        struct pd_t *pd = __get_process_data(ri->rp);
        struct hd_t *hd;
-       unsigned long old_pc = swap_get_instr_ptr(regs);
+       unsigned long old_pc = swap_get_upc(regs);
        unsigned long vaddr = 0;
 
        if (uihv_dentry == NULL)
@@ -154,7 +154,7 @@ static int uihv_main_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
        loader_set_priv_origin(ri, vaddr);
 
        /* PC change check */
-       return old_pc != swap_get_instr_ptr(regs);
+       return old_pc != swap_get_upc(regs);
 }
 
 static int uihv_main_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
index 2da7b7e..b237225 100644 (file)
@@ -129,7 +129,7 @@ int arch_disarm_urp_inst(struct uretprobe_instance *ri,
                         struct task_struct *task)
 {
        struct pt_regs *uregs = task_pt_regs(ri->task);
-       unsigned long ra = swap_get_ret_addr(uregs);
+       unsigned long ra = uregs->ARM_lr;
        unsigned long *tramp = (unsigned long *)arch_tramp_by_ri(ri);
        unsigned long *sp = (unsigned long *)((long)ri->sp & ~1);
        unsigned long *stack = sp - RETPROBE_STACK_DEPTH + 1;
@@ -185,7 +185,7 @@ check_lr: /* check lr anyway */
                       "lr = %08lx - %lx, set ret_addr=%p\n",
                       task->comm, task->tgid, task->pid, ra, vaddr, ri->ret_addr);
 
-               swap_set_ret_addr(uregs, (unsigned long)ri->ret_addr);
+               swap_set_uret_addr(uregs, (unsigned long)ri->ret_addr);
                retval = 0;
        } else if (retval) {
                printk(KERN_INFO "---> %s (%d/%d): trampoline NOT found at "
index ba954ec..9c12f96 100644 (file)
@@ -105,6 +105,16 @@ static inline void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task
        arch_disarm_uprobe_arm(p, task);
 }
 
+static inline unsigned long swap_get_upc(struct pt_regs *regs)
+{
+       return swap_get_upc_arm(regs);
+}
+
+static inline void swap_set_upc(struct pt_regs *regs, unsigned long val)
+{
+       swap_set_upc_arm(regs, val);
+}
+
 static inline unsigned long swap_get_uarg(struct pt_regs *regs, unsigned long n)
 {
        return swap_get_uarg_arm(regs, n);
@@ -116,6 +126,16 @@ static inline void swap_put_uarg(struct pt_regs *regs, unsigned long n,
        swap_put_uarg_arm(regs, n, val);
 }
 
+static inline unsigned long swap_get_uret_addr(struct pt_regs *regs)
+{
+       return swap_get_uret_addr_arm(regs);
+}
+
+static inline void swap_set_uret_addr(struct pt_regs *regs, unsigned long val)
+{
+       swap_set_uret_addr_arm(regs, val);
+}
+
 int swap_arch_init_uprobes(void);
 void swap_arch_exit_uprobes(void);
 
index 0976fb5..73032ed 100644 (file)
@@ -183,6 +183,17 @@ static inline void swap_put_uarg_arm64(struct pt_regs *regs, unsigned long n,
        }
 }
 
+static inline unsigned long swap_get_upc(struct pt_regs *regs)
+{
+       WARN(1, "not implemented"); /* FIXME: to implement */
+       return 0;
+}
+
+static inline void swap_set_upc(struct pt_regs *regs, unsigned long val)
+{
+       WARN(1, "not implemented"); /* FIXME: to implement */
+}
+
 static inline unsigned long swap_get_uarg(struct pt_regs *regs, unsigned long n)
 {
        if (compat_user_mode(regs))
@@ -197,6 +208,17 @@ static inline void swap_put_uarg(struct pt_regs *regs, unsigned long n,
        WARN(1, "not implemented"); /* FIXME: to implement */
 }
 
+static inline unsigned long swap_get_uret_addr(struct pt_regs *regs)
+{
+       WARN(1, "not implemented"); /* FIXME: to implement */
+       return 0;
+}
+
+static inline void swap_set_uret_addr(struct pt_regs *regs, unsigned long val)
+{
+       WARN(1, "not implemented"); /* FIXME: to implement */
+}
+
 int arch_prepare_uprobe(struct uprobe *p);
 void arch_remove_uprobe(struct uprobe *p);
 
index 7220e5f..ce759da 100644 (file)
@@ -100,31 +100,62 @@ void arch_remove_uprobe(struct uprobe *up);
 int arch_arm_uprobe(struct uprobe *p);
 void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task);
 
-static inline unsigned long swap_get_uarg(struct pt_regs *regs, unsigned long n)
+static inline unsigned long swap_get_upc(struct pt_regs *regs)
+{
+       return regs->ip;
+}
+
+static inline void swap_set_upc(struct pt_regs *regs, unsigned long val)
+{
+       regs->ip = val;
+}
+
+static inline unsigned long swap_get_ustack_val(struct pt_regs *regs,
+                                               unsigned long n)
 {
        u32 *ptr, addr = 0;
 
-       /* 1 - return address saved on top of the stack */
-       ptr = (u32 *)regs->sp + n + 1;
+       ptr = (u32 *)regs->sp + n;
        if (get_user(addr, ptr))
-               printk(KERN_INFO "failed to dereference a pointer, ptr=%p\n",
-                      ptr);
+               pr_err("Failed to dereference a pointer, ptr=%p\n", ptr);
 
        return addr;
 }
 
-static inline void swap_put_uarg(struct pt_regs *regs, unsigned long n,
-                                unsigned long val)
+static inline void swap_set_ustack_val(struct pt_regs *regs, unsigned long n,
+                                      unsigned long val)
 {
        u32 *ptr;
 
-       /* 1 - return address saved on top of the stack */
-       ptr = (u32 *)regs->sp + n + 1;
+       ptr = (u32 *)regs->sp + n;
        if (put_user(val, ptr))
-               printk(KERN_INFO "failed to dereference a pointer, ptr=%p\n",
-                      ptr);
+               pr_err("Failed to dereference a pointer, ptr=%p\n", ptr);
 }
 
+static inline unsigned long swap_get_uarg(struct pt_regs *regs, unsigned long n)
+{
+       /* 1 - return address saved on top of the stack */
+       return swap_get_ustack_val(regs, n + 1);
+}
+
+static inline void swap_put_uarg(struct pt_regs *regs, unsigned long n,
+                                unsigned long val)
+{
+       /* 1 - return address saved on top of the stack */
+       swap_set_ustack_val(regs, n + 1, val);
+}
+
+static inline unsigned long swap_get_uret_addr(struct pt_regs *regs)
+{
+       return swap_get_ustack_val(regs, 0);
+}
+
+static inline void swap_set_uret_addr(struct pt_regs *regs, unsigned long val)
+{
+       swap_set_ustack_val(regs, 0, val);
+}
+
+
 int swap_arch_init_uprobes(void);
 void swap_arch_exit_uprobes(void);