168d75effSDimitry Andric //===-- asan_posix.cpp ----------------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // Posix-specific details. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "sanitizer_common/sanitizer_platform.h" 1568d75effSDimitry Andric #if SANITIZER_POSIX 1668d75effSDimitry Andric 1768d75effSDimitry Andric #include "asan_internal.h" 1868d75effSDimitry Andric #include "asan_interceptors.h" 1968d75effSDimitry Andric #include "asan_mapping.h" 20*5ffd83dbSDimitry Andric #include "asan_poisoning.h" 2168d75effSDimitry Andric #include "asan_report.h" 2268d75effSDimitry Andric #include "asan_stack.h" 2368d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 2468d75effSDimitry Andric #include "sanitizer_common/sanitizer_posix.h" 2568d75effSDimitry Andric #include "sanitizer_common/sanitizer_procmaps.h" 2668d75effSDimitry Andric 2768d75effSDimitry Andric #include <pthread.h> 28*5ffd83dbSDimitry Andric #include <signal.h> 2968d75effSDimitry Andric #include <stdlib.h> 3068d75effSDimitry Andric #include <sys/time.h> 3168d75effSDimitry Andric #include <sys/resource.h> 3268d75effSDimitry Andric #include <unistd.h> 3368d75effSDimitry Andric 3468d75effSDimitry Andric namespace __asan { 3568d75effSDimitry Andric 3668d75effSDimitry Andric void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { 3768d75effSDimitry Andric StartReportDeadlySignal(); 3868d75effSDimitry Andric SignalContext sig(siginfo, context); 3968d75effSDimitry Andric ReportDeadlySignal(sig); 4068d75effSDimitry Andric } 4168d75effSDimitry Andric 42*5ffd83dbSDimitry Andric bool PlatformUnpoisonStacks() { 43*5ffd83dbSDimitry Andric stack_t signal_stack; 44*5ffd83dbSDimitry Andric CHECK_EQ(0, sigaltstack(nullptr, &signal_stack)); 45*5ffd83dbSDimitry Andric uptr sigalt_bottom = (uptr)signal_stack.ss_sp; 46*5ffd83dbSDimitry Andric uptr sigalt_top = (uptr)((char *)signal_stack.ss_sp + signal_stack.ss_size); 47*5ffd83dbSDimitry Andric // If we're executing on the signal alternate stack AND the Linux flag 48*5ffd83dbSDimitry Andric // SS_AUTODISARM was used, then we cannot get the signal alternate stack 49*5ffd83dbSDimitry Andric // bounds from sigaltstack -- sigaltstack's output looks just as if no 50*5ffd83dbSDimitry Andric // alternate stack has ever been set up. 51*5ffd83dbSDimitry Andric // We're always unpoisoning the signal alternate stack to support jumping 52*5ffd83dbSDimitry Andric // between the default stack and signal alternate stack. 53*5ffd83dbSDimitry Andric if (signal_stack.ss_flags != SS_DISABLE) 54*5ffd83dbSDimitry Andric UnpoisonStack(sigalt_bottom, sigalt_top, "sigalt"); 55*5ffd83dbSDimitry Andric 56*5ffd83dbSDimitry Andric if (signal_stack.ss_flags != SS_ONSTACK) 57*5ffd83dbSDimitry Andric return false; 58*5ffd83dbSDimitry Andric 59*5ffd83dbSDimitry Andric // Since we're on the signal altnerate stack, we cannot find the DEFAULT 60*5ffd83dbSDimitry Andric // stack bottom using a local variable. 61*5ffd83dbSDimitry Andric uptr default_bottom, tls_addr, tls_size, stack_size; 62*5ffd83dbSDimitry Andric GetThreadStackAndTls(/*main=*/false, &default_bottom, &stack_size, &tls_addr, 63*5ffd83dbSDimitry Andric &tls_size); 64*5ffd83dbSDimitry Andric UnpoisonStack(default_bottom, default_bottom + stack_size, "default"); 65*5ffd83dbSDimitry Andric return true; 66*5ffd83dbSDimitry Andric } 67*5ffd83dbSDimitry Andric 6868d75effSDimitry Andric // ---------------------- TSD ---------------- {{{1 6968d75effSDimitry Andric 7068d75effSDimitry Andric #if SANITIZER_NETBSD && !ASAN_DYNAMIC 7168d75effSDimitry Andric // Thread Static Data cannot be used in early static ASan init on NetBSD. 7268d75effSDimitry Andric // Reuse the Asan TSD API for compatibility with existing code 7368d75effSDimitry Andric // with an alternative implementation. 7468d75effSDimitry Andric 7568d75effSDimitry Andric static void (*tsd_destructor)(void *tsd) = nullptr; 7668d75effSDimitry Andric 7768d75effSDimitry Andric struct tsd_key { 7868d75effSDimitry Andric tsd_key() : key(nullptr) {} 7968d75effSDimitry Andric ~tsd_key() { 8068d75effSDimitry Andric CHECK(tsd_destructor); 8168d75effSDimitry Andric if (key) 8268d75effSDimitry Andric (*tsd_destructor)(key); 8368d75effSDimitry Andric } 8468d75effSDimitry Andric void *key; 8568d75effSDimitry Andric }; 8668d75effSDimitry Andric 8768d75effSDimitry Andric static thread_local struct tsd_key key; 8868d75effSDimitry Andric 8968d75effSDimitry Andric void AsanTSDInit(void (*destructor)(void *tsd)) { 9068d75effSDimitry Andric CHECK(!tsd_destructor); 9168d75effSDimitry Andric tsd_destructor = destructor; 9268d75effSDimitry Andric } 9368d75effSDimitry Andric 9468d75effSDimitry Andric void *AsanTSDGet() { 9568d75effSDimitry Andric CHECK(tsd_destructor); 9668d75effSDimitry Andric return key.key; 9768d75effSDimitry Andric } 9868d75effSDimitry Andric 9968d75effSDimitry Andric void AsanTSDSet(void *tsd) { 10068d75effSDimitry Andric CHECK(tsd_destructor); 10168d75effSDimitry Andric CHECK(tsd); 10268d75effSDimitry Andric CHECK(!key.key); 10368d75effSDimitry Andric key.key = tsd; 10468d75effSDimitry Andric } 10568d75effSDimitry Andric 10668d75effSDimitry Andric void PlatformTSDDtor(void *tsd) { 10768d75effSDimitry Andric CHECK(tsd_destructor); 10868d75effSDimitry Andric CHECK_EQ(key.key, tsd); 10968d75effSDimitry Andric key.key = nullptr; 11068d75effSDimitry Andric // Make sure that signal handler can not see a stale current thread pointer. 11168d75effSDimitry Andric atomic_signal_fence(memory_order_seq_cst); 11268d75effSDimitry Andric AsanThread::TSDDtor(tsd); 11368d75effSDimitry Andric } 11468d75effSDimitry Andric #else 11568d75effSDimitry Andric static pthread_key_t tsd_key; 11668d75effSDimitry Andric static bool tsd_key_inited = false; 11768d75effSDimitry Andric void AsanTSDInit(void (*destructor)(void *tsd)) { 11868d75effSDimitry Andric CHECK(!tsd_key_inited); 11968d75effSDimitry Andric tsd_key_inited = true; 12068d75effSDimitry Andric CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 12168d75effSDimitry Andric } 12268d75effSDimitry Andric 12368d75effSDimitry Andric void *AsanTSDGet() { 12468d75effSDimitry Andric CHECK(tsd_key_inited); 12568d75effSDimitry Andric return pthread_getspecific(tsd_key); 12668d75effSDimitry Andric } 12768d75effSDimitry Andric 12868d75effSDimitry Andric void AsanTSDSet(void *tsd) { 12968d75effSDimitry Andric CHECK(tsd_key_inited); 13068d75effSDimitry Andric pthread_setspecific(tsd_key, tsd); 13168d75effSDimitry Andric } 13268d75effSDimitry Andric 13368d75effSDimitry Andric void PlatformTSDDtor(void *tsd) { 13468d75effSDimitry Andric AsanThreadContext *context = (AsanThreadContext*)tsd; 13568d75effSDimitry Andric if (context->destructor_iterations > 1) { 13668d75effSDimitry Andric context->destructor_iterations--; 13768d75effSDimitry Andric CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 13868d75effSDimitry Andric return; 13968d75effSDimitry Andric } 14068d75effSDimitry Andric AsanThread::TSDDtor(tsd); 14168d75effSDimitry Andric } 14268d75effSDimitry Andric #endif 14368d75effSDimitry Andric } // namespace __asan 14468d75effSDimitry Andric 14568d75effSDimitry Andric #endif // SANITIZER_POSIX 146