hwasan_interceptors.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //===-- hwasan_interceptors.cpp -------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of HWAddressSanitizer.
  10. //
  11. // Interceptors for standard library functions.
  12. //
  13. // FIXME: move as many interceptors as possible into
  14. // sanitizer_common/sanitizer_common_interceptors.h
  15. //===----------------------------------------------------------------------===//
  16. #include "interception/interception.h"
  17. #include "hwasan.h"
  18. #include "hwasan_thread.h"
  19. #include "sanitizer_common/sanitizer_stackdepot.h"
  20. #if !SANITIZER_FUCHSIA
  21. using namespace __hwasan;
  22. #if HWASAN_WITH_INTERCEPTORS
  23. struct ThreadStartArg {
  24. thread_callback_t callback;
  25. void *param;
  26. };
  27. static void *HwasanThreadStartFunc(void *arg) {
  28. __hwasan_thread_enter();
  29. ThreadStartArg A = *reinterpret_cast<ThreadStartArg*>(arg);
  30. UnmapOrDie(arg, GetPageSizeCached());
  31. return A.callback(A.param);
  32. }
  33. INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
  34. void * param) {
  35. ScopedTaggingDisabler disabler;
  36. ThreadStartArg *A = reinterpret_cast<ThreadStartArg *> (MmapOrDie(
  37. GetPageSizeCached(), "pthread_create"));
  38. *A = {callback, param};
  39. int res = REAL(pthread_create)(th, attr, &HwasanThreadStartFunc, A);
  40. return res;
  41. }
  42. INTERCEPTOR(int, pthread_join, void *t, void **arg) {
  43. return REAL(pthread_join)(t, arg);
  44. }
  45. DEFINE_REAL_PTHREAD_FUNCTIONS
  46. DEFINE_REAL(int, vfork)
  47. DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
  48. // Get and/or change the set of blocked signals.
  49. extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set,
  50. __hw_sigset_t *__restrict __oset);
  51. #define SIG_BLOCK 0
  52. #define SIG_SETMASK 2
  53. extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) {
  54. env[0].__magic = kHwJmpBufMagic;
  55. env[0].__mask_was_saved =
  56. (savemask && sigprocmask(SIG_BLOCK, (__hw_sigset_t *)0,
  57. &env[0].__saved_mask) == 0);
  58. return 0;
  59. }
  60. static void __attribute__((always_inline))
  61. InternalLongjmp(__hw_register_buf env, int retval) {
  62. # if defined(__aarch64__)
  63. constexpr size_t kSpIndex = 13;
  64. # elif defined(__x86_64__)
  65. constexpr size_t kSpIndex = 6;
  66. # elif SANITIZER_RISCV64
  67. constexpr size_t kSpIndex = 13;
  68. # endif
  69. // Clear all memory tags on the stack between here and where we're going.
  70. unsigned long long stack_pointer = env[kSpIndex];
  71. // The stack pointer should never be tagged, so we don't need to clear the
  72. // tag for this function call.
  73. __hwasan_handle_longjmp((void *)stack_pointer);
  74. // Run code for handling a longjmp.
  75. // Need to use a register that isn't going to be loaded from the environment
  76. // buffer -- hence why we need to specify the register to use.
  77. // Must implement this ourselves, since we don't know the order of registers
  78. // in different libc implementations and many implementations mangle the
  79. // stack pointer so we can't use it without knowing the demangling scheme.
  80. # if defined(__aarch64__)
  81. register long int retval_tmp asm("x1") = retval;
  82. register void *env_address asm("x0") = &env[0];
  83. asm volatile("ldp x19, x20, [%0, #0<<3];"
  84. "ldp x21, x22, [%0, #2<<3];"
  85. "ldp x23, x24, [%0, #4<<3];"
  86. "ldp x25, x26, [%0, #6<<3];"
  87. "ldp x27, x28, [%0, #8<<3];"
  88. "ldp x29, x30, [%0, #10<<3];"
  89. "ldp d8, d9, [%0, #14<<3];"
  90. "ldp d10, d11, [%0, #16<<3];"
  91. "ldp d12, d13, [%0, #18<<3];"
  92. "ldp d14, d15, [%0, #20<<3];"
  93. "ldr x5, [%0, #13<<3];"
  94. "mov sp, x5;"
  95. // Return the value requested to return through arguments.
  96. // This should be in x1 given what we requested above.
  97. "cmp %1, #0;"
  98. "mov x0, #1;"
  99. "csel x0, %1, x0, ne;"
  100. "br x30;"
  101. : "+r"(env_address)
  102. : "r"(retval_tmp));
  103. # elif defined(__x86_64__)
  104. register long int retval_tmp asm("%rsi") = retval;
  105. register void *env_address asm("%rdi") = &env[0];
  106. asm volatile(
  107. // Restore registers.
  108. "mov (0*8)(%0),%%rbx;"
  109. "mov (1*8)(%0),%%rbp;"
  110. "mov (2*8)(%0),%%r12;"
  111. "mov (3*8)(%0),%%r13;"
  112. "mov (4*8)(%0),%%r14;"
  113. "mov (5*8)(%0),%%r15;"
  114. "mov (6*8)(%0),%%rsp;"
  115. "mov (7*8)(%0),%%rdx;"
  116. // Return 1 if retval is 0.
  117. "mov $1,%%rax;"
  118. "test %1,%1;"
  119. "cmovnz %1,%%rax;"
  120. "jmp *%%rdx;" ::"r"(env_address),
  121. "r"(retval_tmp));
  122. # elif SANITIZER_RISCV64
  123. register long int retval_tmp asm("x11") = retval;
  124. register void *env_address asm("x10") = &env[0];
  125. asm volatile(
  126. "ld ra, 0<<3(%0);"
  127. "ld s0, 1<<3(%0);"
  128. "ld s1, 2<<3(%0);"
  129. "ld s2, 3<<3(%0);"
  130. "ld s3, 4<<3(%0);"
  131. "ld s4, 5<<3(%0);"
  132. "ld s5, 6<<3(%0);"
  133. "ld s6, 7<<3(%0);"
  134. "ld s7, 8<<3(%0);"
  135. "ld s8, 9<<3(%0);"
  136. "ld s9, 10<<3(%0);"
  137. "ld s10, 11<<3(%0);"
  138. "ld s11, 12<<3(%0);"
  139. # if __riscv_float_abi_double
  140. "fld fs0, 14<<3(%0);"
  141. "fld fs1, 15<<3(%0);"
  142. "fld fs2, 16<<3(%0);"
  143. "fld fs3, 17<<3(%0);"
  144. "fld fs4, 18<<3(%0);"
  145. "fld fs5, 19<<3(%0);"
  146. "fld fs6, 20<<3(%0);"
  147. "fld fs7, 21<<3(%0);"
  148. "fld fs8, 22<<3(%0);"
  149. "fld fs9, 23<<3(%0);"
  150. "fld fs10, 24<<3(%0);"
  151. "fld fs11, 25<<3(%0);"
  152. # elif __riscv_float_abi_soft
  153. # else
  154. # error "Unsupported case"
  155. # endif
  156. "ld a4, 13<<3(%0);"
  157. "mv sp, a4;"
  158. // Return the value requested to return through arguments.
  159. // This should be in x11 given what we requested above.
  160. "seqz a0, %1;"
  161. "add a0, a0, %1;"
  162. "ret;"
  163. : "+r"(env_address)
  164. : "r"(retval_tmp));
  165. # endif
  166. }
  167. INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) {
  168. if (env[0].__magic != kHwJmpBufMagic) {
  169. Printf(
  170. "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
  171. "there is a bug in HWASan.\n");
  172. return REAL(siglongjmp)(env, val);
  173. }
  174. if (env[0].__mask_was_saved)
  175. // Restore the saved signal mask.
  176. (void)sigprocmask(SIG_SETMASK, &env[0].__saved_mask,
  177. (__hw_sigset_t *)0);
  178. InternalLongjmp(env[0].__jmpbuf, val);
  179. }
  180. // Required since glibc libpthread calls __libc_longjmp on pthread_exit, and
  181. // _setjmp on start_thread. Hence we have to intercept the longjmp on
  182. // pthread_exit so the __hw_jmp_buf order matches.
  183. INTERCEPTOR(void, __libc_longjmp, __hw_jmp_buf env, int val) {
  184. if (env[0].__magic != kHwJmpBufMagic)
  185. return REAL(__libc_longjmp)(env, val);
  186. InternalLongjmp(env[0].__jmpbuf, val);
  187. }
  188. INTERCEPTOR(void, longjmp, __hw_jmp_buf env, int val) {
  189. if (env[0].__magic != kHwJmpBufMagic) {
  190. Printf(
  191. "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
  192. "there is a bug in HWASan.\n");
  193. return REAL(longjmp)(env, val);
  194. }
  195. InternalLongjmp(env[0].__jmpbuf, val);
  196. }
  197. #undef SIG_BLOCK
  198. #undef SIG_SETMASK
  199. # endif // HWASAN_WITH_INTERCEPTORS
  200. namespace __hwasan {
  201. int OnExit() {
  202. if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
  203. __lsan::HasReportedLeaks()) {
  204. return common_flags()->exitcode;
  205. }
  206. // FIXME: ask frontend whether we need to return failure.
  207. return 0;
  208. }
  209. } // namespace __hwasan
  210. namespace __hwasan {
  211. void InitializeInterceptors() {
  212. static int inited = 0;
  213. CHECK_EQ(inited, 0);
  214. #if HWASAN_WITH_INTERCEPTORS
  215. #if defined(__linux__)
  216. INTERCEPT_FUNCTION(__libc_longjmp);
  217. INTERCEPT_FUNCTION(longjmp);
  218. INTERCEPT_FUNCTION(siglongjmp);
  219. INTERCEPT_FUNCTION(vfork);
  220. #endif // __linux__
  221. INTERCEPT_FUNCTION(pthread_create);
  222. INTERCEPT_FUNCTION(pthread_join);
  223. # endif
  224. inited = 1;
  225. }
  226. } // namespace __hwasan
  227. #endif // #if !SANITIZER_FUCHSIA