hwasan.h 8.2 KB

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