Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/asan/asan_posix.cpp
35233 views
1
//===-- asan_posix.cpp ----------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file is a part of AddressSanitizer, an address sanity checker.
10
//
11
// Posix-specific details.
12
//===----------------------------------------------------------------------===//
13
14
#include "sanitizer_common/sanitizer_platform.h"
15
#if SANITIZER_POSIX
16
17
# include <pthread.h>
18
# include <signal.h>
19
# include <stdlib.h>
20
# include <sys/resource.h>
21
# include <sys/time.h>
22
# include <unistd.h>
23
24
# include "asan_interceptors.h"
25
# include "asan_internal.h"
26
# include "asan_mapping.h"
27
# include "asan_poisoning.h"
28
# include "asan_report.h"
29
# include "asan_stack.h"
30
# include "lsan/lsan_common.h"
31
# include "sanitizer_common/sanitizer_libc.h"
32
# include "sanitizer_common/sanitizer_posix.h"
33
# include "sanitizer_common/sanitizer_procmaps.h"
34
35
namespace __asan {
36
37
void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
38
StartReportDeadlySignal();
39
SignalContext sig(siginfo, context);
40
ReportDeadlySignal(sig);
41
}
42
43
bool PlatformUnpoisonStacks() {
44
stack_t signal_stack;
45
CHECK_EQ(0, sigaltstack(nullptr, &signal_stack));
46
uptr sigalt_bottom = (uptr)signal_stack.ss_sp;
47
uptr sigalt_top = (uptr)((char *)signal_stack.ss_sp + signal_stack.ss_size);
48
// If we're executing on the signal alternate stack AND the Linux flag
49
// SS_AUTODISARM was used, then we cannot get the signal alternate stack
50
// bounds from sigaltstack -- sigaltstack's output looks just as if no
51
// alternate stack has ever been set up.
52
// We're always unpoisoning the signal alternate stack to support jumping
53
// between the default stack and signal alternate stack.
54
if (signal_stack.ss_flags != SS_DISABLE)
55
UnpoisonStack(sigalt_bottom, sigalt_top, "sigalt");
56
57
if (signal_stack.ss_flags != SS_ONSTACK)
58
return false;
59
60
// Since we're on the signal alternate stack, we cannot find the DEFAULT
61
// stack bottom using a local variable.
62
uptr default_bottom, tls_addr, tls_size, stack_size;
63
GetThreadStackAndTls(/*main=*/false, &default_bottom, &stack_size, &tls_addr,
64
&tls_size);
65
UnpoisonStack(default_bottom, default_bottom + stack_size, "default");
66
return true;
67
}
68
69
// ---------------------- TSD ---------------- {{{1
70
71
#if SANITIZER_NETBSD && !ASAN_DYNAMIC
72
// Thread Static Data cannot be used in early static ASan init on NetBSD.
73
// Reuse the Asan TSD API for compatibility with existing code
74
// with an alternative implementation.
75
76
static void (*tsd_destructor)(void *tsd) = nullptr;
77
78
struct tsd_key {
79
tsd_key() : key(nullptr) {}
80
~tsd_key() {
81
CHECK(tsd_destructor);
82
if (key)
83
(*tsd_destructor)(key);
84
}
85
void *key;
86
};
87
88
static thread_local struct tsd_key key;
89
90
void AsanTSDInit(void (*destructor)(void *tsd)) {
91
CHECK(!tsd_destructor);
92
tsd_destructor = destructor;
93
}
94
95
void *AsanTSDGet() {
96
CHECK(tsd_destructor);
97
return key.key;
98
}
99
100
void AsanTSDSet(void *tsd) {
101
CHECK(tsd_destructor);
102
CHECK(tsd);
103
CHECK(!key.key);
104
key.key = tsd;
105
}
106
107
void PlatformTSDDtor(void *tsd) {
108
CHECK(tsd_destructor);
109
CHECK_EQ(key.key, tsd);
110
key.key = nullptr;
111
// Make sure that signal handler can not see a stale current thread pointer.
112
atomic_signal_fence(memory_order_seq_cst);
113
AsanThread::TSDDtor(tsd);
114
}
115
#else
116
static pthread_key_t tsd_key;
117
static bool tsd_key_inited = false;
118
void AsanTSDInit(void (*destructor)(void *tsd)) {
119
CHECK(!tsd_key_inited);
120
tsd_key_inited = true;
121
CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
122
}
123
124
void *AsanTSDGet() {
125
CHECK(tsd_key_inited);
126
return pthread_getspecific(tsd_key);
127
}
128
129
void AsanTSDSet(void *tsd) {
130
CHECK(tsd_key_inited);
131
pthread_setspecific(tsd_key, tsd);
132
}
133
134
void PlatformTSDDtor(void *tsd) {
135
AsanThreadContext *context = (AsanThreadContext *)tsd;
136
if (context->destructor_iterations > 1) {
137
context->destructor_iterations--;
138
CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
139
return;
140
}
141
# if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
142
SANITIZER_SOLARIS
143
// After this point it's unsafe to execute signal handlers which may be
144
// instrumented. It's probably not just a Linux issue.
145
BlockSignals();
146
# endif
147
AsanThread::TSDDtor(tsd);
148
}
149
# endif
150
151
static void BeforeFork() {
152
if (CAN_SANITIZE_LEAKS) {
153
__lsan::LockGlobal();
154
}
155
// `_lsan` functions defined regardless of `CAN_SANITIZE_LEAKS` and lock the
156
// stuff we need.
157
__lsan::LockThreads();
158
__lsan::LockAllocator();
159
StackDepotLockBeforeFork();
160
}
161
162
static void AfterFork(bool fork_child) {
163
StackDepotUnlockAfterFork(fork_child);
164
// `_lsan` functions defined regardless of `CAN_SANITIZE_LEAKS` and unlock
165
// the stuff we need.
166
__lsan::UnlockAllocator();
167
__lsan::UnlockThreads();
168
if (CAN_SANITIZE_LEAKS) {
169
__lsan::UnlockGlobal();
170
}
171
}
172
173
void InstallAtForkHandler() {
174
# if SANITIZER_SOLARIS || SANITIZER_NETBSD || SANITIZER_APPLE
175
return; // FIXME: Implement FutexWait.
176
# endif
177
pthread_atfork(
178
&BeforeFork, []() { AfterFork(/* fork_child= */ false); },
179
[]() { AfterFork(/* fork_child= */ true); });
180
}
181
182
void InstallAtExitCheckLeaks() {
183
if (CAN_SANITIZE_LEAKS) {
184
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
185
if (flags()->halt_on_error)
186
Atexit(__lsan::DoLeakCheck);
187
else
188
Atexit(__lsan::DoRecoverableLeakCheckVoid);
189
}
190
}
191
}
192
193
} // namespace __asan
194
195
#endif // SANITIZER_POSIX
196
197