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 
MaybeRealStrnlen(const char * s,uptr maxlen)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 
SetThreadName(const char * name)68 void SetThreadName(const char *name) {
69   AsanThread *t = GetCurrentThread();
70   if (t)
71     asanThreadRegistry().SetThreadName(t->tid(), name);
72 }
73 
OnExit()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 
DECLARE_REAL_AND_INTERCEPTOR(void *,malloc,uptr)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>
munmap_interceptor(Munmap real_munmap,void * addr,SIZE_T length)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
asan_thread_start(void * arg)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 
INTERCEPTOR(int,pthread_create,void * thread,void * attr,void * (* start_routine)(void *),void * arg)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 
INTERCEPTOR(int,pthread_join,void * thread,void ** retval)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 
INTERCEPTOR(int,pthread_detach,void * thread)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 
INTERCEPTOR(void,pthread_exit,void * retval)308 INTERCEPTOR(void, pthread_exit, void *retval) {
309   asanThreadArgRetval().Finish(GetThreadSelf(), retval);
310   REAL(pthread_exit)(retval);
311 }
312 
313 #    if ASAN_INTERCEPT_TRYJOIN
INTERCEPTOR(int,pthread_tryjoin_np,void * thread,void ** ret)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
INTERCEPTOR(int,pthread_timedjoin_np,void * thread,void ** ret,const struct timespec * abstime)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_REAL_PTHREAD_FUNCTIONS
337 #endif  // ASAN_INTERCEPT_PTHREAD_CREATE
338 
339 #if ASAN_INTERCEPT_SWAPCONTEXT
ClearShadowMemoryForContextStack(uptr stack,uptr ssize)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 
INTERCEPTOR(void,makecontext,struct ucontext_t * ucp,void (* func)(),int argc,...)355 INTERCEPTOR(void, makecontext, struct ucontext_t *ucp, void (*func)(), int argc,
356             ...) {
357   va_list ap;
358   uptr args[64];
359   // We don't know a better way to forward ... into REAL function. We can
360   // increase args size if neccecary.
361   CHECK_LE(argc, ARRAY_SIZE(args));
362   internal_memset(args, 0, sizeof(args));
363   va_start(ap, argc);
364   for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr);
365   va_end(ap);
366 
367 #    define ENUMERATE_ARRAY_4(start) \
368       args[start], args[start + 1], args[start + 2], args[start + 3]
369 #    define ENUMERATE_ARRAY_16(start)                         \
370       ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
371           ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
372 #    define ENUMERATE_ARRAY_64()                                             \
373       ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
374           ENUMERATE_ARRAY_16(48)
375 
376   REAL(makecontext)
377   ((struct ucontext_t *)ucp, func, argc, ENUMERATE_ARRAY_64());
378 
379 #    undef ENUMERATE_ARRAY_4
380 #    undef ENUMERATE_ARRAY_16
381 #    undef ENUMERATE_ARRAY_64
382 
383   // Sign the stack so we can identify it for unpoisoning.
384   SignContextStack(ucp);
385 }
386 
INTERCEPTOR(int,swapcontext,struct ucontext_t * oucp,struct ucontext_t * ucp)387 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
388             struct ucontext_t *ucp) {
389   static bool reported_warning = false;
390   if (!reported_warning) {
391     Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
392            "functions and may produce false positives in some cases!\n");
393     reported_warning = true;
394   }
395   // Clear shadow memory for new context (it may share stack
396   // with current context).
397   uptr stack, ssize;
398   ReadContextStack(ucp, &stack, &ssize);
399   ClearShadowMemoryForContextStack(stack, ssize);
400 
401 #    if __has_attribute(__indirect_return__) && \
402         (defined(__x86_64__) || defined(__i386__))
403   int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
404       __attribute__((__indirect_return__)) = REAL(swapcontext);
405   int res = real_swapcontext(oucp, ucp);
406 #    else
407   int res = REAL(swapcontext)(oucp, ucp);
408 #    endif
409   // swapcontext technically does not return, but program may swap context to
410   // "oucp" later, that would look as if swapcontext() returned 0.
411   // We need to clear shadow for ucp once again, as it may be in arbitrary
412   // state.
413   ClearShadowMemoryForContextStack(stack, ssize);
414   return res;
415 }
416 #endif  // ASAN_INTERCEPT_SWAPCONTEXT
417 
418 #if SANITIZER_NETBSD
419 #define longjmp __longjmp14
420 #define siglongjmp __siglongjmp14
421 #endif
422 
INTERCEPTOR(void,longjmp,void * env,int val)423 INTERCEPTOR(void, longjmp, void *env, int val) {
424   __asan_handle_no_return();
425   REAL(longjmp)(env, val);
426 }
427 
428 #if ASAN_INTERCEPT__LONGJMP
INTERCEPTOR(void,_longjmp,void * env,int val)429 INTERCEPTOR(void, _longjmp, void *env, int val) {
430   __asan_handle_no_return();
431   REAL(_longjmp)(env, val);
432 }
433 #endif
434 
435 #if ASAN_INTERCEPT___LONGJMP_CHK
INTERCEPTOR(void,__longjmp_chk,void * env,int val)436 INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
437   __asan_handle_no_return();
438   REAL(__longjmp_chk)(env, val);
439 }
440 #endif
441 
442 #if ASAN_INTERCEPT_SIGLONGJMP
INTERCEPTOR(void,siglongjmp,void * env,int val)443 INTERCEPTOR(void, siglongjmp, void *env, int val) {
444   __asan_handle_no_return();
445   REAL(siglongjmp)(env, val);
446 }
447 #endif
448 
449 #if ASAN_INTERCEPT___CXA_THROW
INTERCEPTOR(void,__cxa_throw,void * a,void * b,void * c)450 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
451   CHECK(REAL(__cxa_throw));
452   __asan_handle_no_return();
453   REAL(__cxa_throw)(a, b, c);
454 }
455 #endif
456 
457 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
INTERCEPTOR(void,__cxa_rethrow_primary_exception,void * a)458 INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
459   CHECK(REAL(__cxa_rethrow_primary_exception));
460   __asan_handle_no_return();
461   REAL(__cxa_rethrow_primary_exception)(a);
462 }
463 #endif
464 
465 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
INTERCEPTOR(_Unwind_Reason_Code,_Unwind_RaiseException,_Unwind_Exception * object)466 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
467             _Unwind_Exception *object) {
468   CHECK(REAL(_Unwind_RaiseException));
469   __asan_handle_no_return();
470   return REAL(_Unwind_RaiseException)(object);
471 }
472 #endif
473 
474 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
INTERCEPTOR(_Unwind_Reason_Code,_Unwind_SjLj_RaiseException,_Unwind_Exception * object)475 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
476             _Unwind_Exception *object) {
477   CHECK(REAL(_Unwind_SjLj_RaiseException));
478   __asan_handle_no_return();
479   return REAL(_Unwind_SjLj_RaiseException)(object);
480 }
481 #endif
482 
483 #if ASAN_INTERCEPT_INDEX
484 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
485 INTERCEPTOR(char*, index, const char *string, int c)
486   ALIAS(WRAP(strchr));
487 # else
488 #  if SANITIZER_APPLE
489 DECLARE_REAL(char*, index, const char *string, int c)
490 OVERRIDE_FUNCTION(index, strchr);
491 #  else
DEFINE_REAL(char *,index,const char * string,int c)492 DEFINE_REAL(char*, index, const char *string, int c)
493 #  endif
494 # endif
495 #endif  // ASAN_INTERCEPT_INDEX
496 
497 // For both strcat() and strncat() we need to check the validity of |to|
498 // argument irrespective of the |from| length.
499   INTERCEPTOR(char *, strcat, char *to, const char *from) {
500     void *ctx;
501     ASAN_INTERCEPTOR_ENTER(ctx, strcat);
502     AsanInitFromRtl();
503     if (flags()->replace_str) {
504       uptr from_length = internal_strlen(from);
505       ASAN_READ_RANGE(ctx, from, from_length + 1);
506       uptr to_length = internal_strlen(to);
507       ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
508       ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
509       // If the copying actually happens, the |from| string should not overlap
510       // with the resulting string starting at |to|, which has a length of
511       // to_length + from_length + 1.
512       if (from_length > 0) {
513         CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
514                              from_length + 1);
515       }
516     }
517     return REAL(strcat)(to, from);
518   }
519 
INTERCEPTOR(char *,strncat,char * to,const char * from,uptr size)520 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
521   void *ctx;
522   ASAN_INTERCEPTOR_ENTER(ctx, strncat);
523   AsanInitFromRtl();
524   if (flags()->replace_str) {
525     uptr from_length = MaybeRealStrnlen(from, size);
526     uptr copy_length = Min(size, from_length + 1);
527     ASAN_READ_RANGE(ctx, from, copy_length);
528     uptr to_length = internal_strlen(to);
529     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
530     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
531     if (from_length > 0) {
532       CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
533                            from, copy_length);
534     }
535   }
536   return REAL(strncat)(to, from, size);
537 }
538 
INTERCEPTOR(char *,strcpy,char * to,const char * from)539 INTERCEPTOR(char *, strcpy, char *to, const char *from) {
540   void *ctx;
541   ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
542   if constexpr (SANITIZER_APPLE) {
543     // strcpy is called from malloc_default_purgeable_zone()
544     // in __asan::ReplaceSystemAlloc() on Mac.
545     if (UNLIKELY(!AsanInited()))
546       return REAL(strcpy)(to, from);
547   } else {
548     if (!TryAsanInitFromRtl())
549       return REAL(strcpy)(to, from);
550   }
551 
552   if (flags()->replace_str) {
553     uptr from_size = internal_strlen(from) + 1;
554     CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
555     ASAN_READ_RANGE(ctx, from, from_size);
556     ASAN_WRITE_RANGE(ctx, to, from_size);
557   }
558   return REAL(strcpy)(to, from);
559 }
560 
INTERCEPTOR(char *,strdup,const char * s)561 INTERCEPTOR(char*, strdup, const char *s) {
562   void *ctx;
563   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
564   if (UNLIKELY(!TryAsanInitFromRtl()))
565     return internal_strdup(s);
566   uptr length = internal_strlen(s);
567   if (flags()->replace_str) {
568     ASAN_READ_RANGE(ctx, s, length + 1);
569   }
570   GET_STACK_TRACE_MALLOC;
571   void *new_mem = asan_malloc(length + 1, &stack);
572   if (new_mem) {
573     REAL(memcpy)(new_mem, s, length + 1);
574   }
575   return reinterpret_cast<char*>(new_mem);
576 }
577 
578 #if ASAN_INTERCEPT___STRDUP
INTERCEPTOR(char *,__strdup,const char * s)579 INTERCEPTOR(char*, __strdup, const char *s) {
580   void *ctx;
581   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
582   if (UNLIKELY(!TryAsanInitFromRtl()))
583     return internal_strdup(s);
584   uptr length = internal_strlen(s);
585   if (flags()->replace_str) {
586     ASAN_READ_RANGE(ctx, s, length + 1);
587   }
588   GET_STACK_TRACE_MALLOC;
589   void *new_mem = asan_malloc(length + 1, &stack);
590   if (new_mem) {
591     REAL(memcpy)(new_mem, s, length + 1);
592   }
593   return reinterpret_cast<char*>(new_mem);
594 }
595 #endif // ASAN_INTERCEPT___STRDUP
596 
INTERCEPTOR(char *,strncpy,char * to,const char * from,uptr size)597 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
598   void *ctx;
599   ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
600   AsanInitFromRtl();
601   if (flags()->replace_str) {
602     uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
603     CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
604     ASAN_READ_RANGE(ctx, from, from_size);
605     ASAN_WRITE_RANGE(ctx, to, size);
606   }
607   return REAL(strncpy)(to, from, size);
608 }
609 
610 template <typename Fn>
StrtolImpl(void * ctx,Fn real,const char * nptr,char ** endptr,int base)611 static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
612                                      char **endptr, int base)
613     -> decltype(real(nullptr, nullptr, 0)) {
614   if (!flags()->replace_str)
615     return real(nptr, endptr, base);
616   char *real_endptr;
617   auto res = real(nptr, &real_endptr, base);
618   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
619   return res;
620 }
621 
622 #  define INTERCEPTOR_STRTO_BASE(ret_type, func)                             \
623     INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
624       void *ctx;                                                             \
625       ASAN_INTERCEPTOR_ENTER(ctx, func);                                     \
626       AsanInitFromRtl();                                                     \
627       return StrtolImpl(ctx, REAL(func), nptr, endptr, base);                \
628     }
629 
INTERCEPTOR_STRTO_BASE(long,strtol)630 INTERCEPTOR_STRTO_BASE(long, strtol)
631 INTERCEPTOR_STRTO_BASE(long long, strtoll)
632 
633 #  if SANITIZER_GLIBC
634 INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol)
635 INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll)
636 #  endif
637 
638 INTERCEPTOR(int, atoi, const char *nptr) {
639   void *ctx;
640   ASAN_INTERCEPTOR_ENTER(ctx, atoi);
641   if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
642     return REAL(atoi)(nptr);
643   AsanInitFromRtl();
644   if (!flags()->replace_str) {
645     return REAL(atoi)(nptr);
646   }
647   char *real_endptr;
648   // "man atoi" tells that behavior of atoi(nptr) is the same as
649   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
650   // parsed integer can't be stored in *long* type (even if it's
651   // different from int). So, we just imitate this behavior.
652   int result = REAL(strtol)(nptr, &real_endptr, 10);
653   FixRealStrtolEndptr(nptr, &real_endptr);
654   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
655   return result;
656 }
657 
INTERCEPTOR(long,atol,const char * nptr)658 INTERCEPTOR(long, atol, const char *nptr) {
659   void *ctx;
660   ASAN_INTERCEPTOR_ENTER(ctx, atol);
661   if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
662     return REAL(atol)(nptr);
663   AsanInitFromRtl();
664   if (!flags()->replace_str) {
665     return REAL(atol)(nptr);
666   }
667   char *real_endptr;
668   long result = REAL(strtol)(nptr, &real_endptr, 10);
669   FixRealStrtolEndptr(nptr, &real_endptr);
670   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
671   return result;
672 }
673 
INTERCEPTOR(long long,atoll,const char * nptr)674 INTERCEPTOR(long long, atoll, const char *nptr) {
675   void *ctx;
676   ASAN_INTERCEPTOR_ENTER(ctx, atoll);
677   AsanInitFromRtl();
678   if (!flags()->replace_str) {
679     return REAL(atoll)(nptr);
680   }
681   char *real_endptr;
682   long long result = REAL(strtoll)(nptr, &real_endptr, 10);
683   FixRealStrtolEndptr(nptr, &real_endptr);
684   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
685   return result;
686 }
687 
688 #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
AtCxaAtexit(void * unused)689 static void AtCxaAtexit(void *unused) {
690   (void)unused;
691   StopInitOrderChecking();
692 }
693 #endif
694 
695 #if ASAN_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)696 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
697             void *dso_handle) {
698   if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
699     return REAL(__cxa_atexit)(func, arg, dso_handle);
700   AsanInitFromRtl();
701 #    if CAN_SANITIZE_LEAKS
702   __lsan::ScopedInterceptorDisabler disabler;
703 #endif
704   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
705   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
706   return res;
707 }
708 #endif  // ASAN_INTERCEPT___CXA_ATEXIT
709 
710 #if ASAN_INTERCEPT_ATEXIT
INTERCEPTOR(int,atexit,void (* func)())711 INTERCEPTOR(int, atexit, void (*func)()) {
712   AsanInitFromRtl();
713 #    if CAN_SANITIZE_LEAKS
714   __lsan::ScopedInterceptorDisabler disabler;
715 #endif
716   // Avoid calling real atexit as it is unreachable on at least on Linux.
717   int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
718   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
719   return res;
720 }
721 #endif
722 
723 #if ASAN_INTERCEPT_PTHREAD_ATFORK
724 extern "C" {
725 extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
726                            void (*child)());
727 };
728 
INTERCEPTOR(int,pthread_atfork,void (* prepare)(),void (* parent)(),void (* child)())729 INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
730             void (*child)()) {
731 #if CAN_SANITIZE_LEAKS
732   __lsan::ScopedInterceptorDisabler disabler;
733 #endif
734   // REAL(pthread_atfork) cannot be called due to symbol indirections at least
735   // on NetBSD
736   return _pthread_atfork(prepare, parent, child);
737 }
738 #endif
739 
740 #if ASAN_INTERCEPT_VFORK
741 DEFINE_REAL(int, vfork)
742 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
743 #endif
744 
745 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
746 namespace __asan {
InitializeAsanInterceptors()747 void InitializeAsanInterceptors() {
748   static bool was_called_once;
749   CHECK(!was_called_once);
750   was_called_once = true;
751   InitializePlatformInterceptors();
752   InitializeCommonInterceptors();
753   InitializeSignalInterceptors();
754 
755   // Intercept str* functions.
756   ASAN_INTERCEPT_FUNC(strcat);
757   ASAN_INTERCEPT_FUNC(strcpy);
758   ASAN_INTERCEPT_FUNC(strncat);
759   ASAN_INTERCEPT_FUNC(strncpy);
760   ASAN_INTERCEPT_FUNC(strdup);
761 #if ASAN_INTERCEPT___STRDUP
762   ASAN_INTERCEPT_FUNC(__strdup);
763 #endif
764 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
765   ASAN_INTERCEPT_FUNC(index);
766 #endif
767 
768   ASAN_INTERCEPT_FUNC(atoi);
769   ASAN_INTERCEPT_FUNC(atol);
770   ASAN_INTERCEPT_FUNC(atoll);
771   ASAN_INTERCEPT_FUNC(strtol);
772   ASAN_INTERCEPT_FUNC(strtoll);
773 #  if SANITIZER_GLIBC
774   ASAN_INTERCEPT_FUNC(__isoc23_strtol);
775   ASAN_INTERCEPT_FUNC(__isoc23_strtoll);
776 #  endif
777 
778   // Intecept jump-related functions.
779   ASAN_INTERCEPT_FUNC(longjmp);
780 
781 #  if ASAN_INTERCEPT_SWAPCONTEXT
782   ASAN_INTERCEPT_FUNC(swapcontext);
783   ASAN_INTERCEPT_FUNC(makecontext);
784 #  endif
785 #  if ASAN_INTERCEPT__LONGJMP
786   ASAN_INTERCEPT_FUNC(_longjmp);
787 #endif
788 #if ASAN_INTERCEPT___LONGJMP_CHK
789   ASAN_INTERCEPT_FUNC(__longjmp_chk);
790 #endif
791 #if ASAN_INTERCEPT_SIGLONGJMP
792   ASAN_INTERCEPT_FUNC(siglongjmp);
793 #endif
794 
795   // Intercept exception handling functions.
796 #if ASAN_INTERCEPT___CXA_THROW
797   ASAN_INTERCEPT_FUNC(__cxa_throw);
798 #endif
799 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
800   ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
801 #endif
802   // Indirectly intercept std::rethrow_exception.
803 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
804   ASAN_INTERCEPT_FUNC(_Unwind_RaiseException);
805 #endif
806   // Indirectly intercept std::rethrow_exception.
807 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
808   ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException);
809 #endif
810 
811   // Intercept threading-related functions
812 #if ASAN_INTERCEPT_PTHREAD_CREATE
813 // TODO: this should probably have an unversioned fallback for newer arches?
814 #if defined(ASAN_PTHREAD_CREATE_VERSION)
815   ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
816 #else
817   ASAN_INTERCEPT_FUNC(pthread_create);
818 #endif
819   ASAN_INTERCEPT_FUNC(pthread_join);
820   ASAN_INTERCEPT_FUNC(pthread_detach);
821   ASAN_INTERCEPT_FUNC(pthread_exit);
822 #  endif
823 
824 #  if ASAN_INTERCEPT_TIMEDJOIN
825   ASAN_INTERCEPT_FUNC(pthread_timedjoin_np);
826 #endif
827 
828 #if ASAN_INTERCEPT_TRYJOIN
829   ASAN_INTERCEPT_FUNC(pthread_tryjoin_np);
830 #endif
831 
832   // Intercept atexit function.
833 #if ASAN_INTERCEPT___CXA_ATEXIT
834   ASAN_INTERCEPT_FUNC(__cxa_atexit);
835 #endif
836 
837 #if ASAN_INTERCEPT_ATEXIT
838   ASAN_INTERCEPT_FUNC(atexit);
839 #endif
840 
841 #if ASAN_INTERCEPT_PTHREAD_ATFORK
842   ASAN_INTERCEPT_FUNC(pthread_atfork);
843 #endif
844 
845 #if ASAN_INTERCEPT_VFORK
846   ASAN_INTERCEPT_FUNC(vfork);
847 #endif
848 
849   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
850 }
851 
852 } // namespace __asan
853 
854 #endif  // !SANITIZER_FUCHSIA
855