1a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//===-- asan_linux.cc -----------------------------------------------------===// 2a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// 3a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// The LLVM Compiler Infrastructure 4a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// 5a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// This file is distributed under the University of Illinois Open Source 6a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// License. See LICENSE.TXT for details. 7a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// 8a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//===----------------------------------------------------------------------===// 9a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// 10a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 11a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// 12a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// Posix-specific details. 13a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//===----------------------------------------------------------------------===// 14a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#if defined(__linux__) || defined(__APPLE__) 15a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany 16a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include "asan_internal.h" 17a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include "asan_interceptors.h" 18c99f70044d64482adbc1053f04b32bdbf0d4c057Evgeniy Stepanov#include "asan_mapping.h" 197354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov#include "asan_report.h" 20a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include "asan_stack.h" 21a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include "asan_thread_registry.h" 222221f553886c37401b5d84923634ebf04bc482f1Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common/sanitizer_procmaps.h" 24a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany 25cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany#include <pthread.h> 26a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include <signal.h> 27b823e3c5f7891dbbde1eb288237f5f3d5ed64d85Alexey Samsonov#include <stdlib.h> 28a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include <sys/time.h> 29a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include <sys/resource.h> 300ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany#include <unistd.h> 31a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany 323f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. 33f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko 34a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryanynamespace __asan { 35a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany 36a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryanystatic void MaybeInstallSigaction(int signum, 37a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany void (*handler)(int, siginfo_t *, void *)) { 38a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany if (!AsanInterceptsSignal(signum)) 39a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany return; 40a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany struct sigaction sigact; 4109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(memset)(&sigact, 0, sizeof(sigact)); 42a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany sigact.sa_sigaction = handler; 43a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany sigact.sa_flags = SA_SIGINFO; 44cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK; 4509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov CHECK(0 == REAL(sigaction)(signum, &sigact, 0)); 46cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 1) { 47a87bdaa1eab379ae4d9a24456f41f8ae36ba33f6Alexander Potapenko Report("Installed the sigaction for signal %d\n", signum); 48a87bdaa1eab379ae4d9a24456f41f8ae36ba33f6Alexander Potapenko } 49a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany} 50a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany 51a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryanystatic void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) { 523f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr addr = (uptr)siginfo->si_addr; 53a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany // Write the first message using the bullet-proof write. 5447657ce6cbac2fa93d0fd765c5d2872443b50e87Alexey Samsonov if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); 553f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr pc, sp, bp; 56a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany GetPcSpBp(context, &pc, &sp, &bp); 577354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov ReportSIGSEGV(pc, sp, bp, addr); 58a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany} 59a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany 60f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenkovoid SetAlternateSignalStack() { 61f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko stack_t altstack, oldstack; 623f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(0 == sigaltstack(0, &oldstack)); 63f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // If the alternate stack is already in place, do nothing. 64f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko if ((oldstack.ss_flags & SS_DISABLE) == 0) return; 65f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // TODO(glider): the mapped stack should have the MAP_STACK flag in the 66f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // future. It is not required by man 2 sigaltstack now (they're using 67f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // malloc()). 68a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov void* base = MmapOrDie(kAltStackSize, __FUNCTION__); 69f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko altstack.ss_sp = base; 70f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko altstack.ss_flags = 0; 71f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko altstack.ss_size = kAltStackSize; 723f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(0 == sigaltstack(&altstack, 0)); 73cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity > 0) { 74f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko Report("Alternative stack for T%d set: [%p,%p)\n", 75e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany asanThreadRegistry().GetCurrentTidOrInvalid(), 76f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size); 77f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko } 78f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko} 79f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko 80f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenkovoid UnsetAlternateSignalStack() { 81f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko stack_t altstack, oldstack; 823f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany altstack.ss_sp = 0; 83f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko altstack.ss_flags = SS_DISABLE; 84f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko altstack.ss_size = 0; 85f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko CHECK(0 == sigaltstack(&altstack, &oldstack)); 86a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov UnmapOrDie(oldstack.ss_sp, oldstack.ss_size); 87f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko} 88f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko 89a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryanyvoid InstallSignalHandlers() { 90f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // Set the alternate signal stack for the main thread. 91f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // This will cause SetAlternateSignalStack to be called twice, but the stack 92f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko // will be actually set only once. 93cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->use_sigaltstack) SetAlternateSignalStack(); 94a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV); 95a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV); 96a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany} 97a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany 98cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany// ---------------------- TSD ---------------- {{{1 99cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany 100cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryanystatic pthread_key_t tsd_key; 101cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryanystatic bool tsd_key_inited = false; 102f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryanyvoid AsanTSDInit(void (*destructor)(void *tsd)) { 103cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany CHECK(!tsd_key_inited); 104cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany tsd_key_inited = true; 105f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany CHECK(0 == pthread_key_create(&tsd_key, destructor)); 106cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany} 107cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany 108cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryanyvoid *AsanTSDGet() { 109cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany CHECK(tsd_key_inited); 110cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany return pthread_getspecific(tsd_key); 111cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany} 112cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany 113cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryanyvoid AsanTSDSet(void *tsd) { 114cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany CHECK(tsd_key_inited); 115cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany pthread_setspecific(tsd_key, tsd); 116cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany} 117cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany 118a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany} // namespace __asan 119a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany 120a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#endif // __linux__ || __APPLE_ 121