patch.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. #ifdef CONFIG_MMU
  17. static DEFINE_RAW_SPINLOCK(patch_lock);
  18. static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags)
  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. set_fixmap(fixmap, page_to_phys(page));
  32. return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
  33. }
  34. static void __kprobes patch_unmap(int fixmap, unsigned long *flags)
  35. {
  36. clear_fixmap(fixmap);
  37. if (flags)
  38. raw_spin_unlock_irqrestore(&patch_lock, *flags);
  39. }
  40. #else
  41. static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags)
  42. {
  43. return addr;
  44. }
  45. static void __kprobes patch_unmap(int fixmap, unsigned long *flags) { }
  46. #endif
  47. void __kprobes __patch_text_real(void *addr, unsigned int insn, bool remap)
  48. {
  49. bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL);
  50. unsigned int uintaddr = (uintptr_t) addr;
  51. bool twopage = false;
  52. unsigned long flags;
  53. void *waddr = addr;
  54. int size;
  55. if (remap)
  56. waddr = patch_map(addr, FIX_TEXT_POKE0, &flags);
  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. }
  87. flush_icache_range((uintptr_t)(addr),
  88. (uintptr_t)(addr) + size);
  89. }
  90. static int __kprobes patch_text_stop_machine(void *data)
  91. {
  92. struct patch *patch = data;
  93. __patch_text(patch->addr, patch->insn);
  94. return 0;
  95. }
  96. void __kprobes patch_text(void *addr, unsigned int insn)
  97. {
  98. struct patch patch = {
  99. .addr = addr,
  100. .insn = insn,
  101. };
  102. stop_machine_cpuslocked(patch_text_stop_machine, &patch, NULL);
  103. }