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_interceptors.cpp
35233 views
1
//===-- asan_interceptors.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
// Intercept various libc functions.
12
//===----------------------------------------------------------------------===//
13
14
#include "asan_interceptors.h"
15
16
#include "asan_allocator.h"
17
#include "asan_internal.h"
18
#include "asan_mapping.h"
19
#include "asan_poisoning.h"
20
#include "asan_report.h"
21
#include "asan_stack.h"
22
#include "asan_stats.h"
23
#include "asan_suppressions.h"
24
#include "asan_thread.h"
25
#include "lsan/lsan_common.h"
26
#include "sanitizer_common/sanitizer_errno.h"
27
#include "sanitizer_common/sanitizer_internal_defs.h"
28
#include "sanitizer_common/sanitizer_libc.h"
29
30
// There is no general interception at all on Fuchsia.
31
// Only the functions in asan_interceptors_memintrinsics.cpp are
32
// really defined to replace libc functions.
33
#if !SANITIZER_FUCHSIA
34
35
# if SANITIZER_POSIX
36
# include "sanitizer_common/sanitizer_posix.h"
37
# endif
38
39
# if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
40
ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
41
# include <unwind.h>
42
# endif
43
44
# if defined(__i386) && SANITIZER_LINUX
45
# define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
46
# elif defined(__mips__) && SANITIZER_LINUX
47
# define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
48
# endif
49
50
namespace __asan {
51
52
#define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
53
ASAN_READ_RANGE((ctx), (s), \
54
common_flags()->strict_string_checks ? (len) + 1 : (n))
55
56
# define ASAN_READ_STRING(ctx, s, n) \
57
ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n))
58
59
static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
60
#if SANITIZER_INTERCEPT_STRNLEN
61
if (REAL(strnlen)) {
62
return REAL(strnlen)(s, maxlen);
63
}
64
#endif
65
return internal_strnlen(s, maxlen);
66
}
67
68
void SetThreadName(const char *name) {
69
AsanThread *t = GetCurrentThread();
70
if (t)
71
asanThreadRegistry().SetThreadName(t->tid(), name);
72
}
73
74
int OnExit() {
75
if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
76
__lsan::HasReportedLeaks()) {
77
return common_flags()->exitcode;
78
}
79
// FIXME: ask frontend whether we need to return failure.
80
return 0;
81
}
82
83
} // namespace __asan
84
85
// ---------------------- Wrappers ---------------- {{{1
86
using namespace __asan;
87
88
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
89
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
90
91
#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
92
ASAN_INTERCEPT_FUNC_VER(name, ver)
93
#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
94
ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
95
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
96
ASAN_WRITE_RANGE(ctx, ptr, size)
97
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
98
ASAN_READ_RANGE(ctx, ptr, size)
99
# define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
100
ASAN_INTERCEPTOR_ENTER(ctx, func); \
101
do { \
102
if constexpr (SANITIZER_APPLE) { \
103
if (UNLIKELY(!AsanInited())) \
104
return REAL(func)(__VA_ARGS__); \
105
} else { \
106
if (!TryAsanInitFromRtl()) \
107
return REAL(func)(__VA_ARGS__); \
108
} \
109
} while (false)
110
#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
111
do { \
112
} while (false)
113
#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
114
do { \
115
} while (false)
116
#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
117
do { \
118
} while (false)
119
#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
120
do { \
121
} while (false)
122
#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
123
// Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
124
// But asan does not remember UserId's for threads (pthread_t);
125
// and remembers all ever existed threads, so the linear search by UserId
126
// can be slow.
127
#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
128
do { \
129
} while (false)
130
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
131
// Strict init-order checking is dlopen-hostile:
132
// https://github.com/google/sanitizers/issues/178
133
# define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
134
({ \
135
if (flags()->strict_init_order) \
136
StopInitOrderChecking(); \
137
CheckNoDeepBind(filename, flag); \
138
REAL(dlopen)(filename, flag); \
139
})
140
# define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
141
# define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
142
# define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
143
# define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!AsanInited())
144
# define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
145
if (AsanThread *t = GetCurrentThread()) { \
146
*begin = t->tls_begin(); \
147
*end = t->tls_end(); \
148
} else { \
149
*begin = *end = 0; \
150
}
151
152
template <class Mmap>
153
static void* mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
154
int prot, int flags, int fd, OFF64_T offset) {
155
void *res = real_mmap(addr, length, prot, flags, fd, offset);
156
if (length && res != (void *)-1) {
157
const uptr beg = reinterpret_cast<uptr>(res);
158
DCHECK(IsAligned(beg, GetPageSize()));
159
SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
160
// Only unpoison shadow if it's an ASAN managed address.
161
if (AddrIsInMem(beg) && AddrIsInMem(beg + rounded_length - 1))
162
PoisonShadow(beg, RoundUpTo(length, GetPageSize()), 0);
163
}
164
return res;
165
}
166
167
template <class Munmap>
168
static int munmap_interceptor(Munmap real_munmap, void *addr, SIZE_T length) {
169
// We should not tag if munmap fail, but it's to late to tag after
170
// real_munmap, as the pages could be mmaped by another thread.
171
const uptr beg = reinterpret_cast<uptr>(addr);
172
if (length && IsAligned(beg, GetPageSize())) {
173
SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
174
// Protect from unmapping the shadow.
175
if (AddrIsInMem(beg) && AddrIsInMem(beg + rounded_length - 1))
176
PoisonShadow(beg, rounded_length, 0);
177
}
178
return real_munmap(addr, length);
179
}
180
181
# define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \
182
fd, offset) \
183
do { \
184
(void)(ctx); \
185
return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
186
} while (false)
187
188
# define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length) \
189
do { \
190
(void)(ctx); \
191
return munmap_interceptor(REAL(munmap), addr, sz); \
192
} while (false)
193
194
#if CAN_SANITIZE_LEAKS
195
#define COMMON_INTERCEPTOR_STRERROR() \
196
__lsan::ScopedInterceptorDisabler disabler
197
#endif
198
199
# define SIGNAL_INTERCEPTOR_ENTER() \
200
do { \
201
AsanInitFromRtl(); \
202
} while (false)
203
204
# include "sanitizer_common/sanitizer_common_interceptors.inc"
205
# include "sanitizer_common/sanitizer_signal_interceptors.inc"
206
207
// Syscall interceptors don't have contexts, we don't support suppressions
208
// for them.
209
#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
210
#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
211
#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
212
do { \
213
(void)(p); \
214
(void)(s); \
215
} while (false)
216
#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
217
do { \
218
(void)(p); \
219
(void)(s); \
220
} while (false)
221
#include "sanitizer_common/sanitizer_common_syscalls.inc"
222
#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
223
224
#if ASAN_INTERCEPT_PTHREAD_CREATE
225
static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
226
AsanThread *t = (AsanThread *)arg;
227
SetCurrentThread(t);
228
auto self = GetThreadSelf();
229
auto args = asanThreadArgRetval().GetArgs(self);
230
t->ThreadStart(GetTid());
231
232
# if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
233
SANITIZER_SOLARIS
234
__sanitizer_sigset_t sigset;
235
t->GetStartData(sigset);
236
SetSigProcMask(&sigset, nullptr);
237
# endif
238
239
thread_return_t retval = (*args.routine)(args.arg_retval);
240
asanThreadArgRetval().Finish(self, retval);
241
return retval;
242
}
243
244
INTERCEPTOR(int, pthread_create, void *thread, void *attr,
245
void *(*start_routine)(void *), void *arg) {
246
EnsureMainThreadIDIsCorrect();
247
// Strict init-order checking is thread-hostile.
248
if (flags()->strict_init_order)
249
StopInitOrderChecking();
250
GET_STACK_TRACE_THREAD;
251
bool detached = [attr]() {
252
int d = 0;
253
return attr && !REAL(pthread_attr_getdetachstate)(attr, &d) &&
254
IsStateDetached(d);
255
}();
256
257
u32 current_tid = GetCurrentTidOrInvalid();
258
259
__sanitizer_sigset_t sigset = {};
260
# if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
261
SANITIZER_SOLARIS
262
ScopedBlockSignals block(&sigset);
263
# endif
264
265
AsanThread *t = AsanThread::Create(sigset, current_tid, &stack, detached);
266
267
int result;
268
{
269
// Ignore all allocations made by pthread_create: thread stack/TLS may be
270
// stored by pthread for future reuse even after thread destruction, and
271
// the linked list it's stored in doesn't even hold valid pointers to the
272
// objects, the latter are calculated by obscure pointer arithmetic.
273
# if CAN_SANITIZE_LEAKS
274
__lsan::ScopedInterceptorDisabler disabler;
275
# endif
276
asanThreadArgRetval().Create(detached, {start_routine, arg}, [&]() -> uptr {
277
result = REAL(pthread_create)(thread, attr, asan_thread_start, t);
278
return result ? 0 : *(uptr *)(thread);
279
});
280
}
281
if (result != 0) {
282
// If the thread didn't start delete the AsanThread to avoid leaking it.
283
// Note AsanThreadContexts never get destroyed so the AsanThreadContext
284
// that was just created for the AsanThread is wasted.
285
t->Destroy();
286
}
287
return result;
288
}
289
290
INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
291
int result;
292
asanThreadArgRetval().Join((uptr)thread, [&]() {
293
result = REAL(pthread_join)(thread, retval);
294
return !result;
295
});
296
return result;
297
}
298
299
INTERCEPTOR(int, pthread_detach, void *thread) {
300
int result;
301
asanThreadArgRetval().Detach((uptr)thread, [&]() {
302
result = REAL(pthread_detach)(thread);
303
return !result;
304
});
305
return result;
306
}
307
308
INTERCEPTOR(void, pthread_exit, void *retval) {
309
asanThreadArgRetval().Finish(GetThreadSelf(), retval);
310
REAL(pthread_exit)(retval);
311
}
312
313
# if ASAN_INTERCEPT_TRYJOIN
314
INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) {
315
int result;
316
asanThreadArgRetval().Join((uptr)thread, [&]() {
317
result = REAL(pthread_tryjoin_np)(thread, ret);
318
return !result;
319
});
320
return result;
321
}
322
# endif
323
324
# if ASAN_INTERCEPT_TIMEDJOIN
325
INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret,
326
const struct timespec *abstime) {
327
int result;
328
asanThreadArgRetval().Join((uptr)thread, [&]() {
329
result = REAL(pthread_timedjoin_np)(thread, ret, abstime);
330
return !result;
331
});
332
return result;
333
}
334
# endif
335
336
DEFINE_INTERNAL_PTHREAD_FUNCTIONS
337
#endif // ASAN_INTERCEPT_PTHREAD_CREATE
338
339
#if ASAN_INTERCEPT_SWAPCONTEXT
340
static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
341
// Only clear if we know the stack. This should be true only for contexts
342
// created with makecontext().
343
if (!ssize)
344
return;
345
// Align to page size.
346
uptr PageSize = GetPageSizeCached();
347
uptr bottom = RoundDownTo(stack, PageSize);
348
if (!AddrIsInMem(bottom))
349
return;
350
ssize += stack - bottom;
351
ssize = RoundUpTo(ssize, PageSize);
352
PoisonShadow(bottom, ssize, 0);
353
}
354
355
// Since Solaris 10/SPARC, ucp->uc_stack.ss_sp refers to the stack base address
356
// as on other targets. For binary compatibility, the new version uses a
357
// different external name, so we intercept that.
358
# if SANITIZER_SOLARIS && defined(__sparc__)
359
INTERCEPTOR(void, __makecontext_v2, struct ucontext_t *ucp, void (*func)(),
360
int argc, ...) {
361
# else
362
INTERCEPTOR(void, makecontext, struct ucontext_t *ucp, void (*func)(), int argc,
363
...) {
364
# endif
365
va_list ap;
366
uptr args[64];
367
// We don't know a better way to forward ... into REAL function. We can
368
// increase args size if neccecary.
369
CHECK_LE(argc, ARRAY_SIZE(args));
370
internal_memset(args, 0, sizeof(args));
371
va_start(ap, argc);
372
for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr);
373
va_end(ap);
374
375
# define ENUMERATE_ARRAY_4(start) \
376
args[start], args[start + 1], args[start + 2], args[start + 3]
377
# define ENUMERATE_ARRAY_16(start) \
378
ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
379
ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
380
# define ENUMERATE_ARRAY_64() \
381
ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
382
ENUMERATE_ARRAY_16(48)
383
384
# if SANITIZER_SOLARIS && defined(__sparc__)
385
REAL(__makecontext_v2)
386
# else
387
REAL(makecontext)
388
# endif
389
((struct ucontext_t *)ucp, func, argc, ENUMERATE_ARRAY_64());
390
391
# undef ENUMERATE_ARRAY_4
392
# undef ENUMERATE_ARRAY_16
393
# undef ENUMERATE_ARRAY_64
394
395
// Sign the stack so we can identify it for unpoisoning.
396
SignContextStack(ucp);
397
}
398
399
INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
400
struct ucontext_t *ucp) {
401
static bool reported_warning = false;
402
if (!reported_warning) {
403
Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
404
"functions and may produce false positives in some cases!\n");
405
reported_warning = true;
406
}
407
// Clear shadow memory for new context (it may share stack
408
// with current context).
409
uptr stack, ssize;
410
ReadContextStack(ucp, &stack, &ssize);
411
ClearShadowMemoryForContextStack(stack, ssize);
412
413
# if __has_attribute(__indirect_return__) && \
414
(defined(__x86_64__) || defined(__i386__))
415
int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
416
__attribute__((__indirect_return__)) = REAL(swapcontext);
417
int res = real_swapcontext(oucp, ucp);
418
# else
419
int res = REAL(swapcontext)(oucp, ucp);
420
# endif
421
// swapcontext technically does not return, but program may swap context to
422
// "oucp" later, that would look as if swapcontext() returned 0.
423
// We need to clear shadow for ucp once again, as it may be in arbitrary
424
// state.
425
ClearShadowMemoryForContextStack(stack, ssize);
426
return res;
427
}
428
#endif // ASAN_INTERCEPT_SWAPCONTEXT
429
430
#if SANITIZER_NETBSD
431
#define longjmp __longjmp14
432
#define siglongjmp __siglongjmp14
433
#endif
434
435
INTERCEPTOR(void, longjmp, void *env, int val) {
436
__asan_handle_no_return();
437
REAL(longjmp)(env, val);
438
}
439
440
#if ASAN_INTERCEPT__LONGJMP
441
INTERCEPTOR(void, _longjmp, void *env, int val) {
442
__asan_handle_no_return();
443
REAL(_longjmp)(env, val);
444
}
445
#endif
446
447
#if ASAN_INTERCEPT___LONGJMP_CHK
448
INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
449
__asan_handle_no_return();
450
REAL(__longjmp_chk)(env, val);
451
}
452
#endif
453
454
#if ASAN_INTERCEPT_SIGLONGJMP
455
INTERCEPTOR(void, siglongjmp, void *env, int val) {
456
__asan_handle_no_return();
457
REAL(siglongjmp)(env, val);
458
}
459
#endif
460
461
#if ASAN_INTERCEPT___CXA_THROW
462
INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
463
CHECK(REAL(__cxa_throw));
464
__asan_handle_no_return();
465
REAL(__cxa_throw)(a, b, c);
466
}
467
#endif
468
469
#if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
470
INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
471
CHECK(REAL(__cxa_rethrow_primary_exception));
472
__asan_handle_no_return();
473
REAL(__cxa_rethrow_primary_exception)(a);
474
}
475
#endif
476
477
#if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
478
INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
479
_Unwind_Exception *object) {
480
CHECK(REAL(_Unwind_RaiseException));
481
__asan_handle_no_return();
482
return REAL(_Unwind_RaiseException)(object);
483
}
484
#endif
485
486
#if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
487
INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
488
_Unwind_Exception *object) {
489
CHECK(REAL(_Unwind_SjLj_RaiseException));
490
__asan_handle_no_return();
491
return REAL(_Unwind_SjLj_RaiseException)(object);
492
}
493
#endif
494
495
#if ASAN_INTERCEPT_INDEX
496
# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
497
INTERCEPTOR(char*, index, const char *string, int c)
498
ALIAS(WRAP(strchr));
499
# else
500
# if SANITIZER_APPLE
501
DECLARE_REAL(char*, index, const char *string, int c)
502
OVERRIDE_FUNCTION(index, strchr);
503
# else
504
DEFINE_REAL(char*, index, const char *string, int c)
505
# endif
506
# endif
507
#endif // ASAN_INTERCEPT_INDEX
508
509
// For both strcat() and strncat() we need to check the validity of |to|
510
// argument irrespective of the |from| length.
511
INTERCEPTOR(char *, strcat, char *to, const char *from) {
512
void *ctx;
513
ASAN_INTERCEPTOR_ENTER(ctx, strcat);
514
AsanInitFromRtl();
515
if (flags()->replace_str) {
516
uptr from_length = internal_strlen(from);
517
ASAN_READ_RANGE(ctx, from, from_length + 1);
518
uptr to_length = internal_strlen(to);
519
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
520
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
521
// If the copying actually happens, the |from| string should not overlap
522
// with the resulting string starting at |to|, which has a length of
523
// to_length + from_length + 1.
524
if (from_length > 0) {
525
CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
526
from_length + 1);
527
}
528
}
529
return REAL(strcat)(to, from);
530
}
531
532
INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
533
void *ctx;
534
ASAN_INTERCEPTOR_ENTER(ctx, strncat);
535
AsanInitFromRtl();
536
if (flags()->replace_str) {
537
uptr from_length = MaybeRealStrnlen(from, size);
538
uptr copy_length = Min(size, from_length + 1);
539
ASAN_READ_RANGE(ctx, from, copy_length);
540
uptr to_length = internal_strlen(to);
541
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
542
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
543
if (from_length > 0) {
544
CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
545
from, copy_length);
546
}
547
}
548
return REAL(strncat)(to, from, size);
549
}
550
551
INTERCEPTOR(char *, strcpy, char *to, const char *from) {
552
void *ctx;
553
ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
554
if constexpr (SANITIZER_APPLE) {
555
// strcpy is called from malloc_default_purgeable_zone()
556
// in __asan::ReplaceSystemAlloc() on Mac.
557
if (UNLIKELY(!AsanInited()))
558
return REAL(strcpy)(to, from);
559
} else {
560
if (!TryAsanInitFromRtl())
561
return REAL(strcpy)(to, from);
562
}
563
564
if (flags()->replace_str) {
565
uptr from_size = internal_strlen(from) + 1;
566
CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
567
ASAN_READ_RANGE(ctx, from, from_size);
568
ASAN_WRITE_RANGE(ctx, to, from_size);
569
}
570
return REAL(strcpy)(to, from);
571
}
572
573
// Windows doesn't always define the strdup identifier,
574
// and when it does it's a macro defined to either _strdup
575
// or _strdup_dbg, _strdup_dbg ends up calling _strdup, so
576
// we want to intercept that. push/pop_macro are used to avoid problems
577
// if this file ends up including <string.h> in the future.
578
# if SANITIZER_WINDOWS
579
# pragma push_macro("strdup")
580
# undef strdup
581
# define strdup _strdup
582
# endif
583
584
INTERCEPTOR(char*, strdup, const char *s) {
585
void *ctx;
586
ASAN_INTERCEPTOR_ENTER(ctx, strdup);
587
if (UNLIKELY(!TryAsanInitFromRtl()))
588
return internal_strdup(s);
589
uptr length = internal_strlen(s);
590
if (flags()->replace_str) {
591
ASAN_READ_RANGE(ctx, s, length + 1);
592
}
593
GET_STACK_TRACE_MALLOC;
594
void *new_mem = asan_malloc(length + 1, &stack);
595
if (new_mem) {
596
REAL(memcpy)(new_mem, s, length + 1);
597
}
598
return reinterpret_cast<char*>(new_mem);
599
}
600
601
# if ASAN_INTERCEPT___STRDUP
602
INTERCEPTOR(char*, __strdup, const char *s) {
603
void *ctx;
604
ASAN_INTERCEPTOR_ENTER(ctx, strdup);
605
if (UNLIKELY(!TryAsanInitFromRtl()))
606
return internal_strdup(s);
607
uptr length = internal_strlen(s);
608
if (flags()->replace_str) {
609
ASAN_READ_RANGE(ctx, s, length + 1);
610
}
611
GET_STACK_TRACE_MALLOC;
612
void *new_mem = asan_malloc(length + 1, &stack);
613
if (new_mem) {
614
REAL(memcpy)(new_mem, s, length + 1);
615
}
616
return reinterpret_cast<char*>(new_mem);
617
}
618
#endif // ASAN_INTERCEPT___STRDUP
619
620
INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
621
void *ctx;
622
ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
623
AsanInitFromRtl();
624
if (flags()->replace_str) {
625
uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
626
CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
627
ASAN_READ_RANGE(ctx, from, from_size);
628
ASAN_WRITE_RANGE(ctx, to, size);
629
}
630
return REAL(strncpy)(to, from, size);
631
}
632
633
template <typename Fn>
634
static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
635
char **endptr, int base)
636
-> decltype(real(nullptr, nullptr, 0)) {
637
if (!flags()->replace_str)
638
return real(nptr, endptr, base);
639
char *real_endptr;
640
auto res = real(nptr, &real_endptr, base);
641
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
642
return res;
643
}
644
645
# define INTERCEPTOR_STRTO_BASE(ret_type, func) \
646
INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
647
void *ctx; \
648
ASAN_INTERCEPTOR_ENTER(ctx, func); \
649
AsanInitFromRtl(); \
650
return StrtolImpl(ctx, REAL(func), nptr, endptr, base); \
651
}
652
653
INTERCEPTOR_STRTO_BASE(long, strtol)
654
INTERCEPTOR_STRTO_BASE(long long, strtoll)
655
656
# if SANITIZER_GLIBC
657
INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol)
658
INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll)
659
# endif
660
661
INTERCEPTOR(int, atoi, const char *nptr) {
662
void *ctx;
663
ASAN_INTERCEPTOR_ENTER(ctx, atoi);
664
if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
665
return REAL(atoi)(nptr);
666
AsanInitFromRtl();
667
if (!flags()->replace_str) {
668
return REAL(atoi)(nptr);
669
}
670
char *real_endptr;
671
// "man atoi" tells that behavior of atoi(nptr) is the same as
672
// strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
673
// parsed integer can't be stored in *long* type (even if it's
674
// different from int). So, we just imitate this behavior.
675
int result = REAL(strtol)(nptr, &real_endptr, 10);
676
FixRealStrtolEndptr(nptr, &real_endptr);
677
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
678
return result;
679
}
680
681
INTERCEPTOR(long, atol, const char *nptr) {
682
void *ctx;
683
ASAN_INTERCEPTOR_ENTER(ctx, atol);
684
if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
685
return REAL(atol)(nptr);
686
AsanInitFromRtl();
687
if (!flags()->replace_str) {
688
return REAL(atol)(nptr);
689
}
690
char *real_endptr;
691
long result = REAL(strtol)(nptr, &real_endptr, 10);
692
FixRealStrtolEndptr(nptr, &real_endptr);
693
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
694
return result;
695
}
696
697
INTERCEPTOR(long long, atoll, const char *nptr) {
698
void *ctx;
699
ASAN_INTERCEPTOR_ENTER(ctx, atoll);
700
AsanInitFromRtl();
701
if (!flags()->replace_str) {
702
return REAL(atoll)(nptr);
703
}
704
char *real_endptr;
705
long long result = REAL(strtoll)(nptr, &real_endptr, 10);
706
FixRealStrtolEndptr(nptr, &real_endptr);
707
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
708
return result;
709
}
710
711
#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
712
static void AtCxaAtexit(void *unused) {
713
(void)unused;
714
StopInitOrderChecking();
715
}
716
#endif
717
718
#if ASAN_INTERCEPT___CXA_ATEXIT
719
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
720
void *dso_handle) {
721
if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
722
return REAL(__cxa_atexit)(func, arg, dso_handle);
723
AsanInitFromRtl();
724
# if CAN_SANITIZE_LEAKS
725
__lsan::ScopedInterceptorDisabler disabler;
726
#endif
727
int res = REAL(__cxa_atexit)(func, arg, dso_handle);
728
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
729
return res;
730
}
731
#endif // ASAN_INTERCEPT___CXA_ATEXIT
732
733
#if ASAN_INTERCEPT_ATEXIT
734
INTERCEPTOR(int, atexit, void (*func)()) {
735
AsanInitFromRtl();
736
# if CAN_SANITIZE_LEAKS
737
__lsan::ScopedInterceptorDisabler disabler;
738
#endif
739
// Avoid calling real atexit as it is unreachable on at least on Linux.
740
int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
741
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
742
return res;
743
}
744
#endif
745
746
#if ASAN_INTERCEPT_PTHREAD_ATFORK
747
extern "C" {
748
extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
749
void (*child)());
750
}
751
752
INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
753
void (*child)()) {
754
#if CAN_SANITIZE_LEAKS
755
__lsan::ScopedInterceptorDisabler disabler;
756
#endif
757
// REAL(pthread_atfork) cannot be called due to symbol indirections at least
758
// on NetBSD
759
return _pthread_atfork(prepare, parent, child);
760
}
761
#endif
762
763
#if ASAN_INTERCEPT_VFORK
764
DEFINE_REAL(int, vfork,)
765
DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork,)
766
#endif
767
768
// ---------------------- InitializeAsanInterceptors ---------------- {{{1
769
namespace __asan {
770
void InitializeAsanInterceptors() {
771
static bool was_called_once;
772
CHECK(!was_called_once);
773
was_called_once = true;
774
InitializePlatformInterceptors();
775
InitializeCommonInterceptors();
776
InitializeSignalInterceptors();
777
778
// Intercept str* functions.
779
ASAN_INTERCEPT_FUNC(strcat);
780
ASAN_INTERCEPT_FUNC(strcpy);
781
ASAN_INTERCEPT_FUNC(strncat);
782
ASAN_INTERCEPT_FUNC(strncpy);
783
ASAN_INTERCEPT_FUNC(strdup);
784
# if ASAN_INTERCEPT___STRDUP
785
ASAN_INTERCEPT_FUNC(__strdup);
786
#endif
787
#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
788
ASAN_INTERCEPT_FUNC(index);
789
#endif
790
791
ASAN_INTERCEPT_FUNC(atoi);
792
ASAN_INTERCEPT_FUNC(atol);
793
ASAN_INTERCEPT_FUNC(atoll);
794
ASAN_INTERCEPT_FUNC(strtol);
795
ASAN_INTERCEPT_FUNC(strtoll);
796
# if SANITIZER_GLIBC
797
ASAN_INTERCEPT_FUNC(__isoc23_strtol);
798
ASAN_INTERCEPT_FUNC(__isoc23_strtoll);
799
# endif
800
801
// Intecept jump-related functions.
802
ASAN_INTERCEPT_FUNC(longjmp);
803
804
# if ASAN_INTERCEPT_SWAPCONTEXT
805
ASAN_INTERCEPT_FUNC(swapcontext);
806
// See the makecontext interceptor above for an explanation.
807
# if SANITIZER_SOLARIS && defined(__sparc__)
808
ASAN_INTERCEPT_FUNC(__makecontext_v2);
809
# else
810
ASAN_INTERCEPT_FUNC(makecontext);
811
# endif
812
# endif
813
# if ASAN_INTERCEPT__LONGJMP
814
ASAN_INTERCEPT_FUNC(_longjmp);
815
#endif
816
#if ASAN_INTERCEPT___LONGJMP_CHK
817
ASAN_INTERCEPT_FUNC(__longjmp_chk);
818
#endif
819
#if ASAN_INTERCEPT_SIGLONGJMP
820
ASAN_INTERCEPT_FUNC(siglongjmp);
821
#endif
822
823
// Intercept exception handling functions.
824
#if ASAN_INTERCEPT___CXA_THROW
825
ASAN_INTERCEPT_FUNC(__cxa_throw);
826
#endif
827
#if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
828
ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
829
#endif
830
// Indirectly intercept std::rethrow_exception.
831
#if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
832
ASAN_INTERCEPT_FUNC(_Unwind_RaiseException);
833
#endif
834
// Indirectly intercept std::rethrow_exception.
835
#if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
836
ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException);
837
#endif
838
839
// Intercept threading-related functions
840
#if ASAN_INTERCEPT_PTHREAD_CREATE
841
// TODO: this should probably have an unversioned fallback for newer arches?
842
#if defined(ASAN_PTHREAD_CREATE_VERSION)
843
ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
844
#else
845
ASAN_INTERCEPT_FUNC(pthread_create);
846
#endif
847
ASAN_INTERCEPT_FUNC(pthread_join);
848
ASAN_INTERCEPT_FUNC(pthread_detach);
849
ASAN_INTERCEPT_FUNC(pthread_exit);
850
# endif
851
852
# if ASAN_INTERCEPT_TIMEDJOIN
853
ASAN_INTERCEPT_FUNC(pthread_timedjoin_np);
854
#endif
855
856
#if ASAN_INTERCEPT_TRYJOIN
857
ASAN_INTERCEPT_FUNC(pthread_tryjoin_np);
858
#endif
859
860
// Intercept atexit function.
861
#if ASAN_INTERCEPT___CXA_ATEXIT
862
ASAN_INTERCEPT_FUNC(__cxa_atexit);
863
#endif
864
865
#if ASAN_INTERCEPT_ATEXIT
866
ASAN_INTERCEPT_FUNC(atexit);
867
#endif
868
869
#if ASAN_INTERCEPT_PTHREAD_ATFORK
870
ASAN_INTERCEPT_FUNC(pthread_atfork);
871
#endif
872
873
#if ASAN_INTERCEPT_VFORK
874
ASAN_INTERCEPT_FUNC(vfork);
875
#endif
876
877
VReport(1, "AddressSanitizer: libc interceptors initialized\n");
878
}
879
880
# if SANITIZER_WINDOWS
881
# pragma pop_macro("strdup")
882
# endif
883
884
} // namespace __asan
885
886
#endif // !SANITIZER_FUCHSIA
887
888