asan_posix.cc revision 6895adc39c4e09371154c8037366ad4464163ed0
1//===-- asan_linux.cc -----------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of AddressSanitizer, an address sanity checker. 11// 12// Posix-specific details. 13//===----------------------------------------------------------------------===// 14#if defined(__linux__) || defined(__APPLE__) 15 16#include "asan_internal.h" 17#include "asan_interceptors.h" 18#include "asan_mapping.h" 19#include "asan_procmaps.h" 20#include "asan_stack.h" 21#include "asan_thread_registry.h" 22#include "sanitizer_common/sanitizer_libc.h" 23#include "sanitizer_common/sanitizer_procmaps.h" 24 25#include <pthread.h> 26#include <signal.h> 27#include <stdlib.h> 28#include <sys/time.h> 29#include <sys/resource.h> 30#include <unistd.h> 31 32#ifdef ANDROID 33#include <sys/atomics.h> 34#endif 35 36// Should not add dependency on libstdc++, 37// since most of the stuff here is inlinable. 38#include <algorithm> 39 40static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. 41 42namespace __asan { 43 44static inline bool IntervalsAreSeparate(uptr start1, uptr end1, 45 uptr start2, uptr end2) { 46 CHECK(start1 <= end1); 47 CHECK(start2 <= end2); 48 return (end1 < start2) || (end2 < start1); 49} 50 51// FIXME: this is thread-unsafe, but should not cause problems most of the time. 52// When the shadow is mapped only a single thread usually exists (plus maybe 53// several worker threads on Mac, which aren't expected to map big chunks of 54// memory). 55bool AsanShadowRangeIsAvailable() { 56 ProcessMaps procmaps; 57 uptr start, end; 58 uptr shadow_start = kLowShadowBeg; 59 if (kLowShadowBeg > 0) shadow_start -= kMmapGranularity; 60 uptr shadow_end = kHighShadowEnd; 61 while (procmaps.Next(&start, &end, 62 /*offset*/0, /*filename*/0, /*filename_size*/0)) { 63 if (!IntervalsAreSeparate(start, end, shadow_start, shadow_end)) 64 return false; 65 } 66 return true; 67} 68 69static void MaybeInstallSigaction(int signum, 70 void (*handler)(int, siginfo_t *, void *)) { 71 if (!AsanInterceptsSignal(signum)) 72 return; 73 struct sigaction sigact; 74 REAL(memset)(&sigact, 0, sizeof(sigact)); 75 sigact.sa_sigaction = handler; 76 sigact.sa_flags = SA_SIGINFO; 77 if (FLAG_use_sigaltstack) sigact.sa_flags |= SA_ONSTACK; 78 CHECK(0 == REAL(sigaction)(signum, &sigact, 0)); 79 if (FLAG_v >= 1) { 80 Report("Installed the sigaction for signal %d\n", signum); 81 } 82} 83 84static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) { 85 uptr addr = (uptr)siginfo->si_addr; 86 // Write the first message using the bullet-proof write. 87 if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); 88 uptr pc, sp, bp; 89 GetPcSpBp(context, &pc, &sp, &bp); 90 AsanReport("ERROR: AddressSanitizer crashed on unknown address %p" 91 " (pc %p sp %p bp %p T%d)\n", 92 (void*)addr, (void*)pc, (void*)sp, (void*)bp, 93 asanThreadRegistry().GetCurrentTidOrInvalid()); 94 AsanPrintf("AddressSanitizer can not provide additional info. ABORTING\n"); 95 GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp); 96 stack.PrintStack(); 97 ShowStatsAndAbort(); 98} 99 100void SetAlternateSignalStack() { 101 stack_t altstack, oldstack; 102 CHECK(0 == sigaltstack(0, &oldstack)); 103 // If the alternate stack is already in place, do nothing. 104 if ((oldstack.ss_flags & SS_DISABLE) == 0) return; 105 // TODO(glider): the mapped stack should have the MAP_STACK flag in the 106 // future. It is not required by man 2 sigaltstack now (they're using 107 // malloc()). 108 void* base = MmapOrDie(kAltStackSize, __FUNCTION__); 109 altstack.ss_sp = base; 110 altstack.ss_flags = 0; 111 altstack.ss_size = kAltStackSize; 112 CHECK(0 == sigaltstack(&altstack, 0)); 113 if (FLAG_v > 0) { 114 Report("Alternative stack for T%d set: [%p,%p)\n", 115 asanThreadRegistry().GetCurrentTidOrInvalid(), 116 altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size); 117 } 118} 119 120void UnsetAlternateSignalStack() { 121 stack_t altstack, oldstack; 122 altstack.ss_sp = 0; 123 altstack.ss_flags = SS_DISABLE; 124 altstack.ss_size = 0; 125 CHECK(0 == sigaltstack(&altstack, &oldstack)); 126 UnmapOrDie(oldstack.ss_sp, oldstack.ss_size); 127} 128 129void InstallSignalHandlers() { 130 // Set the alternate signal stack for the main thread. 131 // This will cause SetAlternateSignalStack to be called twice, but the stack 132 // will be actually set only once. 133 if (FLAG_use_sigaltstack) SetAlternateSignalStack(); 134 MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV); 135 MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV); 136} 137 138void AsanDisableCoreDumper() { 139 struct rlimit nocore; 140 nocore.rlim_cur = 0; 141 nocore.rlim_max = 0; 142 setrlimit(RLIMIT_CORE, &nocore); 143} 144 145void AsanDumpProcessMap() { 146 ProcessMaps proc_maps; 147 uptr start, end; 148 const sptr kBufSize = 4095; 149 char filename[kBufSize]; 150 Report("Process memory map follows:\n"); 151 while (proc_maps.Next(&start, &end, /* file_offset */0, 152 filename, kBufSize)) { 153 Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename); 154 } 155 Report("End of process memory map.\n"); 156} 157 158uptr GetThreadSelf() { 159 return (uptr)pthread_self(); 160} 161 162void SleepForSeconds(int seconds) { 163 sleep(seconds); 164} 165 166void Exit(int exitcode) { 167 _exit(exitcode); 168} 169 170void Abort() { 171 abort(); 172} 173 174int Atexit(void (*function)(void)) { 175 return atexit(function); 176} 177 178int AtomicInc(int *a) { 179#ifdef ANDROID 180 return __atomic_inc(a) + 1; 181#else 182 return __sync_add_and_fetch(a, 1); 183#endif 184} 185 186u16 AtomicExchange(u16 *a, u16 new_val) { 187 return __sync_lock_test_and_set(a, new_val); 188} 189 190u8 AtomicExchange(u8 *a, u8 new_val) { 191 return __sync_lock_test_and_set(a, new_val); 192} 193 194void SortArray(uptr *array, uptr size) { 195 std::sort(array, array + size); 196} 197 198// ---------------------- TSD ---------------- {{{1 199 200static pthread_key_t tsd_key; 201static bool tsd_key_inited = false; 202void AsanTSDInit(void (*destructor)(void *tsd)) { 203 CHECK(!tsd_key_inited); 204 tsd_key_inited = true; 205 CHECK(0 == pthread_key_create(&tsd_key, destructor)); 206} 207 208void *AsanTSDGet() { 209 CHECK(tsd_key_inited); 210 return pthread_getspecific(tsd_key); 211} 212 213void AsanTSDSet(void *tsd) { 214 CHECK(tsd_key_inited); 215 pthread_setspecific(tsd_key, tsd); 216} 217 218} // namespace __asan 219 220#endif // __linux__ || __APPLE_ 221