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