core.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/stddef.h>
  10. #include <linux/errno.h>
  11. #include <linux/highmem.h>
  12. #include <linux/sched.h>
  13. #include <linux/uprobes.h>
  14. #include <linux/notifier.h>
  15. #include <asm/opcodes.h>
  16. #include <asm/traps.h>
  17. #include "../decode.h"
  18. #include "../decode-arm.h"
  19. #include "core.h"
  20. #define UPROBE_TRAP_NR UINT_MAX
  21. bool is_swbp_insn(uprobe_opcode_t *insn)
  22. {
  23. return (__mem_to_opcode_arm(*insn) & 0x0fffffff) ==
  24. (UPROBE_SWBP_ARM_INSN & 0x0fffffff);
  25. }
  26. int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
  27. unsigned long vaddr)
  28. {
  29. return uprobe_write_opcode(mm, vaddr,
  30. __opcode_to_mem_arm(auprobe->bpinsn));
  31. }
  32. bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs)
  33. {
  34. if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) {
  35. regs->ARM_pc += 4;
  36. return true;
  37. }
  38. return false;
  39. }
  40. bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
  41. {
  42. probes_opcode_t opcode;
  43. if (!auprobe->simulate)
  44. return false;
  45. opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn);
  46. auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs);
  47. return true;
  48. }
  49. unsigned long
  50. arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
  51. struct pt_regs *regs)
  52. {
  53. unsigned long orig_ret_vaddr;
  54. orig_ret_vaddr = regs->ARM_lr;
  55. /* Replace the return addr with trampoline addr */
  56. regs->ARM_lr = trampoline_vaddr;
  57. return orig_ret_vaddr;
  58. }
  59. int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
  60. unsigned long addr)
  61. {
  62. unsigned int insn;
  63. unsigned int bpinsn;
  64. enum probes_insn ret;
  65. /* Thumb not yet support */
  66. if (addr & 0x3)
  67. return -EINVAL;
  68. insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn);
  69. auprobe->ixol[0] = __opcode_to_mem_arm(insn);
  70. auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN);
  71. ret = arm_probes_decode_insn(insn, &auprobe->asi, false,
  72. uprobes_probes_actions, NULL);
  73. switch (ret) {
  74. case INSN_REJECTED:
  75. return -EINVAL;
  76. case INSN_GOOD_NO_SLOT:
  77. auprobe->simulate = true;
  78. break;
  79. case INSN_GOOD:
  80. default:
  81. break;
  82. }
  83. bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff;
  84. if (insn >= 0xe0000000)
  85. bpinsn |= 0xe0000000; /* Unconditional instruction */
  86. else
  87. bpinsn |= insn & 0xf0000000; /* Copy condition from insn */
  88. auprobe->bpinsn = bpinsn;
  89. return 0;
  90. }
  91. void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
  92. void *src, unsigned long len)
  93. {
  94. void *xol_page_kaddr = kmap_atomic(page);
  95. void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK);
  96. preempt_disable();
  97. /* Initialize the slot */
  98. memcpy(dst, src, len);
  99. /* flush caches (dcache/icache) */
  100. flush_uprobe_xol_access(page, vaddr, dst, len);
  101. preempt_enable();
  102. kunmap_atomic(xol_page_kaddr);
  103. }
  104. int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
  105. {
  106. struct uprobe_task *utask = current->utask;
  107. if (auprobe->prehandler)
  108. auprobe->prehandler(auprobe, &utask->autask, regs);
  109. utask->autask.saved_trap_no = current->thread.trap_no;
  110. current->thread.trap_no = UPROBE_TRAP_NR;
  111. regs->ARM_pc = utask->xol_vaddr;
  112. return 0;
  113. }
  114. int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
  115. {
  116. struct uprobe_task *utask = current->utask;
  117. WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR);
  118. current->thread.trap_no = utask->autask.saved_trap_no;
  119. regs->ARM_pc = utask->vaddr + 4;
  120. if (auprobe->posthandler)
  121. auprobe->posthandler(auprobe, &utask->autask, regs);
  122. return 0;
  123. }
  124. bool arch_uprobe_xol_was_trapped(struct task_struct *t)
  125. {
  126. if (t->thread.trap_no != UPROBE_TRAP_NR)
  127. return true;
  128. return false;
  129. }
  130. void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
  131. {
  132. struct uprobe_task *utask = current->utask;
  133. current->thread.trap_no = utask->autask.saved_trap_no;
  134. instruction_pointer_set(regs, utask->vaddr);
  135. }
  136. int arch_uprobe_exception_notify(struct notifier_block *self,
  137. unsigned long val, void *data)
  138. {
  139. return NOTIFY_DONE;
  140. }
  141. static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
  142. {
  143. unsigned long flags;
  144. local_irq_save(flags);
  145. instr &= 0x0fffffff;
  146. if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff))
  147. uprobe_pre_sstep_notifier(regs);
  148. else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff))
  149. uprobe_post_sstep_notifier(regs);
  150. local_irq_restore(flags);
  151. return 0;
  152. }
  153. unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
  154. {
  155. return instruction_pointer(regs);
  156. }
  157. static struct undef_hook uprobes_arm_break_hook = {
  158. .instr_mask = 0x0fffffff,
  159. .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff),
  160. .cpsr_mask = MODE_MASK,
  161. .cpsr_val = USR_MODE,
  162. .fn = uprobe_trap_handler,
  163. };
  164. static struct undef_hook uprobes_arm_ss_hook = {
  165. .instr_mask = 0x0fffffff,
  166. .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff),
  167. .cpsr_mask = MODE_MASK,
  168. .cpsr_val = USR_MODE,
  169. .fn = uprobe_trap_handler,
  170. };
  171. static int arch_uprobes_init(void)
  172. {
  173. register_undef_hook(&uprobes_arm_break_hook);
  174. register_undef_hook(&uprobes_arm_ss_hook);
  175. return 0;
  176. }
  177. device_initcall(arch_uprobes_init);