static_call.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/static_call.h>
  3. #include <linux/memory.h>
  4. #include <linux/bug.h>
  5. #include <asm/text-patching.h>
  6. enum insn_type {
  7. CALL = 0, /* site call */
  8. NOP = 1, /* site cond-call */
  9. JMP = 2, /* tramp / site tail-call */
  10. RET = 3, /* tramp / site cond-tail-call */
  11. JCC = 4,
  12. };
  13. /*
  14. * ud1 %esp, %ecx - a 3 byte #UD that is unique to trampolines, chosen such
  15. * that there is no false-positive trampoline identification while also being a
  16. * speculation stop.
  17. */
  18. static const u8 tramp_ud[] = { 0x0f, 0xb9, 0xcc };
  19. /*
  20. * cs cs cs xorl %eax, %eax - a single 5 byte instruction that clears %[er]ax
  21. */
  22. static const u8 xor5rax[] = { 0x2e, 0x2e, 0x2e, 0x31, 0xc0 };
  23. static const u8 retinsn[] = { RET_INSN_OPCODE, 0xcc, 0xcc, 0xcc, 0xcc };
  24. static u8 __is_Jcc(u8 *insn) /* Jcc.d32 */
  25. {
  26. u8 ret = 0;
  27. if (insn[0] == 0x0f) {
  28. u8 tmp = insn[1];
  29. if ((tmp & 0xf0) == 0x80)
  30. ret = tmp;
  31. }
  32. return ret;
  33. }
  34. extern void __static_call_return(void);
  35. asm (".global __static_call_return\n\t"
  36. ".type __static_call_return, @function\n\t"
  37. ASM_FUNC_ALIGN "\n\t"
  38. "__static_call_return:\n\t"
  39. ANNOTATE_NOENDBR
  40. ANNOTATE_RETPOLINE_SAFE
  41. "ret; int3\n\t"
  42. ".size __static_call_return, . - __static_call_return \n\t");
  43. static void __ref __static_call_transform(void *insn, enum insn_type type,
  44. void *func, bool modinit)
  45. {
  46. const void *emulate = NULL;
  47. int size = CALL_INSN_SIZE;
  48. const void *code;
  49. u8 op, buf[6];
  50. if ((type == JMP || type == RET) && (op = __is_Jcc(insn)))
  51. type = JCC;
  52. switch (type) {
  53. case CALL:
  54. func = callthunks_translate_call_dest(func);
  55. code = text_gen_insn(CALL_INSN_OPCODE, insn, func);
  56. if (func == &__static_call_return0) {
  57. emulate = code;
  58. code = &xor5rax;
  59. }
  60. break;
  61. case NOP:
  62. code = x86_nops[5];
  63. break;
  64. case JMP:
  65. code = text_gen_insn(JMP32_INSN_OPCODE, insn, func);
  66. break;
  67. case RET:
  68. if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
  69. code = text_gen_insn(JMP32_INSN_OPCODE, insn, x86_return_thunk);
  70. else
  71. code = &retinsn;
  72. break;
  73. case JCC:
  74. if (!func) {
  75. func = __static_call_return;
  76. if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
  77. func = x86_return_thunk;
  78. }
  79. buf[0] = 0x0f;
  80. __text_gen_insn(buf+1, op, insn+1, func, 5);
  81. code = buf;
  82. size = 6;
  83. break;
  84. }
  85. if (memcmp(insn, code, size) == 0)
  86. return;
  87. if (system_state == SYSTEM_BOOTING || modinit)
  88. return text_poke_early(insn, code, size);
  89. text_poke_bp(insn, code, size, emulate);
  90. }
  91. static void __static_call_validate(u8 *insn, bool tail, bool tramp)
  92. {
  93. u8 opcode = insn[0];
  94. if (tramp && memcmp(insn+5, tramp_ud, 3)) {
  95. pr_err("trampoline signature fail");
  96. BUG();
  97. }
  98. if (tail) {
  99. if (opcode == JMP32_INSN_OPCODE ||
  100. opcode == RET_INSN_OPCODE ||
  101. __is_Jcc(insn))
  102. return;
  103. } else {
  104. if (opcode == CALL_INSN_OPCODE ||
  105. !memcmp(insn, x86_nops[5], 5) ||
  106. !memcmp(insn, xor5rax, 5))
  107. return;
  108. }
  109. /*
  110. * If we ever trigger this, our text is corrupt, we'll probably not live long.
  111. */
  112. pr_err("unexpected static_call insn opcode 0x%x at %pS\n", opcode, insn);
  113. BUG();
  114. }
  115. static inline enum insn_type __sc_insn(bool null, bool tail)
  116. {
  117. /*
  118. * Encode the following table without branches:
  119. *
  120. * tail null insn
  121. * -----+-------+------
  122. * 0 | 0 | CALL
  123. * 0 | 1 | NOP
  124. * 1 | 0 | JMP
  125. * 1 | 1 | RET
  126. */
  127. return 2*tail + null;
  128. }
  129. void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
  130. {
  131. mutex_lock(&text_mutex);
  132. if (tramp) {
  133. __static_call_validate(tramp, true, true);
  134. __static_call_transform(tramp, __sc_insn(!func, true), func, false);
  135. }
  136. if (IS_ENABLED(CONFIG_HAVE_STATIC_CALL_INLINE) && site) {
  137. __static_call_validate(site, tail, false);
  138. __static_call_transform(site, __sc_insn(!func, tail), func, false);
  139. }
  140. mutex_unlock(&text_mutex);
  141. }
  142. EXPORT_SYMBOL_GPL(arch_static_call_transform);
  143. noinstr void __static_call_update_early(void *tramp, void *func)
  144. {
  145. BUG_ON(system_state != SYSTEM_BOOTING);
  146. BUG_ON(static_call_initialized);
  147. __text_gen_insn(tramp, JMP32_INSN_OPCODE, tramp, func, JMP32_INSN_SIZE);
  148. sync_core();
  149. }
  150. #ifdef CONFIG_MITIGATION_RETHUNK
  151. /*
  152. * This is called by apply_returns() to fix up static call trampolines,
  153. * specifically ARCH_DEFINE_STATIC_CALL_NULL_TRAMP which is recorded as
  154. * having a return trampoline.
  155. *
  156. * The problem is that static_call() is available before determining
  157. * X86_FEATURE_RETHUNK and, by implication, running alternatives.
  158. *
  159. * This means that __static_call_transform() above can have overwritten the
  160. * return trampoline and we now need to fix things up to be consistent.
  161. */
  162. bool __static_call_fixup(void *tramp, u8 op, void *dest)
  163. {
  164. unsigned long addr = (unsigned long)tramp;
  165. /*
  166. * Not all .return_sites are a static_call trampoline (most are not).
  167. * Check if the 3 bytes after the return are still kernel text, if not,
  168. * then this definitely is not a trampoline and we need not worry
  169. * further.
  170. *
  171. * This avoids the memcmp() below tripping over pagefaults etc..
  172. */
  173. if (((addr >> PAGE_SHIFT) != ((addr + 7) >> PAGE_SHIFT)) &&
  174. !kernel_text_address(addr + 7))
  175. return false;
  176. if (memcmp(tramp+5, tramp_ud, 3)) {
  177. /* Not a trampoline site, not our problem. */
  178. return false;
  179. }
  180. mutex_lock(&text_mutex);
  181. if (op == RET_INSN_OPCODE || dest == &__x86_return_thunk)
  182. __static_call_transform(tramp, RET, NULL, true);
  183. mutex_unlock(&text_mutex);
  184. return true;
  185. }
  186. #endif