hwasan.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. //===-- hwasan.h ------------------------------------------------*- C++ -*-===//
  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. // Private Hwasan header.
  12. //===----------------------------------------------------------------------===//
  13. #ifndef HWASAN_H
  14. #define HWASAN_H
  15. #include "hwasan_flags.h"
  16. #include "hwasan_interface_internal.h"
  17. #include "sanitizer_common/sanitizer_common.h"
  18. #include "sanitizer_common/sanitizer_flags.h"
  19. #include "sanitizer_common/sanitizer_internal_defs.h"
  20. #include "sanitizer_common/sanitizer_stacktrace.h"
  21. #include "ubsan/ubsan_platform.h"
  22. #ifndef HWASAN_CONTAINS_UBSAN
  23. # define HWASAN_CONTAINS_UBSAN CAN_SANITIZE_UB
  24. #endif
  25. #ifndef HWASAN_WITH_INTERCEPTORS
  26. #define HWASAN_WITH_INTERCEPTORS 0
  27. #endif
  28. #ifndef HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
  29. #define HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE HWASAN_WITH_INTERCEPTORS
  30. #endif
  31. typedef u8 tag_t;
  32. #if defined(HWASAN_ALIASING_MODE)
  33. # if !defined(__x86_64__)
  34. # error Aliasing mode is only supported on x86_64
  35. # endif
  36. // Tags are done in middle bits using userspace aliasing.
  37. constexpr unsigned kAddressTagShift = 39;
  38. constexpr unsigned kTagBits = 3;
  39. // The alias region is placed next to the shadow so the upper bits of all
  40. // taggable addresses matches the upper bits of the shadow base. This shift
  41. // value determines which upper bits must match. It has a floor of 44 since the
  42. // shadow is always 8TB.
  43. // TODO(morehouse): In alias mode we can shrink the shadow and use a
  44. // simpler/faster shadow calculation.
  45. constexpr unsigned kTaggableRegionCheckShift =
  46. __sanitizer::Max(kAddressTagShift + kTagBits + 1U, 44U);
  47. #elif defined(__x86_64__)
  48. // Tags are done in upper bits using Intel LAM.
  49. constexpr unsigned kAddressTagShift = 57;
  50. constexpr unsigned kTagBits = 6;
  51. #else
  52. // TBI (Top Byte Ignore) feature of AArch64: bits [63:56] are ignored in address
  53. // translation and can be used to store a tag.
  54. constexpr unsigned kAddressTagShift = 56;
  55. constexpr unsigned kTagBits = 8;
  56. #endif // defined(HWASAN_ALIASING_MODE)
  57. // Mask for extracting tag bits from the lower 8 bits.
  58. constexpr uptr kTagMask = (1UL << kTagBits) - 1;
  59. // Mask for extracting tag bits from full pointers.
  60. constexpr uptr kAddressTagMask = kTagMask << kAddressTagShift;
  61. // Minimal alignment of the shadow base address. Determines the space available
  62. // for threads and stack histories. This is an ABI constant.
  63. const unsigned kShadowBaseAlignment = 32;
  64. const unsigned kRecordAddrBaseTagShift = 3;
  65. const unsigned kRecordFPShift = 48;
  66. const unsigned kRecordFPLShift = 4;
  67. const unsigned kRecordFPModulus = 1 << (64 - kRecordFPShift + kRecordFPLShift);
  68. static inline tag_t GetTagFromPointer(uptr p) {
  69. return (p >> kAddressTagShift) & kTagMask;
  70. }
  71. static inline uptr UntagAddr(uptr tagged_addr) {
  72. return tagged_addr & ~kAddressTagMask;
  73. }
  74. static inline void *UntagPtr(const void *tagged_ptr) {
  75. return reinterpret_cast<void *>(
  76. UntagAddr(reinterpret_cast<uptr>(tagged_ptr)));
  77. }
  78. static inline uptr AddTagToPointer(uptr p, tag_t tag) {
  79. return (p & ~kAddressTagMask) | ((uptr)tag << kAddressTagShift);
  80. }
  81. namespace __hwasan {
  82. extern int hwasan_inited;
  83. extern bool hwasan_init_is_running;
  84. extern int hwasan_report_count;
  85. bool InitShadow();
  86. void InitializeOsSupport();
  87. void InitThreads();
  88. void InitializeInterceptors();
  89. void HwasanAllocatorInit();
  90. void HwasanAllocatorLock();
  91. void HwasanAllocatorUnlock();
  92. void *hwasan_malloc(uptr size, StackTrace *stack);
  93. void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack);
  94. void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack);
  95. void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack);
  96. void *hwasan_valloc(uptr size, StackTrace *stack);
  97. void *hwasan_pvalloc(uptr size, StackTrace *stack);
  98. void *hwasan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack);
  99. void *hwasan_memalign(uptr alignment, uptr size, StackTrace *stack);
  100. int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size,
  101. StackTrace *stack);
  102. void hwasan_free(void *ptr, StackTrace *stack);
  103. void InstallAtExitHandler();
  104. #define GET_MALLOC_STACK_TRACE \
  105. BufferedStackTrace stack; \
  106. if (hwasan_inited) \
  107. stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \
  108. nullptr, common_flags()->fast_unwind_on_malloc, \
  109. common_flags()->malloc_context_size)
  110. #define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \
  111. BufferedStackTrace stack; \
  112. if (hwasan_inited) \
  113. stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal)
  114. void HwasanTSDInit();
  115. void HwasanTSDThreadInit();
  116. void HwasanAtExit();
  117. void HwasanOnDeadlySignal(int signo, void *info, void *context);
  118. void HwasanInstallAtForkHandler();
  119. void UpdateMemoryUsage();
  120. void AppendToErrorMessageBuffer(const char *buffer);
  121. void AndroidTestTlsSlot();
  122. // This is a compiler-generated struct that can be shared between hwasan
  123. // implementations.
  124. struct AccessInfo {
  125. uptr addr;
  126. uptr size;
  127. bool is_store;
  128. bool is_load;
  129. bool recover;
  130. };
  131. // Given access info and frame information, unwind the stack and report the tag
  132. // mismatch.
  133. void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc,
  134. uptr *registers_frame = nullptr);
  135. // This dispatches to HandleTagMismatch but sets up the AccessInfo, program
  136. // counter, and frame pointer.
  137. void HwasanTagMismatch(uptr addr, uptr access_info, uptr *registers_frame,
  138. size_t outsize);
  139. } // namespace __hwasan
  140. #define HWASAN_MALLOC_HOOK(ptr, size) \
  141. do { \
  142. if (&__sanitizer_malloc_hook) { \
  143. __sanitizer_malloc_hook(ptr, size); \
  144. } \
  145. RunMallocHooks(ptr, size); \
  146. } while (false)
  147. #define HWASAN_FREE_HOOK(ptr) \
  148. do { \
  149. if (&__sanitizer_free_hook) { \
  150. __sanitizer_free_hook(ptr); \
  151. } \
  152. RunFreeHooks(ptr); \
  153. } while (false)
  154. #if HWASAN_WITH_INTERCEPTORS
  155. // For both bionic and glibc __sigset_t is an unsigned long.
  156. typedef unsigned long __hw_sigset_t;
  157. // Setjmp and longjmp implementations are platform specific, and hence the
  158. // interception code is platform specific too.
  159. # if defined(__aarch64__)
  160. constexpr size_t kHwRegisterBufSize = 22;
  161. # elif defined(__x86_64__)
  162. constexpr size_t kHwRegisterBufSize = 8;
  163. # endif
  164. typedef unsigned long long __hw_register_buf[kHwRegisterBufSize];
  165. struct __hw_jmp_buf_struct {
  166. // NOTE: The machine-dependent definition of `__sigsetjmp'
  167. // assume that a `__hw_jmp_buf' begins with a `__hw_register_buf' and that
  168. // `__mask_was_saved' follows it. Do not move these members or add others
  169. // before it.
  170. //
  171. // We add a __magic field to our struct to catch cases where libc's setjmp
  172. // populated the jmp_buf instead of our interceptor.
  173. __hw_register_buf __jmpbuf; // Calling environment.
  174. unsigned __mask_was_saved : 1; // Saved the signal mask?
  175. unsigned __magic : 31; // Used to distinguish __hw_jmp_buf from jmp_buf.
  176. __hw_sigset_t __saved_mask; // Saved signal mask.
  177. };
  178. typedef struct __hw_jmp_buf_struct __hw_jmp_buf[1];
  179. typedef struct __hw_jmp_buf_struct __hw_sigjmp_buf[1];
  180. constexpr unsigned kHwJmpBufMagic = 0x248ACE77;
  181. #endif // HWASAN_WITH_INTERCEPTORS
  182. #define ENSURE_HWASAN_INITED() \
  183. do { \
  184. CHECK(!hwasan_init_is_running); \
  185. if (!hwasan_inited) { \
  186. __hwasan_init(); \
  187. } \
  188. } while (0)
  189. #endif // HWASAN_H