hwasan.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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 InstallAtExitCheckLeaks();
  120. void UpdateMemoryUsage();
  121. void AppendToErrorMessageBuffer(const char *buffer);
  122. void AndroidTestTlsSlot();
  123. // This is a compiler-generated struct that can be shared between hwasan
  124. // implementations.
  125. struct AccessInfo {
  126. uptr addr;
  127. uptr size;
  128. bool is_store;
  129. bool is_load;
  130. bool recover;
  131. };
  132. // Given access info and frame information, unwind the stack and report the tag
  133. // mismatch.
  134. void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc,
  135. uptr *registers_frame = nullptr);
  136. // This dispatches to HandleTagMismatch but sets up the AccessInfo, program
  137. // counter, and frame pointer.
  138. void HwasanTagMismatch(uptr addr, uptr pc, uptr frame, uptr access_info,
  139. uptr *registers_frame, size_t outsize);
  140. } // namespace __hwasan
  141. #if HWASAN_WITH_INTERCEPTORS
  142. // For both bionic and glibc __sigset_t is an unsigned long.
  143. typedef unsigned long __hw_sigset_t;
  144. // Setjmp and longjmp implementations are platform specific, and hence the
  145. // interception code is platform specific too.
  146. # if defined(__aarch64__)
  147. constexpr size_t kHwRegisterBufSize = 22;
  148. # elif defined(__x86_64__)
  149. constexpr size_t kHwRegisterBufSize = 8;
  150. # elif SANITIZER_RISCV64
  151. // saving PC, 12 int regs, sp, 12 fp regs
  152. # ifndef __riscv_float_abi_soft
  153. constexpr size_t kHwRegisterBufSize = 1 + 12 + 1 + 12;
  154. # else
  155. constexpr size_t kHwRegisterBufSize = 1 + 12 + 1;
  156. # endif
  157. # endif
  158. typedef unsigned long long __hw_register_buf[kHwRegisterBufSize];
  159. struct __hw_jmp_buf_struct {
  160. // NOTE: The machine-dependent definition of `__sigsetjmp'
  161. // assume that a `__hw_jmp_buf' begins with a `__hw_register_buf' and that
  162. // `__mask_was_saved' follows it. Do not move these members or add others
  163. // before it.
  164. //
  165. // We add a __magic field to our struct to catch cases where libc's setjmp
  166. // populated the jmp_buf instead of our interceptor.
  167. __hw_register_buf __jmpbuf; // Calling environment.
  168. unsigned __mask_was_saved : 1; // Saved the signal mask?
  169. unsigned __magic : 31; // Used to distinguish __hw_jmp_buf from jmp_buf.
  170. __hw_sigset_t __saved_mask; // Saved signal mask.
  171. };
  172. typedef struct __hw_jmp_buf_struct __hw_jmp_buf[1];
  173. typedef struct __hw_jmp_buf_struct __hw_sigjmp_buf[1];
  174. constexpr unsigned kHwJmpBufMagic = 0x248ACE77;
  175. #endif // HWASAN_WITH_INTERCEPTORS
  176. #define ENSURE_HWASAN_INITED() \
  177. do { \
  178. CHECK(!hwasan_init_is_running); \
  179. if (!hwasan_inited) { \
  180. __hwasan_init(); \
  181. } \
  182. } while (0)
  183. #endif // HWASAN_H