2 * uprobe/arch/asm-x86/swap_uprobes.c
3 * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial
4 * implementation; Support x86/ARM/MIPS for both user and kernel spaces.
5 * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for
6 * separating core and arch parts
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * Copyright (C) Samsung Electronics, 2006-2010
28 * @section DESCRIPTION
30 * Arch-dependent uprobe interface implementation for x86.
34 #include <linux/kdebug.h>
36 #include <kprobe/swap_slots.h>
37 #include <kprobe/swap_td_raw.h>
38 #include <uprobe/swap_uprobes.h>
40 #include "swap_uprobes.h"
44 struct pt_regs save_regs;
45 struct pt_regs *ptr_regs;
47 int (*handler)(struct uprobe *, struct pt_regs *);
51 * @struct uprobe_ctlblk
52 * @brief Uprobe control block
54 struct uprobe_ctlblk {
55 unsigned long flags; /**< Flags */
56 struct uprobe *p; /**< Pointer to the uprobe */
58 struct save_context ctx;
62 static struct td_raw td_raw;
65 static unsigned long trampoline_addr(struct uprobe *up)
67 return (unsigned long)(up->ainsn.insn +
68 UPROBES_TRAMP_RET_BREAK_IDX);
71 unsigned long arch_tramp_by_ri(struct uretprobe_instance *ri)
73 return trampoline_addr(&ri->rp->up);
76 static struct uprobe_ctlblk *current_ucb(void)
78 return (struct uprobe_ctlblk *)swap_td_raw(&td_raw, current);
81 static struct save_context *current_ctx(void)
83 return ¤t_ucb()->ctx;
86 static struct uprobe *get_current_probe(void)
88 return current_ucb()->p;
91 static void set_current_probe(struct uprobe *p)
96 static void save_current_flags(struct pt_regs *regs)
98 current_ucb()->flags = regs->flags;
101 static void restore_current_flags(struct pt_regs *regs, unsigned long flags)
103 regs->flags &= ~IF_MASK;
104 regs->flags |= flags & IF_MASK;
108 * @brief Prepares uprobe for x86.
110 * @param up Pointer to the uprobe.
111 * @return 0 on success,\n
114 int arch_prepare_uprobe(struct uprobe *p)
116 struct task_struct *task = p->task;
117 u8 tramp[UPROBES_TRAMP_LEN + BP_INSN_SIZE]; /* BP for uretprobe */
118 enum { call_relative_opcode = 0xe8 };
120 if (!read_proc_vm_atomic(task, (unsigned long)p->addr,
121 tramp, MAX_INSN_SIZE)) {
122 printk(KERN_ERR "failed to read memory %p!\n", p->addr);
125 /* TODO: this is a workaround */
126 if (tramp[0] == call_relative_opcode) {
127 printk(KERN_INFO "cannot install probe: 1st instruction is call\n");
131 tramp[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
133 p->opcode = tramp[0];
134 p->ainsn.boostable = swap_can_boost(tramp) ? 0 : -1;
136 p->ainsn.insn = swap_slot_alloc(p->sm);
137 if (p->ainsn.insn == NULL) {
138 printk(KERN_ERR "trampoline out of memory\n");
142 if (!write_proc_vm_atomic(task, (unsigned long)p->ainsn.insn,
143 tramp, sizeof(tramp))) {
144 swap_slot_free(p->sm, p->ainsn.insn);
145 printk(KERN_INFO "failed to write memory %p!\n", tramp);
156 * @brief Jump pre-handler.
158 * @param p Pointer to the uprobe.
159 * @param regs Pointer to CPU register data.
162 int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
164 struct ujprobe *jp = container_of(p, struct ujprobe, up);
165 entry_point_t entry = (entry_point_t)jp->entry;
166 unsigned long args[6];
168 /* FIXME some user space apps crash if we clean interrupt bit */
169 /* regs->EREG(flags) &= ~IF_MASK; */
170 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
171 trace_hardirqs_off();
174 /* read first 6 args from stack */
175 if (!read_proc_vm_atomic(current, regs->EREG(sp) + 4,
178 "failed to read user space func arguments %lx!\n",
182 entry(args[0], args[1], args[2], args[3], args[4], args[5]);
184 arch_ujprobe_return();
190 * @brief Prepares uretprobe for x86.
192 * @param ri Pointer to the uretprobe instance.
193 * @param regs Pointer to CPU register data.
196 int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
198 /* Replace the return addr with trampoline addr */
199 unsigned long ra = trampoline_addr(&ri->rp->up);
200 unsigned long ret_addr;
201 ri->sp = (kprobe_opcode_t *)regs->sp;
203 if (get_user(ret_addr, (unsigned long *)regs->sp)) {
204 pr_err("failed to read user space func ra %lx addr=%p!\n",
205 regs->sp, ri->rp->up.addr);
209 if (put_user(ra, (unsigned long *)regs->sp)) {
210 pr_err("failed to write user space func ra %lx!\n", regs->sp);
214 ri->ret_addr = (uprobe_opcode_t *)ret_addr;
219 static bool get_long(struct task_struct *task,
220 unsigned long vaddr, unsigned long *val)
222 return sizeof(*val) != read_proc_vm_atomic(task, vaddr,
226 static bool put_long(struct task_struct *task,
227 unsigned long vaddr, unsigned long *val)
229 return sizeof(*val) != write_proc_vm_atomic(task, vaddr,
234 * @brief Disarms uretprobe on x86 arch.
236 * @param ri Pointer to the uretprobe instance.
237 * @param task Pointer to the task for which the probe.
238 * @return 0 on success,\n
239 * negative error code on error.
241 int arch_disarm_urp_inst(struct uretprobe_instance *ri,
242 struct task_struct *task)
244 unsigned long ret_addr;
245 unsigned long sp = (unsigned long)ri->sp;
246 unsigned long tramp_addr = trampoline_addr(&ri->rp->up);
248 if (get_long(task, sp, &ret_addr)) {
249 printk(KERN_INFO "---> %s (%d/%d): failed to read stack from %08lx\n",
250 task->comm, task->tgid, task->pid, sp);
254 if (tramp_addr == ret_addr) {
255 if (put_long(task, sp, (unsigned long *)&ri->ret_addr)) {
256 printk(KERN_INFO "---> %s (%d/%d): failed to write "
257 "orig_ret_addr to %08lx",
258 task->comm, task->tgid, task->pid, sp);
262 printk(KERN_INFO "---> %s (%d/%d): trampoline NOT found at sp = %08lx\n",
263 task->comm, task->tgid, task->pid, sp);
271 * @brief Gets trampoline address.
273 * @param p Pointer to the uprobe.
274 * @param regs Pointer to CPU register data.
275 * @return Trampoline address.
277 unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs)
279 return trampoline_addr(p);
283 * @brief Restores return address.
285 * @param orig_ret_addr Original return address.
286 * @param regs Pointer to CPU register data.
289 void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs)
291 regs->EREG(ip) = orig_ret_addr;
295 * @brief Removes uprobe.
297 * @param up Pointer to the target uprobe.
300 void arch_remove_uprobe(struct uprobe *p)
302 swap_slot_free(p->sm, p->ainsn.insn);
305 int arch_arm_uprobe(struct uprobe *p)
308 uprobe_opcode_t insn = BREAKPOINT_INSTRUCTION;
309 unsigned long vaddr = (unsigned long)p->addr;
311 ret = write_proc_vm_atomic(p->task, vaddr, &insn, sizeof(insn));
313 pr_err("arch_arm_uprobe: failed to write memory tgid=%u vaddr=%08lx\n",
314 p->task->tgid, vaddr);
322 void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task)
325 unsigned long vaddr = (unsigned long)p->addr;
327 ret = write_proc_vm_atomic(task, vaddr, &p->opcode, sizeof(p->opcode));
329 pr_err("arch_disarm_uprobe: failed to write memory tgid=%u, vaddr=%08lx\n",
334 static void set_user_jmp_op(void *from, void *to)
336 struct __arch_jmp_op {
341 jop.raddr = (long)(to) - ((long)(from) + 5);
342 jop.op = RELATIVEJUMP_INSTRUCTION;
344 if (put_user(jop.op, (char *)from) ||
345 put_user(jop.raddr, (long *)(from + 1)))
346 pr_err("failed to write jump opcode to user space %p\n", from);
349 static void resume_execution(struct uprobe *p,
350 struct pt_regs *regs,
353 unsigned long *tos, tos_dword = 0;
354 unsigned long copy_eip = (unsigned long)p->ainsn.insn;
355 unsigned long orig_eip = (unsigned long)p->addr;
356 uprobe_opcode_t insns[2];
358 regs->EREG(flags) &= ~TF_MASK;
360 tos = (unsigned long *)&tos_dword;
361 if (get_user(tos_dword, (unsigned long *)regs->sp)) {
362 pr_err("failed to read from user space sp=%lx!\n", regs->sp);
366 if (get_user(*(unsigned short *)insns, (unsigned short *)p->ainsn.insn)) {
367 pr_err("failed to read first 2 opcodes %p!\n", p->ainsn.insn);
372 case 0x9c: /* pushfl */
373 *tos &= ~(TF_MASK | IF_MASK);
374 *tos |= flags & (TF_MASK | IF_MASK);
376 case 0xc2: /* iret/ret/lret */
381 case 0xea: /* jmp absolute -- eip is correct */
382 /* eip is already adjusted, no more changes required */
383 p->ainsn.boostable = 1;
385 case 0xe8: /* call relative - Fix return addr */
386 *tos = orig_eip + (*tos - copy_eip);
388 case 0x9a: /* call absolute -- same as call absolute, indirect */
389 *tos = orig_eip + (*tos - copy_eip);
391 if (put_user(tos_dword, (unsigned long *)regs->sp)) {
392 pr_err("failed to write dword to sp=%lx\n", regs->sp);
398 if ((insns[1] & 0x30) == 0x10) {
400 * call absolute, indirect
401 * Fix return addr; eip is correct.
402 * But this is not boostable
404 *tos = orig_eip + (*tos - copy_eip);
406 if (put_user(tos_dword, (unsigned long *)regs->sp)) {
407 pr_err("failed to write dword to sp=%lx\n", regs->sp);
412 } else if (((insns[1] & 0x31) == 0x20) || /* jmp near, absolute
414 ((insns[1] & 0x31) == 0x21)) {
415 /* jmp far, absolute indirect */
416 /* eip is correct. And this is boostable */
417 p->ainsn.boostable = 1;
421 if (insns[1] == 0xc3)
422 /* repz ret special handling: no more changes */
429 if (put_user(tos_dword, (unsigned long *)regs->sp)) {
430 pr_err("failed to write dword to sp=%lx\n", regs->sp);
434 if (p->ainsn.boostable == 0) {
435 if ((regs->EREG(ip) > copy_eip) && (regs->EREG(ip) - copy_eip) +
438 * These instructions can be executed directly if it
439 * jumps back to correct address.
441 set_user_jmp_op((void *) regs->EREG(ip),
443 (regs->EREG(ip) - copy_eip));
444 p->ainsn.boostable = 1;
446 p->ainsn.boostable = -1;
450 regs->EREG(ip) = orig_eip + (regs->EREG(ip) - copy_eip);
456 static void prepare_tramp(struct uprobe *p, struct pt_regs *regs)
458 regs->ip = (unsigned long)p->ainsn.insn;
461 static void prepare_ss(struct pt_regs *regs)
463 /* set single step mode */
464 regs->flags |= TF_MASK;
465 regs->flags &= ~IF_MASK;
469 static unsigned long resume_userspace_addr;
471 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
472 static void __rcu_nmi_enter(void) {}
473 #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
474 #error "This kernel is not support"
475 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) */
476 static void (*__rcu_nmi_enter)(void);
477 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) */
479 static void __used __up_handler(void)
481 struct pt_regs *regs = current_ctx()->ptr_regs;
482 struct thread_info *tinfo = current_thread_info();
483 struct uprobe *p = current_ucb()->p;
485 /* restore KS regs */
486 *regs = current_ctx()->save_regs;
489 current_ctx()->handler(p, regs);
491 /* resume_userspace */
497 : "r" (regs), "r" (tinfo) , "r" (resume_userspace_addr)
501 void up_handler(void);
504 /* skip hex tractor-driver bytes to make some free space (skip regs) */
509 static int exceptions_handler(struct pt_regs *regs,
510 int (*handler)(struct uprobe *, struct pt_regs *))
513 current_ctx()->save_regs = *regs;
514 current_ctx()->ptr_regs = regs;
517 current_ctx()->handler = handler;
519 /* setup regs to return to KS */
520 regs->ip = (unsigned long)up_handler;
521 regs->ds = __USER_DS;
522 regs->es = __USER_DS;
523 regs->fs = __KERNEL_PERCPU;
524 regs->cs = __KERNEL_CS | get_kernel_rpl();
526 regs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
529 * Here rcu_nmi_enter() call is needed, because we change
530 * US context to KS context as a result rcu_nmi_exit() will
531 * be called on exiting exception and rcu_nmi_enter() and
532 * rcu_nmi_exit() calls must be consistent
539 static int uprobe_handler_retprobe(struct uprobe *p, struct pt_regs *regs)
543 ret = trampoline_uprobe_handler(p, regs);
544 set_current_probe(NULL);
550 static int uprobe_handler_part2(struct uprobe *p, struct pt_regs *regs)
552 if (!p->pre_handler(p, regs)) {
553 prepare_tramp(p, regs);
554 if (p->ainsn.boostable == 1 && !p->post_handler)
555 goto exit_and_put_up;
557 save_current_flags(regs);
558 set_current_probe(p);
565 set_current_probe(NULL);
570 static int uprobe_handler_atomic(struct pt_regs *regs)
572 pid_t tgid = current->tgid;
573 unsigned long vaddr = regs->ip - 1;
574 struct uprobe *p = get_uprobe((void *)vaddr, tgid);
578 if (p->pre_handler) {
579 set_current_probe(p);
580 exceptions_handler(regs, uprobe_handler_part2);
582 uprobe_handler_part2(p, regs);
585 unsigned long tramp_vaddr;
587 tramp_vaddr = vaddr - UPROBES_TRAMP_RET_BREAK_IDX;
588 p = get_uprobe_by_insn_slot((void *)tramp_vaddr, tgid, regs);
590 pr_info("no_uprobe\n");
594 set_current_probe(p);
596 exceptions_handler(regs, uprobe_handler_retprobe);
602 static int post_uprobe_handler(struct uprobe *p, struct pt_regs *regs)
604 unsigned long flags = current_ucb()->flags;
606 resume_execution(p, regs, flags);
607 restore_current_flags(regs, flags);
609 /* reset current probe */
610 set_current_probe(NULL);
616 static int post_uprobe_handler_atomic(struct pt_regs *regs)
618 struct uprobe *p = get_current_probe();
621 exceptions_handler(regs, post_uprobe_handler);
623 pr_info("task[%u %u %s] current uprobe is not found\n",
624 current->tgid, current->pid, current->comm);
630 static int uprobe_exceptions_notify(struct notifier_block *self,
631 unsigned long val, void *data)
633 struct die_args *args = (struct die_args *)data;
634 int ret = NOTIFY_DONE;
636 if (args->regs == NULL || !swap_user_mode(args->regs))
640 #ifdef CONFIG_KPROBES
645 if (uprobe_handler_atomic(args->regs))
649 if (post_uprobe_handler_atomic(args->regs))
659 static struct notifier_block uprobe_exceptions_nb = {
660 .notifier_call = uprobe_exceptions_notify,
664 struct up_valid_struct {
669 static int __uprobe_is_valid(struct uprobe *p, void *data)
671 struct up_valid_struct *valid = (struct up_valid_struct *)data;
681 static bool uprobe_is_valid(struct uprobe *p)
683 struct up_valid_struct valid = {
688 for_each_uprobe(__uprobe_is_valid, (void *)&valid);
693 static int do_exit_handler(struct kprobe *kp, struct pt_regs *regs)
697 p = get_current_probe();
698 if (p && uprobe_is_valid(p)) {
699 set_current_probe(NULL);
706 static struct kprobe kp_do_exit = {
707 .pre_handler = do_exit_handler
711 * @brief Registers notify.
713 * @return register_die_notifier result.
715 int swap_arch_init_uprobes(void)
720 sym = "resume_userspace";
721 resume_userspace_addr = swap_ksyms(sym);
722 if (resume_userspace_addr == 0)
726 kp_do_exit.addr = swap_ksyms(sym);
727 if (kp_do_exit.addr == 0)
730 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
731 sym = "rcu_nmi_enter";
732 __rcu_nmi_enter = (void *)swap_ksyms(sym);
733 if (__rcu_nmi_enter == NULL)
735 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) */
737 ret = swap_td_raw_reg(&td_raw, sizeof(struct uprobe_ctlblk));
741 ret = register_die_notifier(&uprobe_exceptions_nb);
745 ret = swap_register_kprobe(&kp_do_exit);
752 unregister_die_notifier(&uprobe_exceptions_nb);
754 swap_td_raw_unreg(&td_raw);
758 pr_err("symbol '%s' not found\n", sym);
763 * @brief Unregisters notify.
767 void swap_arch_exit_uprobes(void)
769 swap_unregister_kprobe(&kp_do_exit);
770 unregister_die_notifier(&uprobe_exceptions_nb);
771 swap_td_raw_unreg(&td_raw);