xref: /freebsd/contrib/llvm-project/compiler-rt/lib/asan/asan_posix.cpp (revision 68d75eff68281c1b445e3010bb975eae07aac225)
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