1 //===-- asan_interceptors.cc ----------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // Intercept various libc functions.
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 "sanitizer_common/sanitizer_libc.h"
24
25 namespace __asan {
26
27 // Return true if we can quickly decide that the region is unpoisoned.
QuickCheckForUnpoisonedRegion(uptr beg,uptr size)28 static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
29 if (size == 0) return true;
30 if (size <= 32)
31 return !AddressIsPoisoned(beg) &&
32 !AddressIsPoisoned(beg + size - 1) &&
33 !AddressIsPoisoned(beg + size / 2);
34 return false;
35 }
36
37 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
38 // and ASAN_WRITE_RANGE as macro instead of function so
39 // that no extra frames are created, and stack trace contains
40 // relevant information only.
41 // We check all shadow bytes.
42 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
43 uptr __offset = (uptr)(offset); \
44 uptr __size = (uptr)(size); \
45 uptr __bad = 0; \
46 if (__offset > __offset + __size) { \
47 GET_STACK_TRACE_FATAL_HERE; \
48 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
49 } \
50 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
51 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
52 GET_CURRENT_PC_BP_SP; \
53 __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \
54 } \
55 } while (0)
56
57 #define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
58 #define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true)
59
60 // Behavior of functions like "memcpy" or "strcpy" is undefined
61 // if memory intervals overlap. We report error in this case.
62 // Macro is used to avoid creation of new frames.
RangesOverlap(const char * offset1,uptr length1,const char * offset2,uptr length2)63 static inline bool RangesOverlap(const char *offset1, uptr length1,
64 const char *offset2, uptr length2) {
65 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
66 }
67 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
68 const char *offset1 = (const char*)_offset1; \
69 const char *offset2 = (const char*)_offset2; \
70 if (RangesOverlap(offset1, length1, offset2, length2)) { \
71 GET_STACK_TRACE_FATAL_HERE; \
72 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
73 offset2, length2, &stack); \
74 } \
75 } while (0)
76
MaybeRealStrnlen(const char * s,uptr maxlen)77 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
78 #if ASAN_INTERCEPT_STRNLEN
79 if (REAL(strnlen) != 0) {
80 return REAL(strnlen)(s, maxlen);
81 }
82 #endif
83 return internal_strnlen(s, maxlen);
84 }
85
SetThreadName(const char * name)86 void SetThreadName(const char *name) {
87 AsanThread *t = GetCurrentThread();
88 if (t)
89 asanThreadRegistry().SetThreadName(t->tid(), name);
90 }
91
OnExit()92 int OnExit() {
93 // FIXME: ask frontend whether we need to return failure.
94 return 0;
95 }
96
97 } // namespace __asan
98
99 // ---------------------- Wrappers ---------------- {{{1
100 using namespace __asan; // NOLINT
101
DECLARE_REAL_AND_INTERCEPTOR(void *,malloc,uptr)102 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
103 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
104
105 #if !SANITIZER_MAC
106 #define ASAN_INTERCEPT_FUNC(name) \
107 do { \
108 if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
109 VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
110 } while (0)
111 #else
112 // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
113 #define ASAN_INTERCEPT_FUNC(name)
114 #endif // SANITIZER_MAC
115
116 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
117 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
118 ASAN_WRITE_RANGE(ptr, size)
119 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
120 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
121 do { \
122 if (asan_init_is_running) \
123 return REAL(func)(__VA_ARGS__); \
124 ctx = 0; \
125 (void) ctx; \
126 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
127 return REAL(func)(__VA_ARGS__); \
128 ENSURE_ASAN_INITED(); \
129 } while (false)
130 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
131 do { \
132 } while (false)
133 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
134 do { \
135 } while (false)
136 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
137 do { \
138 } while (false)
139 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
140 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
141 // But asan does not remember UserId's for threads (pthread_t);
142 // and remembers all ever existed threads, so the linear search by UserId
143 // can be slow.
144 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
145 do { \
146 } while (false)
147 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
148 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
149 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res) CovUpdateMapping()
150 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CovUpdateMapping()
151 #include "sanitizer_common/sanitizer_common_interceptors.inc"
152
153 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
154 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
155 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
156 do { \
157 (void)(p); \
158 (void)(s); \
159 } while (false)
160 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
161 do { \
162 (void)(p); \
163 (void)(s); \
164 } while (false)
165 #include "sanitizer_common/sanitizer_common_syscalls.inc"
166
167 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
168 AsanThread *t = (AsanThread*)arg;
169 SetCurrentThread(t);
170 return t->ThreadStart(GetTid());
171 }
172
173 #if ASAN_INTERCEPT_PTHREAD_CREATE
INTERCEPTOR(int,pthread_create,void * thread,void * attr,void * (* start_routine)(void *),void * arg)174 INTERCEPTOR(int, pthread_create, void *thread,
175 void *attr, void *(*start_routine)(void*), void *arg) {
176 EnsureMainThreadIDIsCorrect();
177 // Strict init-order checking in thread-hostile.
178 if (flags()->strict_init_order)
179 StopInitOrderChecking();
180 GET_STACK_TRACE_THREAD;
181 int detached = 0;
182 if (attr != 0)
183 REAL(pthread_attr_getdetachstate)(attr, &detached);
184
185 u32 current_tid = GetCurrentTidOrInvalid();
186 AsanThread *t = AsanThread::Create(start_routine, arg);
187 CreateThreadContextArgs args = { t, &stack };
188 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
189 return REAL(pthread_create)(thread, attr, asan_thread_start, t);
190 }
191 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
192
193 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
194
195 #if SANITIZER_ANDROID
INTERCEPTOR(void *,bsd_signal,int signum,void * handler)196 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
197 if (!AsanInterceptsSignal(signum) ||
198 common_flags()->allow_user_segv_handler) {
199 return REAL(bsd_signal)(signum, handler);
200 }
201 return 0;
202 }
203 #else
INTERCEPTOR(void *,signal,int signum,void * handler)204 INTERCEPTOR(void*, signal, int signum, void *handler) {
205 if (!AsanInterceptsSignal(signum) ||
206 common_flags()->allow_user_segv_handler) {
207 return REAL(signal)(signum, handler);
208 }
209 return 0;
210 }
211 #endif
212
INTERCEPTOR(int,sigaction,int signum,const struct sigaction * act,struct sigaction * oldact)213 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
214 struct sigaction *oldact) {
215 if (!AsanInterceptsSignal(signum) ||
216 common_flags()->allow_user_segv_handler) {
217 return REAL(sigaction)(signum, act, oldact);
218 }
219 return 0;
220 }
221
222 namespace __sanitizer {
real_sigaction(int signum,const void * act,void * oldact)223 int real_sigaction(int signum, const void *act, void *oldact) {
224 return REAL(sigaction)(signum,
225 (struct sigaction *)act, (struct sigaction *)oldact);
226 }
227 } // namespace __sanitizer
228
229 #elif SANITIZER_POSIX
230 // We need to have defined REAL(sigaction) on posix systems.
DEFINE_REAL(int,sigaction,int signum,const struct sigaction * act,struct sigaction * oldact)231 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
232 struct sigaction *oldact)
233 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
234
235 #if ASAN_INTERCEPT_SWAPCONTEXT
236 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
237 // Align to page size.
238 uptr PageSize = GetPageSizeCached();
239 uptr bottom = stack & ~(PageSize - 1);
240 ssize += stack - bottom;
241 ssize = RoundUpTo(ssize, PageSize);
242 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
243 if (ssize && ssize <= kMaxSaneContextStackSize) {
244 PoisonShadow(bottom, ssize, 0);
245 }
246 }
247
INTERCEPTOR(int,swapcontext,struct ucontext_t * oucp,struct ucontext_t * ucp)248 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
249 struct ucontext_t *ucp) {
250 static bool reported_warning = false;
251 if (!reported_warning) {
252 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
253 "functions and may produce false positives in some cases!\n");
254 reported_warning = true;
255 }
256 // Clear shadow memory for new context (it may share stack
257 // with current context).
258 uptr stack, ssize;
259 ReadContextStack(ucp, &stack, &ssize);
260 ClearShadowMemoryForContextStack(stack, ssize);
261 int res = REAL(swapcontext)(oucp, ucp);
262 // swapcontext technically does not return, but program may swap context to
263 // "oucp" later, that would look as if swapcontext() returned 0.
264 // We need to clear shadow for ucp once again, as it may be in arbitrary
265 // state.
266 ClearShadowMemoryForContextStack(stack, ssize);
267 return res;
268 }
269 #endif // ASAN_INTERCEPT_SWAPCONTEXT
270
INTERCEPTOR(void,longjmp,void * env,int val)271 INTERCEPTOR(void, longjmp, void *env, int val) {
272 __asan_handle_no_return();
273 REAL(longjmp)(env, val);
274 }
275
276 #if ASAN_INTERCEPT__LONGJMP
INTERCEPTOR(void,_longjmp,void * env,int val)277 INTERCEPTOR(void, _longjmp, void *env, int val) {
278 __asan_handle_no_return();
279 REAL(_longjmp)(env, val);
280 }
281 #endif
282
283 #if ASAN_INTERCEPT_SIGLONGJMP
INTERCEPTOR(void,siglongjmp,void * env,int val)284 INTERCEPTOR(void, siglongjmp, void *env, int val) {
285 __asan_handle_no_return();
286 REAL(siglongjmp)(env, val);
287 }
288 #endif
289
290 #if ASAN_INTERCEPT___CXA_THROW
INTERCEPTOR(void,__cxa_throw,void * a,void * b,void * c)291 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
292 CHECK(REAL(__cxa_throw));
293 __asan_handle_no_return();
294 REAL(__cxa_throw)(a, b, c);
295 }
296 #endif
297
298 #if ASAN_INTERCEPT_MLOCKX
299 // intercept mlock and friends.
300 // Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
301 // All functions return 0 (success).
MlockIsUnsupported()302 static void MlockIsUnsupported() {
303 static bool printed = false;
304 if (printed) return;
305 printed = true;
306 VPrintf(1,
307 "INFO: AddressSanitizer ignores "
308 "mlock/mlockall/munlock/munlockall\n");
309 }
310
INTERCEPTOR(int,mlock,const void * addr,uptr len)311 INTERCEPTOR(int, mlock, const void *addr, uptr len) {
312 MlockIsUnsupported();
313 return 0;
314 }
315
INTERCEPTOR(int,munlock,const void * addr,uptr len)316 INTERCEPTOR(int, munlock, const void *addr, uptr len) {
317 MlockIsUnsupported();
318 return 0;
319 }
320
INTERCEPTOR(int,mlockall,int flags)321 INTERCEPTOR(int, mlockall, int flags) {
322 MlockIsUnsupported();
323 return 0;
324 }
325
INTERCEPTOR(int,munlockall,void)326 INTERCEPTOR(int, munlockall, void) {
327 MlockIsUnsupported();
328 return 0;
329 }
330 #endif
331
CharCmp(unsigned char c1,unsigned char c2)332 static inline int CharCmp(unsigned char c1, unsigned char c2) {
333 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
334 }
335
INTERCEPTOR(int,memcmp,const void * a1,const void * a2,uptr size)336 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
337 if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
338 ENSURE_ASAN_INITED();
339 if (flags()->replace_intrin) {
340 if (flags()->strict_memcmp) {
341 // Check the entire regions even if the first bytes of the buffers are
342 // different.
343 ASAN_READ_RANGE(a1, size);
344 ASAN_READ_RANGE(a2, size);
345 // Fallthrough to REAL(memcmp) below.
346 } else {
347 unsigned char c1 = 0, c2 = 0;
348 const unsigned char *s1 = (const unsigned char*)a1;
349 const unsigned char *s2 = (const unsigned char*)a2;
350 uptr i;
351 for (i = 0; i < size; i++) {
352 c1 = s1[i];
353 c2 = s2[i];
354 if (c1 != c2) break;
355 }
356 ASAN_READ_RANGE(s1, Min(i + 1, size));
357 ASAN_READ_RANGE(s2, Min(i + 1, size));
358 return CharCmp(c1, c2);
359 }
360 }
361 return REAL(memcmp(a1, a2, size));
362 }
363
__asan_memcpy(void * to,const void * from,uptr size)364 void *__asan_memcpy(void *to, const void *from, uptr size) {
365 if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size);
366 // memcpy is called during __asan_init() from the internals
367 // of printf(...).
368 if (asan_init_is_running) {
369 return REAL(memcpy)(to, from, size);
370 }
371 ENSURE_ASAN_INITED();
372 if (flags()->replace_intrin) {
373 if (to != from) {
374 // We do not treat memcpy with to==from as a bug.
375 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
376 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
377 }
378 ASAN_READ_RANGE(from, size);
379 ASAN_WRITE_RANGE(to, size);
380 }
381 return REAL(memcpy)(to, from, size);
382 }
383
__asan_memset(void * block,int c,uptr size)384 void *__asan_memset(void *block, int c, uptr size) {
385 if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size);
386 // memset is called inside Printf.
387 if (asan_init_is_running) {
388 return REAL(memset)(block, c, size);
389 }
390 ENSURE_ASAN_INITED();
391 if (flags()->replace_intrin) {
392 ASAN_WRITE_RANGE(block, size);
393 }
394 return REAL(memset)(block, c, size);
395 }
396
__asan_memmove(void * to,const void * from,uptr size)397 void *__asan_memmove(void *to, const void *from, uptr size) {
398 if (UNLIKELY(!asan_inited))
399 return internal_memmove(to, from, size);
400 ENSURE_ASAN_INITED();
401 if (flags()->replace_intrin) {
402 ASAN_READ_RANGE(from, size);
403 ASAN_WRITE_RANGE(to, size);
404 }
405 return internal_memmove(to, from, size);
406 }
407
INTERCEPTOR(void *,memmove,void * to,const void * from,uptr size)408 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
409 return __asan_memmove(to, from, size);
410 }
411
INTERCEPTOR(void *,memcpy,void * to,const void * from,uptr size)412 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
413 #if !SANITIZER_MAC
414 return __asan_memcpy(to, from, size);
415 #else
416 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
417 // with WRAP(memcpy). As a result, false positives are reported for memmove()
418 // calls. If we just disable error reporting with
419 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
420 // internal_memcpy(), which may lead to crashes, see
421 // http://llvm.org/bugs/show_bug.cgi?id=16362.
422 return __asan_memmove(to, from, size);
423 #endif // !SANITIZER_MAC
424 }
425
INTERCEPTOR(void *,memset,void * block,int c,uptr size)426 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
427 return __asan_memset(block, c, size);
428 }
429
INTERCEPTOR(char *,strchr,const char * str,int c)430 INTERCEPTOR(char*, strchr, const char *str, int c) {
431 if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
432 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
433 // used.
434 if (asan_init_is_running) {
435 return REAL(strchr)(str, c);
436 }
437 ENSURE_ASAN_INITED();
438 char *result = REAL(strchr)(str, c);
439 if (flags()->replace_str) {
440 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
441 ASAN_READ_RANGE(str, bytes_read);
442 }
443 return result;
444 }
445
446 #if ASAN_INTERCEPT_INDEX
447 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
448 INTERCEPTOR(char*, index, const char *string, int c)
449 ALIAS(WRAPPER_NAME(strchr));
450 # else
451 # if SANITIZER_MAC
452 DECLARE_REAL(char*, index, const char *string, int c)
453 OVERRIDE_FUNCTION(index, strchr);
454 # else
DEFINE_REAL(char *,index,const char * string,int c)455 DEFINE_REAL(char*, index, const char *string, int c)
456 # endif
457 # endif
458 #endif // ASAN_INTERCEPT_INDEX
459
460 // For both strcat() and strncat() we need to check the validity of |to|
461 // argument irrespective of the |from| length.
462 INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
463 ENSURE_ASAN_INITED();
464 if (flags()->replace_str) {
465 uptr from_length = REAL(strlen)(from);
466 ASAN_READ_RANGE(from, from_length + 1);
467 uptr to_length = REAL(strlen)(to);
468 ASAN_READ_RANGE(to, to_length);
469 ASAN_WRITE_RANGE(to + to_length, from_length + 1);
470 // If the copying actually happens, the |from| string should not overlap
471 // with the resulting string starting at |to|, which has a length of
472 // to_length + from_length + 1.
473 if (from_length > 0) {
474 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
475 from, from_length + 1);
476 }
477 }
478 return REAL(strcat)(to, from); // NOLINT
479 }
480
INTERCEPTOR(char *,strncat,char * to,const char * from,uptr size)481 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
482 ENSURE_ASAN_INITED();
483 if (flags()->replace_str) {
484 uptr from_length = MaybeRealStrnlen(from, size);
485 uptr copy_length = Min(size, from_length + 1);
486 ASAN_READ_RANGE(from, copy_length);
487 uptr to_length = REAL(strlen)(to);
488 ASAN_READ_RANGE(to, to_length);
489 ASAN_WRITE_RANGE(to + to_length, from_length + 1);
490 if (from_length > 0) {
491 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
492 from, copy_length);
493 }
494 }
495 return REAL(strncat)(to, from, size);
496 }
497
INTERCEPTOR(char *,strcpy,char * to,const char * from)498 INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
499 #if SANITIZER_MAC
500 if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
501 #endif
502 // strcpy is called from malloc_default_purgeable_zone()
503 // in __asan::ReplaceSystemAlloc() on Mac.
504 if (asan_init_is_running) {
505 return REAL(strcpy)(to, from); // NOLINT
506 }
507 ENSURE_ASAN_INITED();
508 if (flags()->replace_str) {
509 uptr from_size = REAL(strlen)(from) + 1;
510 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
511 ASAN_READ_RANGE(from, from_size);
512 ASAN_WRITE_RANGE(to, from_size);
513 }
514 return REAL(strcpy)(to, from); // NOLINT
515 }
516
517 #if ASAN_INTERCEPT_STRDUP
INTERCEPTOR(char *,strdup,const char * s)518 INTERCEPTOR(char*, strdup, const char *s) {
519 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
520 ENSURE_ASAN_INITED();
521 uptr length = REAL(strlen)(s);
522 if (flags()->replace_str) {
523 ASAN_READ_RANGE(s, length + 1);
524 }
525 GET_STACK_TRACE_MALLOC;
526 void *new_mem = asan_malloc(length + 1, &stack);
527 REAL(memcpy)(new_mem, s, length + 1);
528 return reinterpret_cast<char*>(new_mem);
529 }
530 #endif
531
INTERCEPTOR(uptr,strlen,const char * s)532 INTERCEPTOR(uptr, strlen, const char *s) {
533 if (UNLIKELY(!asan_inited)) return internal_strlen(s);
534 // strlen is called from malloc_default_purgeable_zone()
535 // in __asan::ReplaceSystemAlloc() on Mac.
536 if (asan_init_is_running) {
537 return REAL(strlen)(s);
538 }
539 ENSURE_ASAN_INITED();
540 uptr length = REAL(strlen)(s);
541 if (flags()->replace_str) {
542 ASAN_READ_RANGE(s, length + 1);
543 }
544 return length;
545 }
546
INTERCEPTOR(uptr,wcslen,const wchar_t * s)547 INTERCEPTOR(uptr, wcslen, const wchar_t *s) {
548 uptr length = REAL(wcslen)(s);
549 if (!asan_init_is_running) {
550 ENSURE_ASAN_INITED();
551 ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t));
552 }
553 return length;
554 }
555
INTERCEPTOR(char *,strncpy,char * to,const char * from,uptr size)556 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
557 ENSURE_ASAN_INITED();
558 if (flags()->replace_str) {
559 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
560 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
561 ASAN_READ_RANGE(from, from_size);
562 ASAN_WRITE_RANGE(to, size);
563 }
564 return REAL(strncpy)(to, from, size);
565 }
566
567 #if ASAN_INTERCEPT_STRNLEN
INTERCEPTOR(uptr,strnlen,const char * s,uptr maxlen)568 INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
569 ENSURE_ASAN_INITED();
570 uptr length = REAL(strnlen)(s, maxlen);
571 if (flags()->replace_str) {
572 ASAN_READ_RANGE(s, Min(length + 1, maxlen));
573 }
574 return length;
575 }
576 #endif // ASAN_INTERCEPT_STRNLEN
577
IsValidStrtolBase(int base)578 static inline bool IsValidStrtolBase(int base) {
579 return (base == 0) || (2 <= base && base <= 36);
580 }
581
FixRealStrtolEndptr(const char * nptr,char ** endptr)582 static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
583 CHECK(endptr);
584 if (nptr == *endptr) {
585 // No digits were found at strtol call, we need to find out the last
586 // symbol accessed by strtoll on our own.
587 // We get this symbol by skipping leading blanks and optional +/- sign.
588 while (IsSpace(*nptr)) nptr++;
589 if (*nptr == '+' || *nptr == '-') nptr++;
590 *endptr = (char*)nptr;
591 }
592 CHECK(*endptr >= nptr);
593 }
594
INTERCEPTOR(long,strtol,const char * nptr,char ** endptr,int base)595 INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
596 char **endptr, int base) {
597 ENSURE_ASAN_INITED();
598 if (!flags()->replace_str) {
599 return REAL(strtol)(nptr, endptr, base);
600 }
601 char *real_endptr;
602 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
603 if (endptr != 0) {
604 *endptr = real_endptr;
605 }
606 if (IsValidStrtolBase(base)) {
607 FixRealStrtolEndptr(nptr, &real_endptr);
608 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
609 }
610 return result;
611 }
612
INTERCEPTOR(int,atoi,const char * nptr)613 INTERCEPTOR(int, atoi, const char *nptr) {
614 #if SANITIZER_MAC
615 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
616 #endif
617 ENSURE_ASAN_INITED();
618 if (!flags()->replace_str) {
619 return REAL(atoi)(nptr);
620 }
621 char *real_endptr;
622 // "man atoi" tells that behavior of atoi(nptr) is the same as
623 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
624 // parsed integer can't be stored in *long* type (even if it's
625 // different from int). So, we just imitate this behavior.
626 int result = REAL(strtol)(nptr, &real_endptr, 10);
627 FixRealStrtolEndptr(nptr, &real_endptr);
628 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
629 return result;
630 }
631
INTERCEPTOR(long,atol,const char * nptr)632 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
633 #if SANITIZER_MAC
634 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
635 #endif
636 ENSURE_ASAN_INITED();
637 if (!flags()->replace_str) {
638 return REAL(atol)(nptr);
639 }
640 char *real_endptr;
641 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
642 FixRealStrtolEndptr(nptr, &real_endptr);
643 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
644 return result;
645 }
646
647 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
INTERCEPTOR(long long,strtoll,const char * nptr,char ** endptr,int base)648 INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
649 char **endptr, int base) {
650 ENSURE_ASAN_INITED();
651 if (!flags()->replace_str) {
652 return REAL(strtoll)(nptr, endptr, base);
653 }
654 char *real_endptr;
655 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
656 if (endptr != 0) {
657 *endptr = real_endptr;
658 }
659 // If base has unsupported value, strtoll can exit with EINVAL
660 // without reading any characters. So do additional checks only
661 // if base is valid.
662 if (IsValidStrtolBase(base)) {
663 FixRealStrtolEndptr(nptr, &real_endptr);
664 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
665 }
666 return result;
667 }
668
INTERCEPTOR(long long,atoll,const char * nptr)669 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
670 ENSURE_ASAN_INITED();
671 if (!flags()->replace_str) {
672 return REAL(atoll)(nptr);
673 }
674 char *real_endptr;
675 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
676 FixRealStrtolEndptr(nptr, &real_endptr);
677 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
678 return result;
679 }
680 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
681
AtCxaAtexit(void * unused)682 static void AtCxaAtexit(void *unused) {
683 (void)unused;
684 StopInitOrderChecking();
685 }
686
687 #if ASAN_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)688 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
689 void *dso_handle) {
690 #if SANITIZER_MAC
691 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
692 #endif
693 ENSURE_ASAN_INITED();
694 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
695 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
696 return res;
697 }
698 #endif // ASAN_INTERCEPT___CXA_ATEXIT
699
700 #if ASAN_INTERCEPT_FORK
INTERCEPTOR(int,fork,void)701 INTERCEPTOR(int, fork, void) {
702 ENSURE_ASAN_INITED();
703 if (common_flags()->coverage) CovBeforeFork();
704 int pid = REAL(fork)();
705 if (common_flags()->coverage) CovAfterFork(pid);
706 return pid;
707 }
708 #endif // ASAN_INTERCEPT_FORK
709
710 #if SANITIZER_WINDOWS
INTERCEPTOR_WINAPI(DWORD,CreateThread,void * security,uptr stack_size,DWORD (__stdcall * start_routine)(void *),void * arg,DWORD thr_flags,void * tid)711 INTERCEPTOR_WINAPI(DWORD, CreateThread,
712 void* security, uptr stack_size,
713 DWORD (__stdcall *start_routine)(void*), void* arg,
714 DWORD thr_flags, void* tid) {
715 // Strict init-order checking in thread-hostile.
716 if (flags()->strict_init_order)
717 StopInitOrderChecking();
718 GET_STACK_TRACE_THREAD;
719 u32 current_tid = GetCurrentTidOrInvalid();
720 AsanThread *t = AsanThread::Create(start_routine, arg);
721 CreateThreadContextArgs args = { t, &stack };
722 bool detached = false; // FIXME: how can we determine it on Windows?
723 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
724 return REAL(CreateThread)(security, stack_size,
725 asan_thread_start, t, thr_flags, tid);
726 }
727
728 namespace __asan {
InitializeWindowsInterceptors()729 void InitializeWindowsInterceptors() {
730 ASAN_INTERCEPT_FUNC(CreateThread);
731 }
732
733 } // namespace __asan
734 #endif
735
736 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
737 namespace __asan {
InitializeAsanInterceptors()738 void InitializeAsanInterceptors() {
739 static bool was_called_once;
740 CHECK(was_called_once == false);
741 was_called_once = true;
742 InitializeCommonInterceptors();
743
744 // Intercept mem* functions.
745 ASAN_INTERCEPT_FUNC(memcmp);
746 ASAN_INTERCEPT_FUNC(memmove);
747 ASAN_INTERCEPT_FUNC(memset);
748 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
749 ASAN_INTERCEPT_FUNC(memcpy);
750 }
751
752 // Intercept str* functions.
753 ASAN_INTERCEPT_FUNC(strcat); // NOLINT
754 ASAN_INTERCEPT_FUNC(strchr);
755 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
756 ASAN_INTERCEPT_FUNC(strlen);
757 ASAN_INTERCEPT_FUNC(wcslen);
758 ASAN_INTERCEPT_FUNC(strncat);
759 ASAN_INTERCEPT_FUNC(strncpy);
760 #if ASAN_INTERCEPT_STRDUP
761 ASAN_INTERCEPT_FUNC(strdup);
762 #endif
763 #if ASAN_INTERCEPT_STRNLEN
764 ASAN_INTERCEPT_FUNC(strnlen);
765 #endif
766 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
767 ASAN_INTERCEPT_FUNC(index);
768 #endif
769
770 ASAN_INTERCEPT_FUNC(atoi);
771 ASAN_INTERCEPT_FUNC(atol);
772 ASAN_INTERCEPT_FUNC(strtol);
773 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
774 ASAN_INTERCEPT_FUNC(atoll);
775 ASAN_INTERCEPT_FUNC(strtoll);
776 #endif
777
778 #if ASAN_INTERCEPT_MLOCKX
779 // Intercept mlock/munlock.
780 ASAN_INTERCEPT_FUNC(mlock);
781 ASAN_INTERCEPT_FUNC(munlock);
782 ASAN_INTERCEPT_FUNC(mlockall);
783 ASAN_INTERCEPT_FUNC(munlockall);
784 #endif
785
786 // Intecept signal- and jump-related functions.
787 ASAN_INTERCEPT_FUNC(longjmp);
788 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
789 ASAN_INTERCEPT_FUNC(sigaction);
790 #if SANITIZER_ANDROID
791 ASAN_INTERCEPT_FUNC(bsd_signal);
792 #else
793 ASAN_INTERCEPT_FUNC(signal);
794 #endif
795 #endif
796 #if ASAN_INTERCEPT_SWAPCONTEXT
797 ASAN_INTERCEPT_FUNC(swapcontext);
798 #endif
799 #if ASAN_INTERCEPT__LONGJMP
800 ASAN_INTERCEPT_FUNC(_longjmp);
801 #endif
802 #if ASAN_INTERCEPT_SIGLONGJMP
803 ASAN_INTERCEPT_FUNC(siglongjmp);
804 #endif
805
806 // Intercept exception handling functions.
807 #if ASAN_INTERCEPT___CXA_THROW
808 INTERCEPT_FUNCTION(__cxa_throw);
809 #endif
810
811 // Intercept threading-related functions
812 #if ASAN_INTERCEPT_PTHREAD_CREATE
813 ASAN_INTERCEPT_FUNC(pthread_create);
814 #endif
815
816 // Intercept atexit function.
817 #if ASAN_INTERCEPT___CXA_ATEXIT
818 ASAN_INTERCEPT_FUNC(__cxa_atexit);
819 #endif
820
821 #if ASAN_INTERCEPT_FORK
822 ASAN_INTERCEPT_FUNC(fork);
823 #endif
824
825 // Some Windows-specific interceptors.
826 #if SANITIZER_WINDOWS
827 InitializeWindowsInterceptors();
828 #endif
829
830 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
831 }
832
833 } // namespace __asan
834