static_call.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. "__static_call_return:\n\t"
  38. ANNOTATE_NOENDBR
  39. ANNOTATE_RETPOLINE_SAFE
  40. "ret; int3\n\t"
  41. ".size __static_call_return, . - __static_call_return \n\t");
  42. static void __ref __static_call_transform(void *insn, enum insn_type type,
  43. void *func, bool modinit)
  44. {
  45. const void *emulate = NULL;
  46. int size = CALL_INSN_SIZE;
  47. const void *code;
  48. u8 op, buf[6];
  49. if ((type == JMP || type == RET) && (op = __is_Jcc(insn)))
  50. type = JCC;
  51. switch (type) {
  52. case CALL:
  53. code = text_gen_insn(CALL_INSN_OPCODE, insn, func);
  54. if (func == &__static_call_return0) {
  55. emulate = code;
  56. code = &xor5rax;
  57. }
  58. break;
  59. case NOP:
  60. code = x86_nops[5];
  61. break;
  62. case JMP:
  63. code = text_gen_insn(JMP32_INSN_OPCODE, insn, func);
  64. break;
  65. case RET:
  66. if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
  67. code = text_gen_insn(JMP32_INSN_OPCODE, insn, &__x86_return_thunk);
  68. else
  69. code = &retinsn;
  70. break;
  71. case JCC:
  72. if (!func) {
  73. func = __static_call_return;
  74. if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
  75. func = __x86_return_thunk;
  76. }
  77. buf[0] = 0x0f;
  78. __text_gen_insn(buf+1, op, insn+1, func, 5);
  79. code = buf;
  80. size = 6;
  81. break;
  82. }
  83. if (memcmp(insn, code, size) == 0)
  84. return;
  85. if (system_state == SYSTEM_BOOTING || modinit)
  86. return text_poke_early(insn, code, size);
  87. text_poke_bp(insn, code, size, emulate);
  88. }
  89. static void __static_call_validate(u8 *insn, bool tail, bool tramp)
  90. {
  91. u8 opcode = insn[0];
  92. if (tramp && memcmp(insn+5, tramp_ud, 3)) {
  93. pr_err("trampoline signature fail");
  94. BUG();
  95. }
  96. if (tail) {
  97. if (opcode == JMP32_INSN_OPCODE ||
  98. opcode == RET_INSN_OPCODE ||
  99. __is_Jcc(insn))
  100. return;
  101. } else {
  102. if (opcode == CALL_INSN_OPCODE ||
  103. !memcmp(insn, x86_nops[5], 5) ||
  104. !memcmp(insn, xor5rax, 5))
  105. return;
  106. }
  107. /*
  108. * If we ever trigger this, our text is corrupt, we'll probably not live long.
  109. */
  110. pr_err("unexpected static_call insn opcode 0x%x at %pS\n", opcode, insn);
  111. BUG();
  112. }
  113. static inline enum insn_type __sc_insn(bool null, bool tail)
  114. {
  115. /*
  116. * Encode the following table without branches:
  117. *
  118. * tail null insn
  119. * -----+-------+------
  120. * 0 | 0 | CALL
  121. * 0 | 1 | NOP
  122. * 1 | 0 | JMP
  123. * 1 | 1 | RET
  124. */
  125. return 2*tail + null;
  126. }
  127. void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
  128. {
  129. mutex_lock(&text_mutex);
  130. if (tramp) {
  131. __static_call_validate(tramp, true, true);
  132. __static_call_transform(tramp, __sc_insn(!func, true), func, false);
  133. }
  134. if (IS_ENABLED(CONFIG_HAVE_STATIC_CALL_INLINE) && site) {
  135. __static_call_validate(site, tail, false);
  136. __static_call_transform(site, __sc_insn(!func, tail), func, false);
  137. }
  138. mutex_unlock(&text_mutex);
  139. }
  140. EXPORT_SYMBOL_GPL(arch_static_call_transform);
  141. #ifdef CONFIG_RETHUNK
  142. /*
  143. * This is called by apply_returns() to fix up static call trampolines,
  144. * specifically ARCH_DEFINE_STATIC_CALL_NULL_TRAMP which is recorded as
  145. * having a return trampoline.
  146. *
  147. * The problem is that static_call() is available before determining
  148. * X86_FEATURE_RETHUNK and, by implication, running alternatives.
  149. *
  150. * This means that __static_call_transform() above can have overwritten the
  151. * return trampoline and we now need to fix things up to be consistent.
  152. */
  153. bool __static_call_fixup(void *tramp, u8 op, void *dest)
  154. {
  155. unsigned long addr = (unsigned long)tramp;
  156. /*
  157. * Not all .return_sites are a static_call trampoline (most are not).
  158. * Check if the 3 bytes after the return are still kernel text, if not,
  159. * then this definitely is not a trampoline and we need not worry
  160. * further.
  161. *
  162. * This avoids the memcmp() below tripping over pagefaults etc..
  163. */
  164. if (((addr >> PAGE_SHIFT) != ((addr + 7) >> PAGE_SHIFT)) &&
  165. !kernel_text_address(addr + 7))
  166. return false;
  167. if (memcmp(tramp+5, tramp_ud, 3)) {
  168. /* Not a trampoline site, not our problem. */
  169. return false;
  170. }
  171. mutex_lock(&text_mutex);
  172. if (op == RET_INSN_OPCODE || dest == &__x86_return_thunk)
  173. __static_call_transform(tramp, RET, NULL, true);
  174. mutex_unlock(&text_mutex);
  175. return true;
  176. }
  177. #endif