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 14 #ifndef HWASAN_H 15 #define HWASAN_H 16 17 #include "sanitizer_common/sanitizer_flags.h" 18 #include "sanitizer_common/sanitizer_internal_defs.h" 19 #include "sanitizer_common/sanitizer_stacktrace.h" 20 #include "hwasan_interface_internal.h" 21 #include "hwasan_flags.h" 22 #include "ubsan/ubsan_platform.h" 23 24 #ifndef HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE 25 # define HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE 1 26 #endif 27 28 #ifndef HWASAN_CONTAINS_UBSAN 29 # define HWASAN_CONTAINS_UBSAN CAN_SANITIZE_UB 30 #endif 31 32 #ifndef HWASAN_WITH_INTERCEPTORS 33 #define HWASAN_WITH_INTERCEPTORS 0 34 #endif 35 36 typedef u8 tag_t; 37 38 // TBI (Top Byte Ignore) feature of AArch64: bits [63:56] are ignored in address 39 // translation and can be used to store a tag. 40 const unsigned kAddressTagShift = 56; 41 const uptr kAddressTagMask = 0xFFUL << kAddressTagShift; 42 43 // Minimal alignment of the shadow base address. Determines the space available 44 // for threads and stack histories. This is an ABI constant. 45 const unsigned kShadowBaseAlignment = 32; 46 47 const unsigned kRecordAddrBaseTagShift = 3; 48 const unsigned kRecordFPShift = 48; 49 const unsigned kRecordFPLShift = 4; 50 const unsigned kRecordFPModulus = 1 << (64 - kRecordFPShift + kRecordFPLShift); 51 52 static inline tag_t GetTagFromPointer(uptr p) { 53 return p >> kAddressTagShift; 54 } 55 56 static inline uptr UntagAddr(uptr tagged_addr) { 57 return tagged_addr & ~kAddressTagMask; 58 } 59 60 static inline void *UntagPtr(const void *tagged_ptr) { 61 return reinterpret_cast<void *>( 62 UntagAddr(reinterpret_cast<uptr>(tagged_ptr))); 63 } 64 65 static inline uptr AddTagToPointer(uptr p, tag_t tag) { 66 return (p & ~kAddressTagMask) | ((uptr)tag << kAddressTagShift); 67 } 68 69 namespace __hwasan { 70 71 extern int hwasan_inited; 72 extern bool hwasan_init_is_running; 73 extern int hwasan_report_count; 74 75 bool ProtectRange(uptr beg, uptr end); 76 bool InitShadow(); 77 void InitThreads(); 78 void InitInstrumentation(); 79 void MadviseShadow(); 80 char *GetProcSelfMaps(); 81 void InitializeInterceptors(); 82 83 void HwasanAllocatorInit(); 84 void HwasanAllocatorThreadFinish(); 85 86 void *hwasan_malloc(uptr size, StackTrace *stack); 87 void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack); 88 void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack); 89 void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack); 90 void *hwasan_valloc(uptr size, StackTrace *stack); 91 void *hwasan_pvalloc(uptr size, StackTrace *stack); 92 void *hwasan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack); 93 void *hwasan_memalign(uptr alignment, uptr size, StackTrace *stack); 94 int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size, 95 StackTrace *stack); 96 void hwasan_free(void *ptr, StackTrace *stack); 97 98 void InstallTrapHandler(); 99 void InstallAtExitHandler(); 100 101 void EnterSymbolizer(); 102 void ExitSymbolizer(); 103 bool IsInSymbolizer(); 104 105 struct SymbolizerScope { 106 SymbolizerScope() { EnterSymbolizer(); } 107 ~SymbolizerScope() { ExitSymbolizer(); } 108 }; 109 110 // Returns a "chained" origin id, pointing to the given stack trace followed by 111 // the previous origin id. 112 u32 ChainOrigin(u32 id, StackTrace *stack); 113 114 const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1; 115 116 #define GET_MALLOC_STACK_TRACE \ 117 BufferedStackTrace stack; \ 118 if (hwasan_inited) \ 119 stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \ 120 nullptr, common_flags()->fast_unwind_on_malloc, \ 121 common_flags()->malloc_context_size) 122 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 128 #define GET_FATAL_STACK_TRACE_HERE \ 129 GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()) 130 131 #define PRINT_CURRENT_STACK_CHECK() \ 132 { \ 133 GET_FATAL_STACK_TRACE_HERE; \ 134 stack.Print(); \ 135 } 136 137 class ScopedThreadLocalStateBackup { 138 public: 139 ScopedThreadLocalStateBackup() { Backup(); } 140 ~ScopedThreadLocalStateBackup() { Restore(); } 141 void Backup(); 142 void Restore(); 143 private: 144 u64 va_arg_overflow_size_tls; 145 }; 146 147 void HwasanTSDInit(); 148 void HwasanTSDThreadInit(); 149 150 void HwasanOnDeadlySignal(int signo, void *info, void *context); 151 152 void UpdateMemoryUsage(); 153 154 void AppendToErrorMessageBuffer(const char *buffer); 155 156 void AndroidTestTlsSlot(); 157 158 } // namespace __hwasan 159 160 #define HWASAN_MALLOC_HOOK(ptr, size) \ 161 do { \ 162 if (&__sanitizer_malloc_hook) { \ 163 __sanitizer_malloc_hook(ptr, size); \ 164 } \ 165 RunMallocHooks(ptr, size); \ 166 } while (false) 167 #define HWASAN_FREE_HOOK(ptr) \ 168 do { \ 169 if (&__sanitizer_free_hook) { \ 170 __sanitizer_free_hook(ptr); \ 171 } \ 172 RunFreeHooks(ptr); \ 173 } while (false) 174 175 #endif // HWASAN_H 176