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_CONTAINS_UBSAN 25 # define HWASAN_CONTAINS_UBSAN CAN_SANITIZE_UB 26 #endif 27 28 #ifndef HWASAN_WITH_INTERCEPTORS 29 #define HWASAN_WITH_INTERCEPTORS 0 30 #endif 31 32 #ifndef HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE 33 #define HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE HWASAN_WITH_INTERCEPTORS 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 InitShadow(); 76 void InitPrctl(); 77 void InitThreads(); 78 void InitializeInterceptors(); 79 80 void HwasanAllocatorInit(); 81 82 void *hwasan_malloc(uptr size, StackTrace *stack); 83 void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack); 84 void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack); 85 void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack); 86 void *hwasan_valloc(uptr size, StackTrace *stack); 87 void *hwasan_pvalloc(uptr size, StackTrace *stack); 88 void *hwasan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack); 89 void *hwasan_memalign(uptr alignment, uptr size, StackTrace *stack); 90 int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size, 91 StackTrace *stack); 92 void hwasan_free(void *ptr, StackTrace *stack); 93 94 void InstallAtExitHandler(); 95 96 #define GET_MALLOC_STACK_TRACE \ 97 BufferedStackTrace stack; \ 98 if (hwasan_inited) \ 99 stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \ 100 nullptr, common_flags()->fast_unwind_on_malloc, \ 101 common_flags()->malloc_context_size) 102 103 #define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \ 104 BufferedStackTrace stack; \ 105 if (hwasan_inited) \ 106 stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal) 107 108 #define GET_FATAL_STACK_TRACE_HERE \ 109 GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()) 110 111 #define PRINT_CURRENT_STACK_CHECK() \ 112 { \ 113 GET_FATAL_STACK_TRACE_HERE; \ 114 stack.Print(); \ 115 } 116 117 void HwasanTSDInit(); 118 void HwasanTSDThreadInit(); 119 120 void HwasanOnDeadlySignal(int signo, void *info, void *context); 121 122 void UpdateMemoryUsage(); 123 124 void AppendToErrorMessageBuffer(const char *buffer); 125 126 void AndroidTestTlsSlot(); 127 128 } // namespace __hwasan 129 130 #define HWASAN_MALLOC_HOOK(ptr, size) \ 131 do { \ 132 if (&__sanitizer_malloc_hook) { \ 133 __sanitizer_malloc_hook(ptr, size); \ 134 } \ 135 RunMallocHooks(ptr, size); \ 136 } while (false) 137 #define HWASAN_FREE_HOOK(ptr) \ 138 do { \ 139 if (&__sanitizer_free_hook) { \ 140 __sanitizer_free_hook(ptr); \ 141 } \ 142 RunFreeHooks(ptr); \ 143 } while (false) 144 145 #if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__) 146 // For both bionic and glibc __sigset_t is an unsigned long. 147 typedef unsigned long __hw_sigset_t; 148 // Setjmp and longjmp implementations are platform specific, and hence the 149 // interception code is platform specific too. As yet we've only implemented 150 // the interception for AArch64. 151 typedef unsigned long long __hw_register_buf[22]; 152 struct __hw_jmp_buf_struct { 153 // NOTE: The machine-dependent definition of `__sigsetjmp' 154 // assume that a `__hw_jmp_buf' begins with a `__hw_register_buf' and that 155 // `__mask_was_saved' follows it. Do not move these members or add others 156 // before it. 157 __hw_register_buf __jmpbuf; // Calling environment. 158 int __mask_was_saved; // Saved the signal mask? 159 __hw_sigset_t __saved_mask; // Saved signal mask. 160 }; 161 typedef struct __hw_jmp_buf_struct __hw_jmp_buf[1]; 162 typedef struct __hw_jmp_buf_struct __hw_sigjmp_buf[1]; 163 #endif // HWASAN_WITH_INTERCEPTORS && __aarch64__ 164 165 #endif // HWASAN_H 166