cfi.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * This is for all the tests relating directly to Control Flow Integrity.
  4. */
  5. #include "lkdtm.h"
  6. #include <asm/page.h>
  7. static int called_count;
  8. /* Function taking one argument, without a return value. */
  9. static noinline void lkdtm_increment_void(int *counter)
  10. {
  11. (*counter)++;
  12. }
  13. /* Function taking one argument, returning int. */
  14. static noinline int lkdtm_increment_int(int *counter)
  15. {
  16. (*counter)++;
  17. return *counter;
  18. }
  19. /* Don't allow the compiler to inline the calls. */
  20. static noinline void lkdtm_indirect_call(void (*func)(int *))
  21. {
  22. func(&called_count);
  23. }
  24. /*
  25. * This tries to call an indirect function with a mismatched prototype.
  26. */
  27. static void lkdtm_CFI_FORWARD_PROTO(void)
  28. {
  29. /*
  30. * Matches lkdtm_increment_void()'s prototype, but not
  31. * lkdtm_increment_int()'s prototype.
  32. */
  33. pr_info("Calling matched prototype ...\n");
  34. lkdtm_indirect_call(lkdtm_increment_void);
  35. pr_info("Calling mismatched prototype ...\n");
  36. lkdtm_indirect_call((void *)lkdtm_increment_int);
  37. pr_err("FAIL: survived mismatched prototype function call!\n");
  38. pr_expected_config(CONFIG_CFI_CLANG);
  39. }
  40. /*
  41. * This can stay local to LKDTM, as there should not be a production reason
  42. * to disable PAC && SCS.
  43. */
  44. #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
  45. # ifdef CONFIG_ARM64_BTI_KERNEL
  46. # define __no_pac "branch-protection=bti"
  47. # else
  48. # ifdef CONFIG_CC_HAS_BRANCH_PROT_PAC_RET
  49. # define __no_pac "branch-protection=none"
  50. # else
  51. # define __no_pac "sign-return-address=none"
  52. # endif
  53. # endif
  54. # define __no_ret_protection __noscs __attribute__((__target__(__no_pac)))
  55. #else
  56. # define __no_ret_protection __noscs
  57. #endif
  58. #define no_pac_addr(addr) \
  59. ((__force __typeof__(addr))((uintptr_t)(addr) | PAGE_OFFSET))
  60. /* The ultimate ROP gadget. */
  61. static noinline __no_ret_protection
  62. void set_return_addr_unchecked(unsigned long *expected, unsigned long *addr)
  63. {
  64. /* Use of volatile is to make sure final write isn't seen as a dead store. */
  65. unsigned long * volatile *ret_addr = (unsigned long **)__builtin_frame_address(0) + 1;
  66. /* Make sure we've found the right place on the stack before writing it. */
  67. if (no_pac_addr(*ret_addr) == expected)
  68. *ret_addr = (addr);
  69. else
  70. /* Check architecture, stack layout, or compiler behavior... */
  71. pr_warn("Eek: return address mismatch! %px != %px\n",
  72. *ret_addr, addr);
  73. }
  74. static noinline
  75. void set_return_addr(unsigned long *expected, unsigned long *addr)
  76. {
  77. /* Use of volatile is to make sure final write isn't seen as a dead store. */
  78. unsigned long * volatile *ret_addr = (unsigned long **)__builtin_frame_address(0) + 1;
  79. /* Make sure we've found the right place on the stack before writing it. */
  80. if (no_pac_addr(*ret_addr) == expected)
  81. *ret_addr = (addr);
  82. else
  83. /* Check architecture, stack layout, or compiler behavior... */
  84. pr_warn("Eek: return address mismatch! %px != %px\n",
  85. *ret_addr, addr);
  86. }
  87. static volatile int force_check;
  88. static void lkdtm_CFI_BACKWARD(void)
  89. {
  90. /* Use calculated gotos to keep labels addressable. */
  91. void *labels[] = { NULL, &&normal, &&redirected, &&check_normal, &&check_redirected };
  92. pr_info("Attempting unchecked stack return address redirection ...\n");
  93. /* Always false */
  94. if (force_check) {
  95. /*
  96. * Prepare to call with NULLs to avoid parameters being treated as
  97. * constants in -02.
  98. */
  99. set_return_addr_unchecked(NULL, NULL);
  100. set_return_addr(NULL, NULL);
  101. if (force_check)
  102. goto *labels[1];
  103. if (force_check)
  104. goto *labels[2];
  105. if (force_check)
  106. goto *labels[3];
  107. if (force_check)
  108. goto *labels[4];
  109. return;
  110. }
  111. /*
  112. * Use fallthrough switch case to keep basic block ordering between
  113. * set_return_addr*() and the label after it.
  114. */
  115. switch (force_check) {
  116. case 0:
  117. set_return_addr_unchecked(&&normal, &&redirected);
  118. fallthrough;
  119. case 1:
  120. normal:
  121. /* Always true */
  122. if (!force_check) {
  123. pr_err("FAIL: stack return address manipulation failed!\n");
  124. /* If we can't redirect "normally", we can't test mitigations. */
  125. return;
  126. }
  127. break;
  128. default:
  129. redirected:
  130. pr_info("ok: redirected stack return address.\n");
  131. break;
  132. }
  133. pr_info("Attempting checked stack return address redirection ...\n");
  134. switch (force_check) {
  135. case 0:
  136. set_return_addr(&&check_normal, &&check_redirected);
  137. fallthrough;
  138. case 1:
  139. check_normal:
  140. /* Always true */
  141. if (!force_check) {
  142. pr_info("ok: control flow unchanged.\n");
  143. return;
  144. }
  145. check_redirected:
  146. pr_err("FAIL: stack return address was redirected!\n");
  147. break;
  148. }
  149. if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL)) {
  150. pr_expected_config(CONFIG_ARM64_PTR_AUTH_KERNEL);
  151. return;
  152. }
  153. if (IS_ENABLED(CONFIG_SHADOW_CALL_STACK)) {
  154. pr_expected_config(CONFIG_SHADOW_CALL_STACK);
  155. return;
  156. }
  157. pr_warn("This is probably expected, since this %s was built *without* %s=y nor %s=y\n",
  158. lkdtm_kernel_info,
  159. "CONFIG_ARM64_PTR_AUTH_KERNEL", "CONFIG_SHADOW_CALL_STACK");
  160. }
  161. static struct crashtype crashtypes[] = {
  162. CRASHTYPE(CFI_FORWARD_PROTO),
  163. CRASHTYPE(CFI_BACKWARD),
  164. };
  165. struct crashtype_category cfi_crashtypes = {
  166. .crashtypes = crashtypes,
  167. .len = ARRAY_SIZE(crashtypes),
  168. };