From 08a0c43bb2cbdde2f96b4664dec8ae3bf30f0c52 Mon Sep 17 00:00:00 2001 From: Anatolii Nikulin Date: Mon, 22 Jun 2015 15:45:02 +0300 Subject: [PATCH] [REFACTOR] remove kprobe from uprobe Change-Id: I378b0d6af97b3bd342b7708ffad2122d7e54073c Signed-off-by: Anatolii Nikulin --- fbiprobe/fbiprobe.c | 7 +- nsp/nsp.c | 12 +-- preload/preload_module.c | 18 ++-- uprobe/arch/arm/swap-asm/swap_uprobes.c | 116 +++++++++++++---------- uprobe/arch/arm/swap-asm/swap_uprobes.h | 7 +- uprobe/arch/x86/swap-asm/swap_uprobes.c | 86 ++++++++++------- uprobe/arch/x86/swap-asm/swap_uprobes.h | 6 +- uprobe/swap_uprobes.c | 159 +++++++++++++++----------------- uprobe/swap_uprobes.h | 85 +++++++++++++---- us_manager/probes/probe_info_new.c | 7 +- us_manager/probes/probe_info_new.h | 2 +- us_manager/sspt/sspt.h | 8 +- us_manager/sspt/sspt_debug.h | 2 +- wsp/wsp.c | 8 +- 14 files changed, 297 insertions(+), 226 deletions(-) diff --git a/fbiprobe/fbiprobe.c b/fbiprobe/fbiprobe.c index d507502..96c2467 100644 --- a/fbiprobe/fbiprobe.c +++ b/fbiprobe/fbiprobe.c @@ -255,10 +255,9 @@ exit: return 0; } -static int fbi_probe_handler(struct kprobe *p, struct pt_regs *regs) +static int fbi_probe_handler(struct uprobe *p, struct pt_regs *regs) { - struct uprobe *up = container_of(p, struct uprobe, kp); - struct us_ip *ip = container_of(up, struct us_ip, uprobe); + struct us_ip *ip = container_of(p, struct us_ip, uprobe); struct fbi_info *fbi_i = &ip->info->fbi_i; struct fbi_var_data *fbi_d = NULL; uint8_t i; @@ -308,7 +307,7 @@ void fbi_probe_cleanup(struct probe_info *probe_i) void fbi_probe_init(struct us_ip *ip) { - ip->uprobe.kp.pre_handler = (kprobe_pre_handler_t)fbi_probe_handler; + ip->uprobe.pre_handler = (uprobe_pre_handler_t)fbi_probe_handler; } void fbi_probe_uninit(struct us_ip *ip) diff --git a/nsp/nsp.c b/nsp/nsp.c index 3a0fc6f..07482fa 100644 --- a/nsp/nsp.c +++ b/nsp/nsp.c @@ -60,7 +60,7 @@ static int main_rh(struct uretprobe_instance *ri, struct pt_regs *regs); static struct probe_info_new pin_main = MAKE_URPROBE(main_eh, main_rh, 0); /* appcore_efl_main */ -static int ac_efl_main_h(struct kprobe *p, struct pt_regs *regs); +static int ac_efl_main_h(struct uprobe *p, struct pt_regs *regs); static struct probe_info_new pin_ac_efl_main = MAKE_UPROBE(ac_efl_main_h); static struct probe_new p_ac_efl_main = { .info = &pin_ac_efl_main @@ -74,7 +74,7 @@ static struct probe_new p_ac_init = { }; /* elm_run@plt */ -static int elm_run_h(struct kprobe *p, struct pt_regs *regs); +static int elm_run_h(struct uprobe *p, struct pt_regs *regs); static struct probe_info_new pin_elm_run = MAKE_UPROBE(elm_run_h); static struct probe_new p_elm_run = { .info = &pin_elm_run @@ -673,7 +673,7 @@ static void stage_end(enum nsp_proc_stat priv, enum nsp_proc_stat cur, } } -static int main_h(struct kprobe *p, struct pt_regs *regs) +static int main_h(struct uprobe *p, struct pt_regs *regs) { struct tdata *tdata; u64 time_start; @@ -708,7 +708,7 @@ static int main_eh(struct uretprobe_instance *ri, struct pt_regs *regs) struct uretprobe *rp = ri->rp; if (rp) { - main_h(&rp->up.kp, regs); + main_h(&rp->up, regs); if (get_quiet() == QT_OFF) { struct us_ip *ip; @@ -743,7 +743,7 @@ static int main_rh(struct uretprobe_instance *ri, struct pt_regs *regs) return 0; } -static int ac_efl_main_h(struct kprobe *p, struct pt_regs *regs) +static int ac_efl_main_h(struct uprobe *p, struct pt_regs *regs) { stage_end(NPS_MAIN_E, NPS_AC_EFL_MAIN_E, NMS_MAIN); return 0; @@ -755,7 +755,7 @@ static int ac_init_rh(struct uretprobe_instance *ri, struct pt_regs *regs) return 0; } -static int elm_run_h(struct kprobe *p, struct pt_regs *regs) +static int elm_run_h(struct uprobe *p, struct pt_regs *regs) { stage_end(NPS_AC_INIT_R, NPS_ELM_RUN_E, NMS_CREATE); return 0; diff --git a/preload/preload_module.c b/preload/preload_module.c index 87575f8..f7cb11e 100644 --- a/preload/preload_module.c +++ b/preload/preload_module.c @@ -140,7 +140,7 @@ static inline void __prepare_ujump(struct uretprobe_instance *ri, struct pt_regs *regs, unsigned long vaddr) { - ri->rp->up.kp.ss_addr[smp_processor_id()] = (kprobe_opcode_t *)vaddr; + ri->rp->up.ss_addr[smp_processor_id()] = (kprobe_opcode_t *)vaddr; #ifdef CONFIG_ARM if (thumb_mode(regs)) { @@ -201,7 +201,7 @@ static inline void print_regs(const char *prefix, struct pt_regs *regs, "sp(%08lx), lr(%08lx), pc(%08lx)\n", current->comm, current->tgid, current->pid, (int)preload_pd_get_state(__get_process_data(ri->rp)), - prefix, (unsigned long)ri->rp->up.kp.addr, + prefix, (unsigned long)ri->rp->up.addr, regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3, regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc); @@ -210,7 +210,7 @@ static inline void print_regs(const char *prefix, struct pt_regs *regs, "ip(%08lx), arg0(%08lx), arg1(%08lx), raddr(%08lx)\n", current->comm, current->tgid, current->pid, (int)preload_pd_get_state(__get_process_data(ri->rp)), - prefix, (unsigned long)ri->rp->up.kp.addr, + prefix, (unsigned long)ri->rp->up.addr, regs->EREG(ip), swap_get_arg(regs, 0), swap_get_arg(regs, 1), swap_get_ret_addr(regs)); #endif /* CONFIG_ARM */ @@ -715,7 +715,7 @@ static int preload_us_ret(struct uretprobe_instance *ri, struct pt_regs *regs) -static int get_caller_handler(struct kprobe *p, struct pt_regs *regs) +static int get_caller_handler(struct uprobe *p, struct pt_regs *regs) { unsigned long caller; int ret; @@ -732,7 +732,7 @@ static int get_caller_handler(struct kprobe *p, struct pt_regs *regs) return 0; } -static int get_call_type_handler(struct kprobe *p, struct pt_regs *regs) +static int get_call_type_handler(struct uprobe *p, struct pt_regs *regs) { unsigned char call_type; int ret; @@ -749,7 +749,7 @@ static int get_call_type_handler(struct kprobe *p, struct pt_regs *regs) return 0; } -static int write_msg_handler(struct kprobe *p, struct pt_regs *regs) +static int write_msg_handler(struct uprobe *p, struct pt_regs *regs) { char *user_buf; char *buf; @@ -819,7 +819,7 @@ int preload_module_get_caller_init(struct us_ip *ip) { struct uprobe *up = &ip->uprobe; - up->kp.pre_handler = get_caller_handler; + up->pre_handler = get_caller_handler; return 0; } @@ -832,7 +832,7 @@ int preload_module_get_call_type_init(struct us_ip *ip) { struct uprobe *up = &ip->uprobe; - up->kp.pre_handler = get_call_type_handler; + up->pre_handler = get_call_type_handler; return 0; } @@ -845,7 +845,7 @@ int preload_module_write_msg_init(struct us_ip *ip) { struct uprobe *up = &ip->uprobe; - up->kp.pre_handler = write_msg_handler; + up->pre_handler = write_msg_handler; return 0; } diff --git a/uprobe/arch/arm/swap-asm/swap_uprobes.c b/uprobe/arch/arm/swap-asm/swap_uprobes.c index af1ccf5..56a4a20 100644 --- a/uprobe/arch/arm/swap-asm/swap_uprobes.c +++ b/uprobe/arch/arm/swap-asm/swap_uprobes.c @@ -100,13 +100,12 @@ static int is_thumb2(kprobe_opcode_t insn) (insn & 0xf800) == 0xf800); } -static int arch_copy_trampoline_arm_uprobe(struct uprobe *up) +static int arch_copy_trampoline_arm_uprobe(struct uprobe *p) { int ret; - struct kprobe *p = up2kp(up); unsigned long insn = p->opcode; unsigned long vaddr = (unsigned long)p->addr; - unsigned long *tramp = up->atramp.tramp_arm; + unsigned long *tramp = p->atramp.tramp_arm; ret = arch_make_trampoline_arm(vaddr, insn, tramp); p->safe_arm = !!ret; @@ -394,20 +393,19 @@ static int prep_pc_dep_insn_execbuf_thumb(kprobe_opcode_t *insns, return 0; } -static int arch_copy_trampoline_thumb_uprobe(struct uprobe *up) +static int arch_copy_trampoline_thumb_uprobe(struct uprobe *p) { int uregs, pc_dep; - struct kprobe *p = up2kp(up); unsigned int addr; unsigned long vaddr = (unsigned long)p->addr; unsigned long insn = p->opcode; - unsigned long *tramp = up->atramp.tramp_thumb; - enum { tramp_len = sizeof(up->atramp.tramp_thumb) }; + unsigned long *tramp = p->atramp.tramp_thumb; + enum { tramp_len = sizeof(p->atramp.tramp_thumb) }; p->safe_thumb = 1; if (vaddr & 0x01) { printk(KERN_INFO "Error in %s at %d: attempt to register " - "kprobe at an unaligned address\n", __FILE__, __LINE__); + "uprobe at an unaligned address\n", __FILE__, __LINE__); return -EINVAL; } @@ -610,10 +608,9 @@ static int arch_copy_trampoline_thumb_uprobe(struct uprobe *up) * @return 0 on success,\n * negative error code on error. */ -int arch_prepare_uprobe(struct uprobe *up) +int arch_prepare_uprobe(struct uprobe *p) { - struct kprobe *p = up2kp(up); - struct task_struct *task = up->task; + struct task_struct *task = p->task; unsigned long vaddr = (unsigned long)p->addr; unsigned long insn; @@ -631,8 +628,8 @@ int arch_prepare_uprobe(struct uprobe *up) p->opcode = insn; - arch_copy_trampoline_arm_uprobe(up); - arch_copy_trampoline_thumb_uprobe(up); + arch_copy_trampoline_arm_uprobe(p); + arch_copy_trampoline_thumb_uprobe(p); if ((p->safe_arm) && (p->safe_thumb)) { printk(KERN_INFO "Error in %s at %d: failed " @@ -642,8 +639,8 @@ int arch_prepare_uprobe(struct uprobe *up) return -EFAULT; } - up->atramp.utramp = swap_slot_alloc(up->sm); - if (up->atramp.utramp == NULL) { + p->atramp.utramp = swap_slot_alloc(p->sm); + if (p->atramp.utramp == NULL) { printk(KERN_INFO "Error: swap_slot_alloc failed (%08lx)\n", vaddr); return -ENOMEM; @@ -661,13 +658,13 @@ int arch_prepare_uprobe(struct uprobe *up) void arch_opcode_analysis_uretprobe(struct uretprobe *rp) { /* Remove retprobe if first insn overwrites lr */ - rp->thumb_noret = !!(THUMB2_INSN_MATCH(BL, rp->up.kp.opcode) || - THUMB2_INSN_MATCH(BLX1, rp->up.kp.opcode) || - THUMB_INSN_MATCH(BLX2, rp->up.kp.opcode)); + rp->thumb_noret = !!(THUMB2_INSN_MATCH(BL, rp->up.opcode) || + THUMB2_INSN_MATCH(BLX1, rp->up.opcode) || + THUMB_INSN_MATCH(BLX2, rp->up.opcode)); - rp->arm_noret = !!(ARM_INSN_MATCH(BL, rp->up.kp.opcode) || - ARM_INSN_MATCH(BLX1, rp->up.kp.opcode) || - ARM_INSN_MATCH(BLX2, rp->up.kp.opcode)); + rp->arm_noret = !!(ARM_INSN_MATCH(BL, rp->up.opcode) || + ARM_INSN_MATCH(BLX1, rp->up.opcode) || + ARM_INSN_MATCH(BLX2, rp->up.opcode)); } /** @@ -686,12 +683,12 @@ int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs) ri->sp = (kprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs)); if (ri->preload_thumb) { - regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b; + regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b; } else { if (thumb_mode(regs)) - regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b; + regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b; else - regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn + + regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn + UPROBES_TRAMP_RET_BREAK_IDX); } @@ -721,9 +718,9 @@ int arch_disarm_urp_inst(struct uretprobe_instance *ri, /* Understand function mode */ if ((long)ri->sp & 1) { tramp = (unsigned long *) - ((unsigned long)ri->rp->up.kp.ainsn.insn + 0x1b); + ((unsigned long)ri->rp->up.ainsn.insn + 0x1b); } else { - tramp = (unsigned long *)(ri->rp->up.kp.ainsn.insn + + tramp = (unsigned long *)(ri->rp->up.ainsn.insn + UPROBES_TRAMP_RET_BREAK_IDX); } @@ -755,7 +752,7 @@ int arch_disarm_urp_inst(struct uretprobe_instance *ri, "%08lx (%08lx /%+d) - %p\n", task->comm, task->tgid, task->pid, (unsigned long)found, (unsigned long)sp, - found - sp, ri->rp->up.kp.addr); + found - sp, ri->rp->up.addr); retval = write_proc_vm_atomic(task, (unsigned long)found, &ri->ret_addr, sizeof(ri->ret_addr)); @@ -773,14 +770,14 @@ check_lr: /* check lr anyway */ printk(KERN_INFO "---> %s (%d/%d): trampoline found at " "lr = %08lx - %p\n", task->comm, task->tgid, task->pid, - ra, ri->rp->up.kp.addr); + ra, ri->rp->up.addr); swap_set_ret_addr(uregs, (unsigned long)ri->ret_addr); retval = 0; } else if (retval) { printk(KERN_INFO "---> %s (%d/%d): trampoline NOT found at " "sp = %08lx, lr = %08lx - %p\n", task->comm, task->tgid, task->pid, - (unsigned long)sp, ra, ri->rp->up.kp.addr); + (unsigned long)sp, ra, ri->rp->up.addr); } return retval; @@ -789,17 +786,16 @@ check_lr: /* check lr anyway */ /** * @brief Jump pre-handler. * - * @param p Pointer to the kprobe. + * @param p Pointer to the uprobe. * @param regs Pointer to CPU register data. * @return 0. */ -int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs) +int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs) { - struct uprobe *up = container_of(p, struct uprobe, kp); - struct ujprobe *jp = container_of(up, struct ujprobe, up); + struct ujprobe *jp = container_of(p, struct ujprobe, up); - kprobe_pre_entry_handler_t pre_entry = - (kprobe_pre_entry_handler_t)jp->pre_entry; + uprobe_pre_entry_handler_t pre_entry = + (uprobe_pre_entry_handler_t)jp->pre_entry; entry_point_t entry = (entry_point_t)jp->entry; if (pre_entry) { @@ -820,11 +816,11 @@ int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs) /** * @brief Gets trampoline address. * - * @param p Pointer to the kprobe. + * @param p Pointer to the uprobe. * @param regs Pointer to CPU register data. * @return Trampoline address. */ -unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs) +unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs) { return thumb_mode(regs) ? (unsigned long)(p->ainsn.insn) + 0x1b : @@ -861,7 +857,7 @@ void arch_remove_uprobe(struct uprobe *up) swap_slot_free(up->sm, up->atramp.utramp); } -static void restore_opcode_for_thumb(struct kprobe *p, struct pt_regs *regs) +static void restore_opcode_for_thumb(struct uprobe *p, struct pt_regs *regs) { if (thumb_mode(regs) && !is_thumb2(p->opcode)) { u16 tmp = p->opcode >> 16; @@ -871,10 +867,9 @@ static void restore_opcode_for_thumb(struct kprobe *p, struct pt_regs *regs) } } -static int make_trampoline(struct uprobe *up, struct pt_regs *regs) +static int make_trampoline(struct uprobe *p, struct pt_regs *regs) { unsigned long *tramp, *utramp; - struct kprobe *p = up2kp(up); int sw; /* @@ -890,13 +885,13 @@ static int make_trampoline(struct uprobe *up, struct pt_regs *regs) /* ARM */ case 0b110: case 0b010: - tramp = up->atramp.tramp_arm; + tramp = p->atramp.tramp_arm; break; /* THUMB */ case 0b111: case 0b101: restore_opcode_for_thumb(p, regs); - tramp = up->atramp.tramp_thumb; + tramp = p->atramp.tramp_thumb; break; default: printk(KERN_INFO "Error in %s at %d: we are in arm mode " @@ -904,14 +899,14 @@ static int make_trampoline(struct uprobe *up, struct pt_regs *regs) "(%0lX instruction at %p address)!\n", __FILE__, __LINE__, p->opcode, p->addr); - disarm_uprobe(p, up->task); + disarm_uprobe(p, p->task); return 1; } - utramp = up->atramp.utramp; + utramp = p->atramp.utramp; - if (!write_proc_vm_atomic(up->task, (unsigned long)utramp, tramp, + if (!write_proc_vm_atomic(p->task, (unsigned long)utramp, tramp, UPROBES_TRAMP_LEN * sizeof(*tramp))) { printk(KERN_ERR "failed to write memory %p!\n", utramp); return -EINVAL; @@ -923,21 +918,41 @@ static int make_trampoline(struct uprobe *up, struct pt_regs *regs) return 0; } +/** + * @brief Prepares singlestep for current CPU. + * + * @param p Pointer to uprobe. + * @param regs Pointer to CPU registers data. + * @return Void. + */ + +static void uprobe_prepare_singlestep(struct uprobe *p, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + if (p->ss_addr[cpu]) { + regs->ARM_pc = (unsigned long)p->ss_addr[cpu]; + p->ss_addr[cpu] = NULL; + } else { + regs->ARM_pc = (unsigned long)p->ainsn.insn; + } +} + static int uprobe_handler(struct pt_regs *regs) { kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->ARM_pc); struct task_struct *task = current; pid_t tgid = task->tgid; - struct kprobe *p; + struct uprobe *p; - p = get_ukprobe(addr, tgid); + p = get_uprobe(addr, tgid); if (p == NULL) { unsigned long offset_bp = thumb_mode(regs) ? 0x1a : 4 * UPROBES_TRAMP_RET_BREAK_IDX; void *tramp_addr = (void *)addr - offset_bp; - p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs); + p = get_uprobe_by_insn_slot(tramp_addr, tgid, regs); if (p == NULL) { printk(KERN_INFO "no_uprobe: Not one of ours: let " "kernel handle it %p\n", addr); @@ -947,9 +962,8 @@ static int uprobe_handler(struct pt_regs *regs) trampoline_uprobe_handler(p, regs); } else { if (p->ainsn.insn == NULL) { - struct uprobe *up = kp2up(p); - if (make_trampoline(up, regs)) { + if (make_trampoline(p, regs)) { printk(KERN_INFO "no_uprobe live\n"); return 0; } @@ -959,7 +973,7 @@ static int uprobe_handler(struct pt_regs *regs) } if (!p->pre_handler || !p->pre_handler(p, regs)) - prepare_singlestep(p, regs); + uprobe_prepare_singlestep(p, regs); } return 0; diff --git a/uprobe/arch/arm/swap-asm/swap_uprobes.h b/uprobe/arch/arm/swap-asm/swap_uprobes.h index 51342af..ee21d13 100644 --- a/uprobe/arch/arm/swap-asm/swap_uprobes.h +++ b/uprobe/arch/arm/swap-asm/swap_uprobes.h @@ -39,7 +39,6 @@ #include /* FIXME: for UPROBES_TRAMP_LEN */ -struct kprobe; struct task_struct; struct uprobe; struct uretprobe; @@ -73,8 +72,8 @@ static inline void arch_ujprobe_return(void) int arch_prepare_uprobe(struct uprobe *up); -int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs); -static inline int longjmp_break_uhandler(struct kprobe *p, struct pt_regs *regs) +int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs); +static inline int longjmp_break_uhandler(struct uprobe *p, struct pt_regs *regs) { return 0; } @@ -84,7 +83,7 @@ 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 arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs); +unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs); void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs); void arch_remove_uprobe(struct uprobe *up); diff --git a/uprobe/arch/x86/swap-asm/swap_uprobes.c b/uprobe/arch/x86/swap-asm/swap_uprobes.c index 84de6e4..0d6053a 100644 --- a/uprobe/arch/x86/swap-asm/swap_uprobes.c +++ b/uprobe/arch/x86/swap-asm/swap_uprobes.c @@ -45,12 +45,12 @@ */ struct uprobe_ctlblk { unsigned long flags; /**< Flags */ - struct kprobe *p; /**< Pointer to the uprobe's kprobe */ + struct uprobe *p; /**< Pointer to the uprobe */ }; static unsigned long trampoline_addr(struct uprobe *up) { - return (unsigned long)(up->kp.ainsn.insn + + return (unsigned long)(up->ainsn.insn + UPROBES_TRAMP_RET_BREAK_IDX); } @@ -60,12 +60,12 @@ static struct uprobe_ctlblk *current_ucb(void) return (struct uprobe_ctlblk *)(end_of_stack(current) + 20); } -static struct kprobe *get_current_probe(void) +static struct uprobe *get_current_probe(void) { return current_ucb()->p; } -static void set_current_probe(struct kprobe *p) +static void set_current_probe(struct uprobe *p) { current_ucb()->p = p; } @@ -88,11 +88,10 @@ static void restore_current_flags(struct pt_regs *regs, unsigned long flags) * @return 0 on success,\n * -1 on error. */ -int arch_prepare_uprobe(struct uprobe *up) +int arch_prepare_uprobe(struct uprobe *p) { - struct kprobe *p = up2kp(up); - struct task_struct *task = up->task; - u8 *tramp = up->atramp.tramp; + struct task_struct *task = p->task; + u8 *tramp = p->atramp.tramp; enum { call_relative_opcode = 0xe8 }; if (!read_proc_vm_atomic(task, (unsigned long)p->addr, @@ -113,15 +112,15 @@ int arch_prepare_uprobe(struct uprobe *up) p->ainsn.boostable = swap_can_boost(tramp) ? 0 : -1; - p->ainsn.insn = swap_slot_alloc(up->sm); + p->ainsn.insn = swap_slot_alloc(p->sm); if (p->ainsn.insn == NULL) { printk(KERN_ERR "trampoline out of memory\n"); return -ENOMEM; } if (!write_proc_vm_atomic(task, (unsigned long)p->ainsn.insn, - tramp, sizeof(up->atramp.tramp))) { - swap_slot_free(up->sm, p->ainsn.insn); + tramp, sizeof(p->atramp.tramp))) { + swap_slot_free(p->sm, p->ainsn.insn); printk(KERN_INFO "failed to write memory %p!\n", tramp); return -EINVAL; } @@ -135,16 +134,15 @@ int arch_prepare_uprobe(struct uprobe *up) /** * @brief Jump pre-handler. * - * @param p Pointer to the uprobe's kprobe. + * @param p Pointer to the uprobe. * @param regs Pointer to CPU register data. * @return 0. */ -int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs) +int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs) { - struct uprobe *up = container_of(p, struct uprobe, kp); - struct ujprobe *jp = container_of(up, struct ujprobe, up); - kprobe_pre_entry_handler_t pre_entry = - (kprobe_pre_entry_handler_t)jp->pre_entry; + struct ujprobe *jp = container_of(p, struct ujprobe, up); + uprobe_pre_entry_handler_t pre_entry = + (uprobe_pre_entry_handler_t)jp->pre_entry; entry_point_t entry = (entry_point_t)jp->entry; unsigned long args[6]; @@ -189,7 +187,7 @@ int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs) 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); + regs->EREG(sp), ri->rp->up.addr); return -EINVAL; } @@ -245,13 +243,13 @@ int arch_disarm_urp_inst(struct uretprobe_instance *ri, /** * @brief Gets trampoline address. * - * @param p Pointer to the uprobe's kprobe. + * @param p Pointer to the uprobe. * @param regs Pointer to CPU register data. * @return Trampoline address. */ -unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs) +unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs) { - return trampoline_addr(kp2up(p)); + return trampoline_addr(p); } /** @@ -272,11 +270,9 @@ void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs) * @param up Pointer to the target uprobe. * @return Void. */ -void arch_remove_uprobe(struct uprobe *up) +void arch_remove_uprobe(struct uprobe *p) { - struct kprobe *p = up2kp(up); - - swap_slot_free(up->sm, p->ainsn.insn); + swap_slot_free(p->sm, p->ainsn.insn); } static void set_user_jmp_op(void *from, void *to) @@ -295,7 +291,7 @@ static void set_user_jmp_op(void *from, void *to) "failed to write jump opcode to user space %p\n", from); } -static void resume_execution(struct kprobe *p, +static void resume_execution(struct uprobe *p, struct pt_regs *regs, unsigned long flags) { @@ -420,7 +416,7 @@ no_change: return; } -static bool prepare_ss_addr(struct kprobe *p, struct pt_regs *regs) +static bool prepare_ss_addr(struct uprobe *p, struct pt_regs *regs) { unsigned long *ss_addr = (long *)&p->ss_addr[smp_processor_id()]; @@ -441,9 +437,35 @@ static void prepare_ss(struct pt_regs *regs) regs->flags &= ~IF_MASK; } +/** + * @brief Prepares singlestep for current CPU. + * + * @param p Pointer to uprobe. + * @param regs Pointer to CPU registers data. + * @return Void. + */ +static void uprobe_prepare_singlestep(struct uprobe *p, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + if (p->ss_addr[cpu]) { + regs->EREG(ip) = (unsigned long)p->ss_addr[cpu]; + p->ss_addr[cpu] = NULL; + } else { + regs->EREG(flags) |= TF_MASK; + regs->EREG(flags) &= ~IF_MASK; + /* single step inline if the instruction is an int3 */ + if (p->opcode == BREAKPOINT_INSTRUCTION) { + regs->EREG(ip) = (unsigned long) p->addr; + /* printk(KERN_INFO "break_insn!!!\n"); */ + } else + regs->EREG(ip) = (unsigned long) p->ainsn.insn; + } +} + static int uprobe_handler(struct pt_regs *regs) { - struct kprobe *p; + struct uprobe *p; kprobe_opcode_t *addr; struct task_struct *task = current; pid_t tgid = task->tgid; @@ -451,12 +473,12 @@ static int uprobe_handler(struct pt_regs *regs) save_current_flags(regs); addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t)); - p = get_ukprobe(addr, tgid); + p = get_uprobe(addr, tgid); if (p == NULL) { void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX; - p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs); + p = get_uprobe_by_insn_slot(tramp_addr, tgid, regs); if (p == NULL) { printk(KERN_INFO "no_uprobe\n"); return 0; @@ -475,6 +497,8 @@ static int uprobe_handler(struct pt_regs *regs) set_current_probe(p); prepare_ss(regs); } + + uprobe_prepare_singlestep(p, regs); } } @@ -483,7 +507,7 @@ static int uprobe_handler(struct pt_regs *regs) static int post_uprobe_handler(struct pt_regs *regs) { - struct kprobe *p = get_current_probe(); + struct uprobe *p = get_current_probe(); unsigned long flags = current_ucb()->flags; if (p == NULL) { diff --git a/uprobe/arch/x86/swap-asm/swap_uprobes.h b/uprobe/arch/x86/swap-asm/swap_uprobes.h index faef033..038f65c 100644 --- a/uprobe/arch/x86/swap-asm/swap_uprobes.h +++ b/uprobe/arch/x86/swap-asm/swap_uprobes.h @@ -73,8 +73,8 @@ static inline void arch_ujprobe_return(void) } int arch_prepare_uprobe(struct uprobe *up); -int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs); -static inline int longjmp_break_uhandler(struct kprobe *p, struct pt_regs *regs) +int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs); +static inline int longjmp_break_uhandler(struct uprobe *p, struct pt_regs *regs) { return 0; } @@ -87,7 +87,7 @@ static inline int arch_opcode_analysis_uretprobe(struct uretprobe *rp) 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 arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs); +unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs); void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs); void arch_remove_uprobe(struct uprobe *up); diff --git a/uprobe/swap_uprobes.c b/uprobe/swap_uprobes.c index 82e64c8..2f6d3c3 100644 --- a/uprobe/swap_uprobes.c +++ b/uprobe/swap_uprobes.c @@ -64,15 +64,15 @@ void print_uprobe_hash_table(void) { int i; struct hlist_head *head; - struct kprobe *p; + struct uprobe *p; DECLARE_NODE_PTR_FOR_HLIST(node); /* print uprobe table */ for (i = 0; i < UPROBE_TABLE_SIZE; ++i) { head = &uprobe_insn_slot_table[i]; - swap_hlist_for_each_entry_rcu(p, node, head, is_hlist_arm) { - printk(KERN_INFO "####### find U tgid=%u, addr=%x\n", - p->tgid, p->addr); + swap_hlist_for_each_entry_rcu(p, node, head, is_hlist) { + printk(KERN_INFO "####### find U tgid=%u, addr=0x%lx\n", + p->task->tgid, (unsigned long)p->addr); } } } @@ -81,7 +81,7 @@ void print_uprobe_hash_table(void) /* * Keep all fields in the uprobe consistent */ -static inline void copy_uprobe(struct kprobe *old_p, struct kprobe *p) +static inline void copy_uprobe(struct uprobe *old_p, struct uprobe *p) { memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t)); memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn)); @@ -95,14 +95,14 @@ static inline void copy_uprobe(struct kprobe *old_p, struct kprobe *p) * Aggregate handlers for multiple uprobes support - these handlers * take care of invoking the individual uprobe handlers on p->list */ -static int aggr_pre_uhandler(struct kprobe *p, struct pt_regs *regs) +static int aggr_pre_uhandler(struct uprobe *p, struct pt_regs *regs) { - struct kprobe *kp; + struct uprobe *up; int ret; - list_for_each_entry_rcu(kp, &p->list, list) { - if (kp->pre_handler) { - ret = kp->pre_handler(kp, regs); + list_for_each_entry_rcu(up, &p->list, list) { + if (up->pre_handler) { + ret = up->pre_handler(up, regs); if (ret) return ret; } @@ -111,25 +111,25 @@ static int aggr_pre_uhandler(struct kprobe *p, struct pt_regs *regs) return 0; } -static void aggr_post_uhandler(struct kprobe *p, struct pt_regs *regs, +static void aggr_post_uhandler(struct uprobe *p, struct pt_regs *regs, unsigned long flags) { - struct kprobe *kp; + struct uprobe *up; - list_for_each_entry_rcu(kp, &p->list, list) { - if (kp->post_handler) - kp->post_handler(kp, regs, flags); + list_for_each_entry_rcu(up, &p->list, list) { + if (up->post_handler) + up->post_handler(up, regs, flags); } } -static int aggr_fault_uhandler(struct kprobe *p, +static int aggr_fault_uhandler(struct uprobe *p, struct pt_regs *regs, int trapnr) { return 0; } -static int aggr_break_uhandler(struct kprobe *p, struct pt_regs *regs) +static int aggr_break_uhandler(struct uprobe *p, struct pt_regs *regs) { return 0; } @@ -138,7 +138,7 @@ static int aggr_break_uhandler(struct kprobe *p, struct pt_regs *regs) * Add the new probe to old_p->list. Fail if this is the * second ujprobe at the address - two ujprobes can't coexist */ -static int add_new_uprobe(struct kprobe *old_p, struct kprobe *p) +static int add_new_uprobe(struct uprobe *old_p, struct uprobe *p) { if (p->break_handler) { if (old_p->break_handler) @@ -160,7 +160,7 @@ static int add_new_uprobe(struct kprobe *old_p, struct kprobe *p) * Fill in the required fields of the "manager uprobe". Replace the * earlier uprobe in the hlist with the manager uprobe */ -static inline void add_aggr_uprobe(struct kprobe *ap, struct kprobe *p) +static inline void add_aggr_uprobe(struct uprobe *ap, struct uprobe *p) { copy_uprobe(p, ap); @@ -184,10 +184,9 @@ static inline void add_aggr_uprobe(struct kprobe *ap, struct kprobe *p) * This is the second or subsequent uprobe at the address - handle * the intricacies */ -static int register_aggr_uprobe(struct kprobe *old_p, struct kprobe *p) +static int register_aggr_uprobe(struct uprobe *old_p, struct uprobe *p) { int ret = 0; - struct kprobe *ap; if (old_p->pre_handler == aggr_pre_uhandler) { copy_uprobe(old_p, p); @@ -197,11 +196,10 @@ static int register_aggr_uprobe(struct kprobe *old_p, struct kprobe *p) if (!uap) return -ENOMEM; - uap->task = kp2up(p)->task; - ap = up2kp(uap); - add_aggr_uprobe(ap, old_p); - copy_uprobe(ap, p); - ret = add_new_uprobe(ap, p); + uap->task = p->task; + add_aggr_uprobe(uap, old_p); + copy_uprobe(uap, p); + ret = add_new_uprobe(uap, p); } return ret; @@ -210,11 +208,11 @@ static int register_aggr_uprobe(struct kprobe *old_p, struct kprobe *p) static int arm_uprobe(struct uprobe *p) { kprobe_opcode_t insn = BREAKPOINT_INSTRUCTION; - int ret = write_proc_vm_atomic(p->task, (unsigned long)p->kp.addr, + int ret = write_proc_vm_atomic(p->task, (unsigned long)p->addr, &insn, sizeof(insn)); if (!ret) { printk("arm_uprobe: failed to write memory " - "tgid=%u addr=%p!\n", p->task->tgid, p->kp.addr); + "tgid=%u addr=%p!\n", p->task->tgid, p->addr); return -EACCES; } @@ -225,11 +223,11 @@ static int arm_uprobe(struct uprobe *p) /** * @brief Disarms uprobe. * - * @param p Pointer to the uprobe's kprobe. + * @param p Pointer to the uprobe. * @param task Pointer to the target task. * @return Void. */ -void disarm_uprobe(struct kprobe *p, struct task_struct *task) +void disarm_uprobe(struct uprobe *p, struct task_struct *task) { int ret = write_proc_vm_atomic(task, (unsigned long)p->addr, &p->opcode, sizeof(p->opcode)); @@ -262,22 +260,22 @@ static void init_uretprobe_inst_table(void) } /** - * @brief Gets uprobe's kprobe. + * @brief Gets uprobe. * * @param addr Probe's address. * @param tgid Probes's thread group ID. - * @return Pointer to the kprobe on success,\n + * @return Pointer to the uprobe on success,\n * NULL otherwise. */ -struct kprobe *get_ukprobe(void *addr, pid_t tgid) +struct uprobe *get_uprobe(void *addr, pid_t tgid) { struct hlist_head *head; - struct kprobe *p; + struct uprobe *p; DECLARE_NODE_PTR_FOR_HLIST(node); head = &uprobe_table[hash_ptr(addr, UPROBE_HASH_BITS)]; swap_hlist_for_each_entry_rcu(p, node, head, hlist) { - if (p->addr == addr && kp2up(p)->task->tgid == tgid) + if (p->addr == addr && p->task->tgid == tgid) return p; } @@ -287,10 +285,10 @@ struct kprobe *get_ukprobe(void *addr, pid_t tgid) /** * @brief Adds uprobe to hlist when trampoline have been made. * - * @param p Pointer to the uprobe's kprobe. + * @param p Pointer to the uprobe. * @return Void. */ -void add_uprobe_table(struct kprobe *p) +void add_uprobe_table(struct uprobe *p) { write_lock(&st_lock); hlist_add_head(&p->is_hlist, @@ -298,7 +296,7 @@ void add_uprobe_table(struct kprobe *p) write_unlock(&st_lock); } -static void del_uprobe_table(struct kprobe *p) +static void del_uprobe_table(struct uprobe *p) { write_lock(&st_lock); if (!hlist_unhashed(&p->is_hlist)) @@ -307,26 +305,26 @@ static void del_uprobe_table(struct kprobe *p) } /** - * @brief Gets kprobe by insn slot. + * @brief Gets uprobe by insn slot. * * @param addr Probe's address. * @param tgit Probe's thread group ID. * @param regs Pointer to CPU registers data. - * @return Pointer to the kprobe on success,\n + * @return Pointer to the uprobe on success,\n * NULL otherwise. */ -struct kprobe *get_ukprobe_by_insn_slot(void *addr, - pid_t tgid, - struct pt_regs *regs) +struct uprobe *get_uprobe_by_insn_slot(void *addr, + pid_t tgid, + struct pt_regs *regs) { struct hlist_head *head; - struct kprobe *p; + struct uprobe *p; DECLARE_NODE_PTR_FOR_HLIST(node); read_lock(&st_lock); head = &slot_table[hash_ptr(addr, UPROBE_HASH_BITS)]; swap_hlist_for_each_entry(p, node, head, is_hlist) { - if (p->ainsn.insn == addr && kp2up(p)->task->tgid == tgid) { + if (p->ainsn.insn == addr && p->task->tgid == tgid) { read_unlock(&st_lock); return p; } @@ -339,7 +337,7 @@ struct kprobe *get_ukprobe_by_insn_slot(void *addr, static void remove_uprobe(struct uprobe *up) { - del_uprobe_table(&up->kp); + del_uprobe_table(up); arch_remove_uprobe(up); } @@ -478,12 +476,11 @@ static struct uretprobe_instance *get_free_urp_inst(struct uretprobe *rp) * @return 0 on success,\n * negative error code on error. */ -int swap_register_uprobe(struct uprobe *up) +int swap_register_uprobe(struct uprobe *p) { int ret = 0; - struct kprobe *p, *old_p; + struct uprobe *old_p; - p = &up->kp; if (!p->addr) return -EINVAL; @@ -498,8 +495,6 @@ int swap_register_uprobe(struct uprobe *up) #endif p->ainsn.insn = NULL; - p->mod_refcounted = 0; - p->nmissed = 0; INIT_LIST_HEAD(&p->list); #ifdef KPROBES_PROFILE p->start_tm.tv_sec = p->start_tm.tv_usec = 0; @@ -508,9 +503,9 @@ int swap_register_uprobe(struct uprobe *up) #endif /* get the first item */ - old_p = get_ukprobe(p->addr, kp2up(p)->task->tgid); + old_p = get_uprobe(p->addr, p->task->tgid); if (old_p) { - struct task_struct *task = up->task; + struct task_struct *task = p->task; /* TODO: add support many uprobes on address */ printk(KERN_INFO "uprobe on task[%u %u %s] vaddr=%p is there\n", @@ -528,7 +523,7 @@ int swap_register_uprobe(struct uprobe *up) INIT_HLIST_NODE(&p->is_hlist); - ret = arch_prepare_uprobe(up); + ret = arch_prepare_uprobe(p); if (ret) { DBPRINTF("goto out\n", ret); goto out; @@ -541,11 +536,11 @@ int swap_register_uprobe(struct uprobe *up) hlist_add_head_rcu(&p->hlist, &uprobe_table[hash_ptr(p->addr, UPROBE_HASH_BITS)]); - ret = arm_uprobe(up); + ret = arm_uprobe(p); if (ret) { hlist_del_rcu(&p->hlist); synchronize_rcu(); - remove_uprobe(up); + remove_uprobe(p); } out: @@ -561,13 +556,12 @@ EXPORT_SYMBOL_GPL(swap_register_uprobe); * @param disarm Disarm flag. When true uprobe is disarmed. * @return Void. */ -void __swap_unregister_uprobe(struct uprobe *up, int disarm) +void __swap_unregister_uprobe(struct uprobe *p, int disarm) { - struct kprobe *p, *old_p, *list_p; + struct uprobe *old_p, *list_p; int cleanup_p; - p = &up->kp; - old_p = get_ukprobe(p->addr, kp2up(p)->task->tgid); + old_p = get_uprobe(p->addr, p->task->tgid); if (unlikely(!old_p)) return; @@ -587,7 +581,7 @@ valid_p: (p->list.next == &old_p->list) && (p->list.prev == &old_p->list))) { /* Only probe on the hash list */ if (disarm) - disarm_uprobe(&up->kp, up->task); + disarm_uprobe(p, p->task); hlist_del_rcu(&old_p->hlist); cleanup_p = 1; @@ -605,7 +599,7 @@ valid_p: if (!in_atomic()) synchronize_sched(); - remove_uprobe(up); + remove_uprobe(p); } else { if (p->break_handler) old_p->break_handler = NULL; @@ -649,8 +643,8 @@ int swap_register_ujprobe(struct ujprobe *jp) int ret = 0; /* Todo: Verify probepoint is a function entry point */ - jp->up.kp.pre_handler = setjmp_upre_handler; - jp->up.kp.break_handler = longjmp_break_uhandler; + jp->up.pre_handler = setjmp_upre_handler; + jp->up.break_handler = longjmp_break_uhandler; ret = swap_register_uprobe(&jp->up); @@ -687,14 +681,14 @@ EXPORT_SYMBOL_GPL(swap_unregister_ujprobe); /** * @brief Trampoline uprobe handler. * - * @param p Pointer to the uprobe's kprobe. + * @param p Pointer to the uprobe. * @param regs Pointer to CPU register data. * @return 1 */ -int trampoline_uprobe_handler(struct kprobe *p, struct pt_regs *regs) +int trampoline_uprobe_handler(struct uprobe *p, struct pt_regs *regs) { struct uretprobe_instance *ri = NULL; - struct kprobe *kp; + struct uprobe *up; struct hlist_head *head; unsigned long flags, tramp_addr, orig_ret_addr = 0; struct hlist_node *tmp; @@ -724,9 +718,9 @@ int trampoline_uprobe_handler(struct kprobe *p, struct pt_regs *regs) continue; } - kp = NULL; + up = NULL; if (ri->rp) { - kp = up2kp(&ri->rp->up); + up = &ri->rp->up; if (ri->rp->handler) ri->rp->handler(ri, regs); @@ -735,7 +729,7 @@ int trampoline_uprobe_handler(struct kprobe *p, struct pt_regs *regs) orig_ret_addr = (unsigned long)ri->ret_addr; recycle_urp_inst(ri); - if ((orig_ret_addr != tramp_addr && kp == p) || kp == NULL) { + if ((orig_ret_addr != tramp_addr && up == p) || up == NULL) { /* * This is the real return address. Any other * instances associated with this task are for @@ -754,10 +748,9 @@ int trampoline_uprobe_handler(struct kprobe *p, struct pt_regs *regs) return 1; } -static int pre_handler_uretprobe(struct kprobe *p, struct pt_regs *regs) +static int pre_handler_uretprobe(struct uprobe *p, struct pt_regs *regs) { - struct uprobe *up = container_of(p, struct uprobe, kp); - struct uretprobe *rp = container_of(up, struct uretprobe, up); + struct uretprobe *rp = container_of(p, struct uretprobe, up); #ifdef CONFIG_ARM int noret = thumb_mode(regs) ? rp->thumb_noret : rp->arm_noret; #endif @@ -816,10 +809,10 @@ int swap_register_uretprobe(struct uretprobe *rp) DBPRINTF("START\n"); - rp->up.kp.pre_handler = pre_handler_uretprobe; - rp->up.kp.post_handler = NULL; - rp->up.kp.fault_handler = NULL; - rp->up.kp.break_handler = NULL; + rp->up.pre_handler = pre_handler_uretprobe; + rp->up.post_handler = NULL; + rp->up.fault_handler = NULL; + rp->up.break_handler = NULL; /* Pre-allocate memory for max kretprobe instances */ if (rp->maxactive <= 0) { @@ -908,7 +901,7 @@ void swap_discard_pending_uretprobes(struct task_struct *task) if (ri->task == task) { printk(KERN_INFO "%s (%d/%d): pending urp inst: %08lx\n", task->comm, task->tgid, task->pid, - (unsigned long)ri->rp->up.kp.addr); + (unsigned long)ri->rp->up.addr); arch_disarm_urp_inst(ri, task); recycle_urp_inst(ri); } @@ -938,7 +931,7 @@ void __swap_unregister_uretprobe(struct uretprobe *rp, int disarm) printk(KERN_INFO "%s (%d/%d): " "cannot disarm urp instance (%08lx)\n", ri->task->comm, ri->task->tgid, ri->task->pid, - (unsigned long)rp->up.kp.addr); + (unsigned long)rp->up.addr); recycle_urp_inst(ri); } @@ -974,7 +967,7 @@ EXPORT_SYMBOL_GPL(swap_unregister_uretprobe); void swap_unregister_all_uprobes(struct task_struct *task) { struct hlist_head *head; - struct kprobe *p; + struct uprobe *p; int i; struct hlist_node *tnode; DECLARE_NODE_PTR_FOR_HLIST(node); @@ -982,14 +975,12 @@ void swap_unregister_all_uprobes(struct task_struct *task) for (i = 0; i < UPROBE_TABLE_SIZE; ++i) { head = &uprobe_table[i]; swap_hlist_for_each_entry_safe(p, node, tnode, head, hlist) { - if (kp2up(p)->task->tgid == task->tgid) { - struct uprobe *up = - container_of(p, struct uprobe, kp); + if (p->task->tgid == task->tgid) { printk(KERN_INFO "%s: delete uprobe at %p[%lx]" " for %s/%d\n", __func__, p->addr, (unsigned long)p->opcode, task->comm, task->pid); - swap_unregister_uprobe(up); + swap_unregister_uprobe(p); } } } diff --git a/uprobe/swap_uprobes.h b/uprobe/swap_uprobes.h index 1e3a9fd..9578cf8 100644 --- a/uprobe/swap_uprobes.h +++ b/uprobe/swap_uprobes.h @@ -38,16 +38,71 @@ #include +/** + * @brief Uprobe pre-handler pointer. + */ +typedef int (*uprobe_pre_handler_t) (struct uprobe *, struct pt_regs *); + +/** + * @brief Uprobe break handler pointer. + */ +typedef int (*uprobe_break_handler_t) (struct uprobe *, struct pt_regs *); + +/** + * @brief Uprobe post handler pointer. + */ +typedef void (*uprobe_post_handler_t) (struct uprobe *, + struct pt_regs *, + unsigned long flags); + +/** + * @brief Uprobe fault handler pointer. + */ +typedef int (*uprobe_fault_handler_t) (struct uprobe *, + struct pt_regs *, + int trapnr); /** * @struct uprobe - * @brief Stores uprobe data, based on kprobe. + * @brief Stores uprobe data. */ struct uprobe { - struct kprobe kp; /**< Kprobe for this uprobe */ - struct task_struct *task; /**< Pointer to the task struct */ - struct slot_manager *sm; /**< Pointer to slot manager */ - struct arch_specific_tramp atramp; /**< Stores trampoline */ + struct hlist_node hlist; /**< Hash list.*/ + /** List of probes to search by instruction slot.*/ + struct hlist_node is_hlist; + /** List of uprobes for multi-handler support.*/ + struct list_head list; + /** Location of the probe point. */ + kprobe_opcode_t *addr; + /** Called before addr is executed.*/ + uprobe_pre_handler_t pre_handler; + /** Called after addr is executed, unless...*/ + uprobe_post_handler_t post_handler; + /** ... called if executing addr causes a fault (eg. page fault).*/ + uprobe_fault_handler_t fault_handler; + /** Return 1 if it handled fault, otherwise kernel will see it.*/ + uprobe_break_handler_t break_handler; + /** Saved opcode (which has been replaced with breakpoint).*/ + kprobe_opcode_t opcode; + /** Copy of the original instruction.*/ + struct arch_specific_insn ainsn; + /** Override single-step target address, may be used to redirect + * control-flow to arbitrary address after probe point without + * invocation of original instruction; useful for functions + * replacement. If jprobe.entry should return address of function or + * NULL if original function should be called. + * Not supported for X86, not tested for MIPS. */ + kprobe_opcode_t *ss_addr[NR_CPUS]; +#ifdef CONFIG_ARM + /** Safe/unsafe to use probe on ARM.*/ + unsigned safe_arm:1; + /** Safe/unsafe to use probe on Thumb.*/ + unsigned safe_thumb:1; +#endif + + struct task_struct *task; /**< Pointer to the task struct */ + struct slot_manager *sm; /**< Pointer to slot manager */ + struct arch_specific_tramp atramp; /**< Stores trampoline */ }; /** @@ -143,25 +198,15 @@ void swap_unregister_all_uprobes(struct task_struct *task); void swap_discard_pending_uretprobes(struct task_struct *task); void swap_ujprobe_return(void); -struct kprobe *get_ukprobe(void *addr, pid_t tgid); -struct kprobe *get_ukprobe_by_insn_slot(void *addr, +struct uprobe *get_uprobe(void *addr, pid_t tgid); +struct uprobe *get_uprobe_by_insn_slot(void *addr, pid_t tgid, struct pt_regs *regs); -static inline struct uprobe *kp2up(struct kprobe *p) -{ - return container_of(p, struct uprobe, kp); -} - -static inline struct kprobe *up2kp(struct uprobe *p) -{ - return &p->kp; -} - -void disarm_uprobe(struct kprobe *p, struct task_struct *task); +void disarm_uprobe(struct uprobe *p, struct task_struct *task); -int trampoline_uprobe_handler(struct kprobe *p, struct pt_regs *regs); +int trampoline_uprobe_handler(struct uprobe *p, struct pt_regs *regs); -void add_uprobe_table(struct kprobe *p); +void add_uprobe_table(struct uprobe *p); #endif /* _SWAP_UPROBES_H */ diff --git a/us_manager/probes/probe_info_new.c b/us_manager/probes/probe_info_new.c index 5c764e8..22c49b0 100644 --- a/us_manager/probes/probe_info_new.c +++ b/us_manager/probes/probe_info_new.c @@ -65,10 +65,9 @@ static int urp_ret_handler(struct uretprobe_instance *ri, struct pt_regs *regs) return 0; } -static int uprobe_handler(struct kprobe *p, struct pt_regs *regs) +static int uprobe_handler(struct uprobe *p, struct pt_regs *regs) { - struct uprobe *up = container_of(p, struct uprobe, kp); - struct us_ip *ip = container_of(up, struct us_ip, uprobe); + struct us_ip *ip = container_of(p, struct us_ip, uprobe); struct probe_info_new *info_new; info_new = probe_info_get_val(ip->info, struct probe_info_new *); @@ -178,7 +177,7 @@ static void up_unregister_probe(struct us_ip *ip, int disarm) static void up_init(struct us_ip *ip) { - ip->uprobe.kp.pre_handler = uprobe_handler; + ip->uprobe.pre_handler = uprobe_handler; } static void up_uninit(struct us_ip *ip) diff --git a/us_manager/probes/probe_info_new.h b/us_manager/probes/probe_info_new.h index 62ddaec..b176522 100644 --- a/us_manager/probes/probe_info_new.h +++ b/us_manager/probes/probe_info_new.h @@ -36,7 +36,7 @@ struct probe_info_new { enum probe_t type; union { struct { - kprobe_pre_handler_t handler; + uprobe_pre_handler_t handler; } p; struct { diff --git a/us_manager/sspt/sspt.h b/us_manager/sspt/sspt.h index 3199ae7..cd54010 100644 --- a/us_manager/sspt/sspt.h +++ b/us_manager/sspt/sspt.h @@ -58,7 +58,7 @@ static inline int sspt_register_usprobe(struct us_ip *ip) return -EINVAL; } - up->kp.addr = (kprobe_opcode_t *)ip->orig_addr; + up->addr = (kprobe_opcode_t *)ip->orig_addr; up->task = ip->page->file->proc->task; up->sm = ip->page->file->proc->sm; @@ -66,12 +66,12 @@ static inline int sspt_register_usprobe(struct us_ip *ip) if (ret) { struct sspt_file *file = ip->page->file; char *name = file->dentry->d_iname; - unsigned long addr = (unsigned long)up->kp.addr; + unsigned long addr = (unsigned long)up->addr; unsigned long offset = addr - file->vm_start; printk(KERN_INFO "swap_register_uretprobe() failure %d " "(%s:%lx|%lx)\n", ret, name, offset, - (unsigned long)ip->retprobe.up.kp.opcode); + (unsigned long)ip->retprobe.up.opcode); } return ret; @@ -89,7 +89,7 @@ static inline int sspt_unregister_usprobe(struct task_struct *task, break; case US_DISARM: up = probe_info_get_uprobe(ip->info, ip); - disarm_uprobe(&up->kp, task); + disarm_uprobe(up, task); break; case US_UNINSTALL: probe_info_unregister(ip->info, ip, 0); diff --git a/us_manager/sspt/sspt_debug.h b/us_manager/sspt/sspt_debug.h index 0b3dc79..7d7e212 100644 --- a/us_manager/sspt/sspt_debug.h +++ b/us_manager/sspt/sspt_debug.h @@ -47,7 +47,7 @@ static inline void print_ip(struct us_ip *ip, int i) printk(KERN_INFO "### addr[%2d]=%lx, R_addr=%lx\n", i, (unsigned long)ip->offset, - (unsigned long)rp->up.kp.addr); + (unsigned long)rp->up.addr); print_retprobe(rp); } } diff --git a/wsp/wsp.c b/wsp/wsp.c index ccfa7d5..8f40a17 100644 --- a/wsp/wsp.c +++ b/wsp/wsp.c @@ -83,7 +83,7 @@ static void do_res_finish(struct wsp_res *res) /* * soup_req */ -static int soup_req_handle(struct kprobe *p, struct pt_regs *regs) +static int soup_req_handle(struct uprobe *p, struct pt_regs *regs) { enum { max_str_len = 512 }; const char __user *user_s; @@ -116,7 +116,7 @@ static struct probe_info_new soup_req = MAKE_UPROBE(soup_req_handle); /* * main_res_req */ -static int mres_req_handle(struct kprobe *p, struct pt_regs *regs) +static int mres_req_handle(struct uprobe *p, struct pt_regs *regs) { void *ptr = (void *)swap_get_uarg(regs, 0); struct wsp_res *res; @@ -162,7 +162,7 @@ static struct probe_info_new mres_adata = /* * main_res_finish */ -static int mres_finish_handle(struct kprobe *p, struct pt_regs *regs) +static int mres_finish_handle(struct uprobe *p, struct pt_regs *regs) { void *ptr = (void *)swap_get_uarg(regs, 0); struct wsp_res *res; @@ -182,7 +182,7 @@ static struct probe_info_new mres_finish = MAKE_UPROBE(mres_finish_handle); /* * res_request */ -static int res_request_handle(struct kprobe *p, struct pt_regs *regs) +static int res_request_handle(struct uprobe *p, struct pt_regs *regs) { void *ptr = (void *)swap_get_uarg(regs, 0); struct wsp_res *res; -- 2.7.4