patch.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/kernel.h>
  3. #include <linux/spinlock.h>
  4. #include <linux/kprobes.h>
  5. #include <linux/mm.h>
  6. #include <linux/stop_machine.h>
  7. #include <asm/cacheflush.h>
  8. #include <asm/fixmap.h>
  9. #include <asm/smp_plat.h>
  10. #include <asm/opcodes.h>
  11. #include <asm/patch.h>
  12. struct patch {
  13. void *addr;
  14. unsigned int insn;
  15. };
  16. static DEFINE_RAW_SPINLOCK(patch_lock);
  17. static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags)
  18. __acquires(&patch_lock)
  19. {
  20. unsigned int uintaddr = (uintptr_t) addr;
  21. bool module = !core_kernel_text(uintaddr);
  22. struct page *page;
  23. if (module && IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
  24. page = vmalloc_to_page(addr);
  25. else if (!module && IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
  26. page = virt_to_page(addr);
  27. else
  28. return addr;
  29. if (flags)
  30. raw_spin_lock_irqsave(&patch_lock, *flags);
  31. else
  32. __acquire(&patch_lock);
  33. set_fixmap(fixmap, page_to_phys(page));
  34. return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
  35. }
  36. static void __kprobes patch_unmap(int fixmap, unsigned long *flags)
  37. __releases(&patch_lock)
  38. {
  39. clear_fixmap(fixmap);
  40. if (flags)
  41. raw_spin_unlock_irqrestore(&patch_lock, *flags);
  42. else
  43. __release(&patch_lock);
  44. }
  45. void __kprobes __patch_text_real(void *addr, unsigned int insn, bool remap)
  46. {
  47. bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL);
  48. unsigned int uintaddr = (uintptr_t) addr;
  49. bool twopage = false;
  50. unsigned long flags;
  51. void *waddr = addr;
  52. int size;
  53. if (remap)
  54. waddr = patch_map(addr, FIX_TEXT_POKE0, &flags);
  55. else
  56. __acquire(&patch_lock);
  57. if (thumb2 && __opcode_is_thumb16(insn)) {
  58. *(u16 *)waddr = __opcode_to_mem_thumb16(insn);
  59. size = sizeof(u16);
  60. } else if (thumb2 && (uintaddr & 2)) {
  61. u16 first = __opcode_thumb32_first(insn);
  62. u16 second = __opcode_thumb32_second(insn);
  63. u16 *addrh0 = waddr;
  64. u16 *addrh1 = waddr + 2;
  65. twopage = (uintaddr & ~PAGE_MASK) == PAGE_SIZE - 2;
  66. if (twopage && remap)
  67. addrh1 = patch_map(addr + 2, FIX_TEXT_POKE1, NULL);
  68. *addrh0 = __opcode_to_mem_thumb16(first);
  69. *addrh1 = __opcode_to_mem_thumb16(second);
  70. if (twopage && addrh1 != addr + 2) {
  71. flush_kernel_vmap_range(addrh1, 2);
  72. patch_unmap(FIX_TEXT_POKE1, NULL);
  73. }
  74. size = sizeof(u32);
  75. } else {
  76. if (thumb2)
  77. insn = __opcode_to_mem_thumb32(insn);
  78. else
  79. insn = __opcode_to_mem_arm(insn);
  80. *(u32 *)waddr = insn;
  81. size = sizeof(u32);
  82. }
  83. if (waddr != addr) {
  84. flush_kernel_vmap_range(waddr, twopage ? size / 2 : size);
  85. patch_unmap(FIX_TEXT_POKE0, &flags);
  86. } else
  87. __release(&patch_lock);
  88. flush_icache_range((uintptr_t)(addr),
  89. (uintptr_t)(addr) + size);
  90. }
  91. static int __kprobes patch_text_stop_machine(void *data)
  92. {
  93. struct patch *patch = data;
  94. __patch_text(patch->addr, patch->insn);
  95. return 0;
  96. }
  97. void __kprobes patch_text(void *addr, unsigned int insn)
  98. {
  99. struct patch patch = {
  100. .addr = addr,
  101. .insn = insn,
  102. };
  103. stop_machine_cpuslocked(patch_text_stop_machine, &patch, NULL);
  104. }