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 1781ad6265SDimitry Andric # include <pthread.h> 1881ad6265SDimitry Andric # include <signal.h> 1981ad6265SDimitry Andric # include <stdlib.h> 2081ad6265SDimitry Andric # include <sys/resource.h> 2181ad6265SDimitry Andric # include <sys/time.h> 2281ad6265SDimitry Andric # include <unistd.h> 2381ad6265SDimitry Andric 2468d75effSDimitry Andric # include "asan_interceptors.h" 2581ad6265SDimitry Andric # include "asan_internal.h" 2668d75effSDimitry Andric # include "asan_mapping.h" 275ffd83dbSDimitry Andric # include "asan_poisoning.h" 2868d75effSDimitry Andric # include "asan_report.h" 2968d75effSDimitry Andric # include "asan_stack.h" 3081ad6265SDimitry Andric # include "lsan/lsan_common.h" 3168d75effSDimitry Andric # include "sanitizer_common/sanitizer_libc.h" 3268d75effSDimitry Andric # include "sanitizer_common/sanitizer_posix.h" 3368d75effSDimitry Andric # include "sanitizer_common/sanitizer_procmaps.h" 3468d75effSDimitry Andric 3568d75effSDimitry Andric namespace __asan { 3668d75effSDimitry Andric 3768d75effSDimitry Andric void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { 3868d75effSDimitry Andric StartReportDeadlySignal(); 3968d75effSDimitry Andric SignalContext sig(siginfo, context); 4068d75effSDimitry Andric ReportDeadlySignal(sig); 4168d75effSDimitry Andric } 4268d75effSDimitry Andric 435ffd83dbSDimitry Andric bool PlatformUnpoisonStacks() { 445ffd83dbSDimitry Andric stack_t signal_stack; 455ffd83dbSDimitry Andric CHECK_EQ(0, sigaltstack(nullptr, &signal_stack)); 465ffd83dbSDimitry Andric uptr sigalt_bottom = (uptr)signal_stack.ss_sp; 475ffd83dbSDimitry Andric uptr sigalt_top = (uptr)((char *)signal_stack.ss_sp + signal_stack.ss_size); 485ffd83dbSDimitry Andric // If we're executing on the signal alternate stack AND the Linux flag 495ffd83dbSDimitry Andric // SS_AUTODISARM was used, then we cannot get the signal alternate stack 505ffd83dbSDimitry Andric // bounds from sigaltstack -- sigaltstack's output looks just as if no 515ffd83dbSDimitry Andric // alternate stack has ever been set up. 525ffd83dbSDimitry Andric // We're always unpoisoning the signal alternate stack to support jumping 535ffd83dbSDimitry Andric // between the default stack and signal alternate stack. 545ffd83dbSDimitry Andric if (signal_stack.ss_flags != SS_DISABLE) 555ffd83dbSDimitry Andric UnpoisonStack(sigalt_bottom, sigalt_top, "sigalt"); 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric if (signal_stack.ss_flags != SS_ONSTACK) 585ffd83dbSDimitry Andric return false; 595ffd83dbSDimitry Andric 60fe6060f1SDimitry Andric // Since we're on the signal alternate stack, we cannot find the DEFAULT 615ffd83dbSDimitry Andric // stack bottom using a local variable. 625ffd83dbSDimitry Andric uptr default_bottom, tls_addr, tls_size, stack_size; 635ffd83dbSDimitry Andric GetThreadStackAndTls(/*main=*/false, &default_bottom, &stack_size, &tls_addr, 645ffd83dbSDimitry Andric &tls_size); 655ffd83dbSDimitry Andric UnpoisonStack(default_bottom, default_bottom + stack_size, "default"); 665ffd83dbSDimitry Andric return true; 675ffd83dbSDimitry Andric } 685ffd83dbSDimitry Andric 6968d75effSDimitry Andric // ---------------------- TSD ---------------- {{{1 7068d75effSDimitry Andric 7168d75effSDimitry Andric #if SANITIZER_NETBSD && !ASAN_DYNAMIC 7268d75effSDimitry Andric // Thread Static Data cannot be used in early static ASan init on NetBSD. 7368d75effSDimitry Andric // Reuse the Asan TSD API for compatibility with existing code 7468d75effSDimitry Andric // with an alternative implementation. 7568d75effSDimitry Andric 7668d75effSDimitry Andric static void (*tsd_destructor)(void *tsd) = nullptr; 7768d75effSDimitry Andric 7868d75effSDimitry Andric struct tsd_key { 7968d75effSDimitry Andric tsd_key() : key(nullptr) {} 8068d75effSDimitry Andric ~tsd_key() { 8168d75effSDimitry Andric CHECK(tsd_destructor); 8268d75effSDimitry Andric if (key) 8368d75effSDimitry Andric (*tsd_destructor)(key); 8468d75effSDimitry Andric } 8568d75effSDimitry Andric void *key; 8668d75effSDimitry Andric }; 8768d75effSDimitry Andric 8868d75effSDimitry Andric static thread_local struct tsd_key key; 8968d75effSDimitry Andric 9068d75effSDimitry Andric void AsanTSDInit(void (*destructor)(void *tsd)) { 9168d75effSDimitry Andric CHECK(!tsd_destructor); 9268d75effSDimitry Andric tsd_destructor = destructor; 9368d75effSDimitry Andric } 9468d75effSDimitry Andric 9568d75effSDimitry Andric void *AsanTSDGet() { 9668d75effSDimitry Andric CHECK(tsd_destructor); 9768d75effSDimitry Andric return key.key; 9868d75effSDimitry Andric } 9968d75effSDimitry Andric 10068d75effSDimitry Andric void AsanTSDSet(void *tsd) { 10168d75effSDimitry Andric CHECK(tsd_destructor); 10268d75effSDimitry Andric CHECK(tsd); 10368d75effSDimitry Andric CHECK(!key.key); 10468d75effSDimitry Andric key.key = tsd; 10568d75effSDimitry Andric } 10668d75effSDimitry Andric 10768d75effSDimitry Andric void PlatformTSDDtor(void *tsd) { 10868d75effSDimitry Andric CHECK(tsd_destructor); 10968d75effSDimitry Andric CHECK_EQ(key.key, tsd); 11068d75effSDimitry Andric key.key = nullptr; 11168d75effSDimitry Andric // Make sure that signal handler can not see a stale current thread pointer. 11268d75effSDimitry Andric atomic_signal_fence(memory_order_seq_cst); 11368d75effSDimitry Andric AsanThread::TSDDtor(tsd); 11468d75effSDimitry Andric } 11568d75effSDimitry Andric #else 11668d75effSDimitry Andric static pthread_key_t tsd_key; 11768d75effSDimitry Andric static bool tsd_key_inited = false; 11868d75effSDimitry Andric void AsanTSDInit(void (*destructor)(void *tsd)) { 11968d75effSDimitry Andric CHECK(!tsd_key_inited); 12068d75effSDimitry Andric tsd_key_inited = true; 12168d75effSDimitry Andric CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 12268d75effSDimitry Andric } 12368d75effSDimitry Andric 12468d75effSDimitry Andric void *AsanTSDGet() { 12568d75effSDimitry Andric CHECK(tsd_key_inited); 12668d75effSDimitry Andric return pthread_getspecific(tsd_key); 12768d75effSDimitry Andric } 12868d75effSDimitry Andric 12968d75effSDimitry Andric void AsanTSDSet(void *tsd) { 13068d75effSDimitry Andric CHECK(tsd_key_inited); 13168d75effSDimitry Andric pthread_setspecific(tsd_key, tsd); 13268d75effSDimitry Andric } 13368d75effSDimitry Andric 13468d75effSDimitry Andric void PlatformTSDDtor(void *tsd) { 13568d75effSDimitry Andric AsanThreadContext *context = (AsanThreadContext *)tsd; 13668d75effSDimitry Andric if (context->destructor_iterations > 1) { 13768d75effSDimitry Andric context->destructor_iterations--; 13868d75effSDimitry Andric CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 13968d75effSDimitry Andric return; 14068d75effSDimitry Andric } 1415f757f3fSDimitry Andric # if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ 1425f757f3fSDimitry Andric SANITIZER_SOLARIS 1435f757f3fSDimitry Andric // After this point it's unsafe to execute signal handlers which may be 1445f757f3fSDimitry Andric // instrumented. It's probably not just a Linux issue. 1455f757f3fSDimitry Andric BlockSignals(); 1465f757f3fSDimitry Andric # endif 14768d75effSDimitry Andric AsanThread::TSDDtor(tsd); 14868d75effSDimitry Andric } 14968d75effSDimitry Andric # endif 15081ad6265SDimitry Andric 151*cb14a3feSDimitry Andric static void BeforeFork() { 1525f757f3fSDimitry Andric if (CAN_SANITIZE_LEAKS) { 1535f757f3fSDimitry Andric __lsan::LockGlobal(); 1545f757f3fSDimitry Andric } 1555f757f3fSDimitry Andric // `_lsan` functions defined regardless of `CAN_SANITIZE_LEAKS` and lock the 1565f757f3fSDimitry Andric // stuff we need. 1575f757f3fSDimitry Andric __lsan::LockThreads(); 1585f757f3fSDimitry Andric __lsan::LockAllocator(); 159*cb14a3feSDimitry Andric StackDepotLockBeforeFork(); 160*cb14a3feSDimitry Andric } 161*cb14a3feSDimitry Andric 162*cb14a3feSDimitry Andric static void AfterFork(bool fork_child) { 163*cb14a3feSDimitry Andric StackDepotUnlockAfterFork(fork_child); 1645f757f3fSDimitry Andric // `_lsan` functions defined regardless of `CAN_SANITIZE_LEAKS` and unlock 1655f757f3fSDimitry Andric // the stuff we need. 1665f757f3fSDimitry Andric __lsan::UnlockAllocator(); 1675f757f3fSDimitry Andric __lsan::UnlockThreads(); 1685f757f3fSDimitry Andric if (CAN_SANITIZE_LEAKS) { 1695f757f3fSDimitry Andric __lsan::UnlockGlobal(); 1705f757f3fSDimitry Andric } 171*cb14a3feSDimitry Andric } 172*cb14a3feSDimitry Andric 173*cb14a3feSDimitry Andric void InstallAtForkHandler() { 174*cb14a3feSDimitry Andric # if SANITIZER_SOLARIS || SANITIZER_NETBSD || SANITIZER_APPLE 175*cb14a3feSDimitry Andric return; // FIXME: Implement FutexWait. 176*cb14a3feSDimitry Andric # endif 177*cb14a3feSDimitry Andric pthread_atfork( 178*cb14a3feSDimitry Andric &BeforeFork, []() { AfterFork(/* fork_child= */ false); }, 179*cb14a3feSDimitry Andric []() { AfterFork(/* fork_child= */ true); }); 1805f757f3fSDimitry Andric } 1815f757f3fSDimitry Andric 18281ad6265SDimitry Andric void InstallAtExitCheckLeaks() { 18381ad6265SDimitry Andric if (CAN_SANITIZE_LEAKS) { 18481ad6265SDimitry Andric if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { 18581ad6265SDimitry Andric if (flags()->halt_on_error) 18681ad6265SDimitry Andric Atexit(__lsan::DoLeakCheck); 18781ad6265SDimitry Andric else 18881ad6265SDimitry Andric Atexit(__lsan::DoRecoverableLeakCheckVoid); 18981ad6265SDimitry Andric } 19081ad6265SDimitry Andric } 19181ad6265SDimitry Andric } 19281ad6265SDimitry Andric 19368d75effSDimitry Andric } // namespace __asan 19468d75effSDimitry Andric 19568d75effSDimitry Andric #endif // SANITIZER_POSIX 196