hwasan_interceptors.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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. DEFINE_REAL(int, vfork)
  43. DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
  44. // Get and/or change the set of blocked signals.
  45. extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set,
  46. __hw_sigset_t *__restrict __oset);
  47. #define SIG_BLOCK 0
  48. #define SIG_SETMASK 2
  49. extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) {
  50. env[0].__magic = kHwJmpBufMagic;
  51. env[0].__mask_was_saved =
  52. (savemask && sigprocmask(SIG_BLOCK, (__hw_sigset_t *)0,
  53. &env[0].__saved_mask) == 0);
  54. return 0;
  55. }
  56. static void __attribute__((always_inline))
  57. InternalLongjmp(__hw_register_buf env, int retval) {
  58. # if defined(__aarch64__)
  59. constexpr size_t kSpIndex = 13;
  60. # elif defined(__x86_64__)
  61. constexpr size_t kSpIndex = 6;
  62. # endif
  63. // Clear all memory tags on the stack between here and where we're going.
  64. unsigned long long stack_pointer = env[kSpIndex];
  65. // The stack pointer should never be tagged, so we don't need to clear the
  66. // tag for this function call.
  67. __hwasan_handle_longjmp((void *)stack_pointer);
  68. // Run code for handling a longjmp.
  69. // Need to use a register that isn't going to be loaded from the environment
  70. // buffer -- hence why we need to specify the register to use.
  71. // Must implement this ourselves, since we don't know the order of registers
  72. // in different libc implementations and many implementations mangle the
  73. // stack pointer so we can't use it without knowing the demangling scheme.
  74. # if defined(__aarch64__)
  75. register long int retval_tmp asm("x1") = retval;
  76. register void *env_address asm("x0") = &env[0];
  77. asm volatile("ldp x19, x20, [%0, #0<<3];"
  78. "ldp x21, x22, [%0, #2<<3];"
  79. "ldp x23, x24, [%0, #4<<3];"
  80. "ldp x25, x26, [%0, #6<<3];"
  81. "ldp x27, x28, [%0, #8<<3];"
  82. "ldp x29, x30, [%0, #10<<3];"
  83. "ldp d8, d9, [%0, #14<<3];"
  84. "ldp d10, d11, [%0, #16<<3];"
  85. "ldp d12, d13, [%0, #18<<3];"
  86. "ldp d14, d15, [%0, #20<<3];"
  87. "ldr x5, [%0, #13<<3];"
  88. "mov sp, x5;"
  89. // Return the value requested to return through arguments.
  90. // This should be in x1 given what we requested above.
  91. "cmp %1, #0;"
  92. "mov x0, #1;"
  93. "csel x0, %1, x0, ne;"
  94. "br x30;"
  95. : "+r"(env_address)
  96. : "r"(retval_tmp));
  97. # elif defined(__x86_64__)
  98. register long int retval_tmp asm("%rsi") = retval;
  99. register void *env_address asm("%rdi") = &env[0];
  100. asm volatile(
  101. // Restore registers.
  102. "mov (0*8)(%0),%%rbx;"
  103. "mov (1*8)(%0),%%rbp;"
  104. "mov (2*8)(%0),%%r12;"
  105. "mov (3*8)(%0),%%r13;"
  106. "mov (4*8)(%0),%%r14;"
  107. "mov (5*8)(%0),%%r15;"
  108. "mov (6*8)(%0),%%rsp;"
  109. "mov (7*8)(%0),%%rdx;"
  110. // Return 1 if retval is 0.
  111. "mov $1,%%rax;"
  112. "test %1,%1;"
  113. "cmovnz %1,%%rax;"
  114. "jmp *%%rdx;" ::"r"(env_address),
  115. "r"(retval_tmp));
  116. # endif
  117. }
  118. INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) {
  119. if (env[0].__magic != kHwJmpBufMagic) {
  120. Printf(
  121. "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
  122. "there is a bug in HWASan.\n");
  123. return REAL(siglongjmp)(env, val);
  124. }
  125. if (env[0].__mask_was_saved)
  126. // Restore the saved signal mask.
  127. (void)sigprocmask(SIG_SETMASK, &env[0].__saved_mask,
  128. (__hw_sigset_t *)0);
  129. InternalLongjmp(env[0].__jmpbuf, val);
  130. }
  131. // Required since glibc libpthread calls __libc_longjmp on pthread_exit, and
  132. // _setjmp on start_thread. Hence we have to intercept the longjmp on
  133. // pthread_exit so the __hw_jmp_buf order matches.
  134. INTERCEPTOR(void, __libc_longjmp, __hw_jmp_buf env, int val) {
  135. if (env[0].__magic != kHwJmpBufMagic)
  136. return REAL(__libc_longjmp)(env, val);
  137. InternalLongjmp(env[0].__jmpbuf, val);
  138. }
  139. INTERCEPTOR(void, longjmp, __hw_jmp_buf env, int val) {
  140. if (env[0].__magic != kHwJmpBufMagic) {
  141. Printf(
  142. "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
  143. "there is a bug in HWASan.\n");
  144. return REAL(longjmp)(env, val);
  145. }
  146. InternalLongjmp(env[0].__jmpbuf, val);
  147. }
  148. #undef SIG_BLOCK
  149. #undef SIG_SETMASK
  150. # endif // HWASAN_WITH_INTERCEPTORS
  151. namespace __hwasan {
  152. int OnExit() {
  153. // FIXME: ask frontend whether we need to return failure.
  154. return 0;
  155. }
  156. } // namespace __hwasan
  157. namespace __hwasan {
  158. void InitializeInterceptors() {
  159. static int inited = 0;
  160. CHECK_EQ(inited, 0);
  161. #if HWASAN_WITH_INTERCEPTORS
  162. #if defined(__linux__)
  163. INTERCEPT_FUNCTION(__libc_longjmp);
  164. INTERCEPT_FUNCTION(longjmp);
  165. INTERCEPT_FUNCTION(siglongjmp);
  166. INTERCEPT_FUNCTION(vfork);
  167. #endif // __linux__
  168. INTERCEPT_FUNCTION(pthread_create);
  169. #endif
  170. inited = 1;
  171. }
  172. } // namespace __hwasan
  173. #endif // #if !SANITIZER_FUCHSIA