1*68d75effSDimitry Andric //===-- asan_posix.cpp ----------------------------------------------------===// 2*68d75effSDimitry Andric // 3*68d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*68d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*68d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*68d75effSDimitry Andric // 7*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 8*68d75effSDimitry Andric // 9*68d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 10*68d75effSDimitry Andric // 11*68d75effSDimitry Andric // Posix-specific details. 12*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 13*68d75effSDimitry Andric 14*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_platform.h" 15*68d75effSDimitry Andric #if SANITIZER_POSIX 16*68d75effSDimitry Andric 17*68d75effSDimitry Andric #include "asan_internal.h" 18*68d75effSDimitry Andric #include "asan_interceptors.h" 19*68d75effSDimitry Andric #include "asan_mapping.h" 20*68d75effSDimitry Andric #include "asan_report.h" 21*68d75effSDimitry Andric #include "asan_stack.h" 22*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 23*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_posix.h" 24*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_procmaps.h" 25*68d75effSDimitry Andric 26*68d75effSDimitry Andric #include <pthread.h> 27*68d75effSDimitry Andric #include <stdlib.h> 28*68d75effSDimitry Andric #include <sys/time.h> 29*68d75effSDimitry Andric #include <sys/resource.h> 30*68d75effSDimitry Andric #include <unistd.h> 31*68d75effSDimitry Andric 32*68d75effSDimitry Andric namespace __asan { 33*68d75effSDimitry Andric 34*68d75effSDimitry Andric void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { 35*68d75effSDimitry Andric StartReportDeadlySignal(); 36*68d75effSDimitry Andric SignalContext sig(siginfo, context); 37*68d75effSDimitry Andric ReportDeadlySignal(sig); 38*68d75effSDimitry Andric } 39*68d75effSDimitry Andric 40*68d75effSDimitry Andric // ---------------------- TSD ---------------- {{{1 41*68d75effSDimitry Andric 42*68d75effSDimitry Andric #if SANITIZER_NETBSD && !ASAN_DYNAMIC 43*68d75effSDimitry Andric // Thread Static Data cannot be used in early static ASan init on NetBSD. 44*68d75effSDimitry Andric // Reuse the Asan TSD API for compatibility with existing code 45*68d75effSDimitry Andric // with an alternative implementation. 46*68d75effSDimitry Andric 47*68d75effSDimitry Andric static void (*tsd_destructor)(void *tsd) = nullptr; 48*68d75effSDimitry Andric 49*68d75effSDimitry Andric struct tsd_key { 50*68d75effSDimitry Andric tsd_key() : key(nullptr) {} 51*68d75effSDimitry Andric ~tsd_key() { 52*68d75effSDimitry Andric CHECK(tsd_destructor); 53*68d75effSDimitry Andric if (key) 54*68d75effSDimitry Andric (*tsd_destructor)(key); 55*68d75effSDimitry Andric } 56*68d75effSDimitry Andric void *key; 57*68d75effSDimitry Andric }; 58*68d75effSDimitry Andric 59*68d75effSDimitry Andric static thread_local struct tsd_key key; 60*68d75effSDimitry Andric 61*68d75effSDimitry Andric void AsanTSDInit(void (*destructor)(void *tsd)) { 62*68d75effSDimitry Andric CHECK(!tsd_destructor); 63*68d75effSDimitry Andric tsd_destructor = destructor; 64*68d75effSDimitry Andric } 65*68d75effSDimitry Andric 66*68d75effSDimitry Andric void *AsanTSDGet() { 67*68d75effSDimitry Andric CHECK(tsd_destructor); 68*68d75effSDimitry Andric return key.key; 69*68d75effSDimitry Andric } 70*68d75effSDimitry Andric 71*68d75effSDimitry Andric void AsanTSDSet(void *tsd) { 72*68d75effSDimitry Andric CHECK(tsd_destructor); 73*68d75effSDimitry Andric CHECK(tsd); 74*68d75effSDimitry Andric CHECK(!key.key); 75*68d75effSDimitry Andric key.key = tsd; 76*68d75effSDimitry Andric } 77*68d75effSDimitry Andric 78*68d75effSDimitry Andric void PlatformTSDDtor(void *tsd) { 79*68d75effSDimitry Andric CHECK(tsd_destructor); 80*68d75effSDimitry Andric CHECK_EQ(key.key, tsd); 81*68d75effSDimitry Andric key.key = nullptr; 82*68d75effSDimitry Andric // Make sure that signal handler can not see a stale current thread pointer. 83*68d75effSDimitry Andric atomic_signal_fence(memory_order_seq_cst); 84*68d75effSDimitry Andric AsanThread::TSDDtor(tsd); 85*68d75effSDimitry Andric } 86*68d75effSDimitry Andric #else 87*68d75effSDimitry Andric static pthread_key_t tsd_key; 88*68d75effSDimitry Andric static bool tsd_key_inited = false; 89*68d75effSDimitry Andric void AsanTSDInit(void (*destructor)(void *tsd)) { 90*68d75effSDimitry Andric CHECK(!tsd_key_inited); 91*68d75effSDimitry Andric tsd_key_inited = true; 92*68d75effSDimitry Andric CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 93*68d75effSDimitry Andric } 94*68d75effSDimitry Andric 95*68d75effSDimitry Andric void *AsanTSDGet() { 96*68d75effSDimitry Andric CHECK(tsd_key_inited); 97*68d75effSDimitry Andric return pthread_getspecific(tsd_key); 98*68d75effSDimitry Andric } 99*68d75effSDimitry Andric 100*68d75effSDimitry Andric void AsanTSDSet(void *tsd) { 101*68d75effSDimitry Andric CHECK(tsd_key_inited); 102*68d75effSDimitry Andric pthread_setspecific(tsd_key, tsd); 103*68d75effSDimitry Andric } 104*68d75effSDimitry Andric 105*68d75effSDimitry Andric void PlatformTSDDtor(void *tsd) { 106*68d75effSDimitry Andric AsanThreadContext *context = (AsanThreadContext*)tsd; 107*68d75effSDimitry Andric if (context->destructor_iterations > 1) { 108*68d75effSDimitry Andric context->destructor_iterations--; 109*68d75effSDimitry Andric CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 110*68d75effSDimitry Andric return; 111*68d75effSDimitry Andric } 112*68d75effSDimitry Andric AsanThread::TSDDtor(tsd); 113*68d75effSDimitry Andric } 114*68d75effSDimitry Andric #endif 115*68d75effSDimitry Andric } // namespace __asan 116*68d75effSDimitry Andric 117*68d75effSDimitry Andric #endif // SANITIZER_POSIX 118