asan_interceptors.cc revision ae4e6fd0300b13812a02a779619b1a451478cdd1
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- asan_interceptors.cc ----------------------------------------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is a part of AddressSanitizer, an address sanity checker. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Intercept various libc functions. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_interceptors.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "asan_allocator.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "asan_intercepted_functions.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_internal.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_mapping.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_poisoning.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_report.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_stack.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "asan_stats.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "interception/interception.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_common/sanitizer_libc.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace __asan { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if we can quickly decide that the region is unpoisoned. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size == 0) return true; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size <= 32) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !AddressIsPoisoned(beg) && 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !AddressIsPoisoned(beg + size - 1) && 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !AddressIsPoisoned(beg + size / 2); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and ASAN_WRITE_RANGE as macro instead of function so 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that no extra frames are created, and stack trace contains 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// relevant information only. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We check all shadow bytes. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr __offset = (uptr)(offset); \ 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr __size = (uptr)(size); \ 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr __bad = 0; \ 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (__bad = __asan_region_is_poisoned(__offset, __size))) { \ 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_CURRENT_PC_BP_SP; \ 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false) 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Behavior of functions like "memcpy" or "strcpy" is undefined 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if memory intervals overlap. We report error in this case. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Macro is used to avoid creation of new frames. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool RangesOverlap(const char *offset1, uptr length1, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *offset2, uptr length2) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *offset1 = (const char*)_offset1; \ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *offset2 = (const char*)_offset2; \ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RangesOverlap(offset1, length1, offset2, length2)) { \ 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_STACK_TRACE_FATAL_HERE; \ 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \ 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset2, length2, &stack); \ 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define ENSURE_ASAN_INITED() do { \ 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK(!asan_init_is_running); \ 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!asan_inited) { \ 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __asan_init(); \ 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if ASAN_INTERCEPT_STRNLEN 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (REAL(strnlen) != 0) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return REAL(strnlen)(s, maxlen); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return internal_strnlen(s, maxlen); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetThreadName(const char *name) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsanThread *t = GetCurrentThread(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (t) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) asanThreadRegistry().SetThreadName(t->tid(), name); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 97} // namespace __asan 98 99// ---------------------- Wrappers ---------------- {{{1 100using namespace __asan; // NOLINT 101 102#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 103 ASAN_WRITE_RANGE(ptr, size) 104#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) 105#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 106 do { \ 107 if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \ 108 ctx = 0; \ 109 (void) ctx; \ 110 ENSURE_ASAN_INITED(); \ 111 } while (false) 112#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 113 do { \ 114 } while (false) 115#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 116 do { \ 117 } while (false) 118#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 119 do { \ 120 } while (false) 121#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 122#include "sanitizer_common/sanitizer_common_interceptors.inc" 123 124#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s) 125#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s) 126#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 127 do { \ 128 } while (false) 129#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 130 do { \ 131 } while (false) 132#include "sanitizer_common/sanitizer_common_syscalls.inc" 133 134static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 135 AsanThread *t = (AsanThread*)arg; 136 SetCurrentThread(t); 137 return t->ThreadStart(GetTid()); 138} 139 140#if ASAN_INTERCEPT_PTHREAD_CREATE 141extern "C" int pthread_attr_getdetachstate(void *attr, int *v); 142 143INTERCEPTOR(int, pthread_create, void *thread, 144 void *attr, void *(*start_routine)(void*), void *arg) { 145 EnsureMainThreadIDIsCorrect(); 146 // Strict init-order checking in thread-hostile. 147 if (flags()->strict_init_order) 148 StopInitOrderChecking(); 149 GET_STACK_TRACE_THREAD; 150 int detached = 0; 151 if (attr != 0) 152 pthread_attr_getdetachstate(attr, &detached); 153 154 u32 current_tid = GetCurrentTidOrInvalid(); 155 AsanThread *t = AsanThread::Create(start_routine, arg); 156 CreateThreadContextArgs args = { t, &stack }; 157 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 158 return REAL(pthread_create)(thread, attr, asan_thread_start, t); 159} 160#endif // ASAN_INTERCEPT_PTHREAD_CREATE 161 162#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 163INTERCEPTOR(void*, signal, int signum, void *handler) { 164 if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) { 165 return REAL(signal)(signum, handler); 166 } 167 return 0; 168} 169 170INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 171 struct sigaction *oldact) { 172 if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) { 173 return REAL(sigaction)(signum, act, oldact); 174 } 175 return 0; 176} 177#elif SANITIZER_POSIX 178// We need to have defined REAL(sigaction) on posix systems. 179DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 180 struct sigaction *oldact) 181#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 182 183#if ASAN_INTERCEPT_SWAPCONTEXT 184static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 185 // Align to page size. 186 uptr PageSize = GetPageSizeCached(); 187 uptr bottom = stack & ~(PageSize - 1); 188 ssize += stack - bottom; 189 ssize = RoundUpTo(ssize, PageSize); 190 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 191 if (ssize && ssize <= kMaxSaneContextStackSize) { 192 PoisonShadow(bottom, ssize, 0); 193 } 194} 195 196INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 197 struct ucontext_t *ucp) { 198 static bool reported_warning = false; 199 if (!reported_warning) { 200 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 201 "functions and may produce false positives in some cases!\n"); 202 reported_warning = true; 203 } 204 // Clear shadow memory for new context (it may share stack 205 // with current context). 206 uptr stack, ssize; 207 ReadContextStack(ucp, &stack, &ssize); 208 ClearShadowMemoryForContextStack(stack, ssize); 209 int res = REAL(swapcontext)(oucp, ucp); 210 // swapcontext technically does not return, but program may swap context to 211 // "oucp" later, that would look as if swapcontext() returned 0. 212 // We need to clear shadow for ucp once again, as it may be in arbitrary 213 // state. 214 ClearShadowMemoryForContextStack(stack, ssize); 215 return res; 216} 217#endif // ASAN_INTERCEPT_SWAPCONTEXT 218 219INTERCEPTOR(void, longjmp, void *env, int val) { 220 __asan_handle_no_return(); 221 REAL(longjmp)(env, val); 222} 223 224#if ASAN_INTERCEPT__LONGJMP 225INTERCEPTOR(void, _longjmp, void *env, int val) { 226 __asan_handle_no_return(); 227 REAL(_longjmp)(env, val); 228} 229#endif 230 231#if ASAN_INTERCEPT_SIGLONGJMP 232INTERCEPTOR(void, siglongjmp, void *env, int val) { 233 __asan_handle_no_return(); 234 REAL(siglongjmp)(env, val); 235} 236#endif 237 238#if ASAN_INTERCEPT___CXA_THROW 239INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 240 CHECK(REAL(__cxa_throw)); 241 __asan_handle_no_return(); 242 REAL(__cxa_throw)(a, b, c); 243} 244#endif 245 246// intercept mlock and friends. 247// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 248// All functions return 0 (success). 249static void MlockIsUnsupported() { 250 static bool printed = false; 251 if (printed) return; 252 printed = true; 253 if (flags()->verbosity > 0) 254 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n"); 255} 256 257INTERCEPTOR(int, mlock, const void *addr, uptr len) { 258 MlockIsUnsupported(); 259 return 0; 260} 261 262INTERCEPTOR(int, munlock, const void *addr, uptr len) { 263 MlockIsUnsupported(); 264 return 0; 265} 266 267INTERCEPTOR(int, mlockall, int flags) { 268 MlockIsUnsupported(); 269 return 0; 270} 271 272INTERCEPTOR(int, munlockall, void) { 273 MlockIsUnsupported(); 274 return 0; 275} 276 277static inline int CharCmp(unsigned char c1, unsigned char c2) { 278 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 279} 280 281INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 282 if (!asan_inited) return internal_memcmp(a1, a2, size); 283 ENSURE_ASAN_INITED(); 284 if (flags()->replace_intrin) { 285 if (flags()->strict_memcmp) { 286 // Check the entire regions even if the first bytes of the buffers are 287 // different. 288 ASAN_READ_RANGE(a1, size); 289 ASAN_READ_RANGE(a2, size); 290 // Fallthrough to REAL(memcmp) below. 291 } else { 292 unsigned char c1 = 0, c2 = 0; 293 const unsigned char *s1 = (const unsigned char*)a1; 294 const unsigned char *s2 = (const unsigned char*)a2; 295 uptr i; 296 for (i = 0; i < size; i++) { 297 c1 = s1[i]; 298 c2 = s2[i]; 299 if (c1 != c2) break; 300 } 301 ASAN_READ_RANGE(s1, Min(i + 1, size)); 302 ASAN_READ_RANGE(s2, Min(i + 1, size)); 303 return CharCmp(c1, c2); 304 } 305 } 306 return REAL(memcmp(a1, a2, size)); 307} 308 309INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 310 if (!asan_inited) return internal_memcpy(to, from, size); 311 // memcpy is called during __asan_init() from the internals 312 // of printf(...). 313 if (asan_init_is_running) { 314 return REAL(memcpy)(to, from, size); 315 } 316 ENSURE_ASAN_INITED(); 317 if (flags()->replace_intrin) { 318 if (to != from) { 319 // We do not treat memcpy with to==from as a bug. 320 // See http://llvm.org/bugs/show_bug.cgi?id=11763. 321 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 322 } 323 ASAN_READ_RANGE(from, size); 324 ASAN_WRITE_RANGE(to, size); 325 } 326 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 327 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 328 return internal_memcpy(to, from, size); 329} 330 331INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 332 if (!asan_inited) return internal_memmove(to, from, size); 333 if (asan_init_is_running) { 334 return REAL(memmove)(to, from, size); 335 } 336 ENSURE_ASAN_INITED(); 337 if (flags()->replace_intrin) { 338 ASAN_READ_RANGE(from, size); 339 ASAN_WRITE_RANGE(to, size); 340 } 341 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 342 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 343 return internal_memmove(to, from, size); 344} 345 346INTERCEPTOR(void*, memset, void *block, int c, uptr size) { 347 if (!asan_inited) return internal_memset(block, c, size); 348 // memset is called inside Printf. 349 if (asan_init_is_running) { 350 return REAL(memset)(block, c, size); 351 } 352 ENSURE_ASAN_INITED(); 353 if (flags()->replace_intrin) { 354 ASAN_WRITE_RANGE(block, size); 355 } 356 return REAL(memset)(block, c, size); 357} 358 359INTERCEPTOR(char*, strchr, const char *str, int c) { 360 if (!asan_inited) return internal_strchr(str, c); 361 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is 362 // used. 363 if (asan_init_is_running) { 364 return REAL(strchr)(str, c); 365 } 366 ENSURE_ASAN_INITED(); 367 char *result = REAL(strchr)(str, c); 368 if (flags()->replace_str) { 369 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 370 ASAN_READ_RANGE(str, bytes_read); 371 } 372 return result; 373} 374 375#if ASAN_INTERCEPT_INDEX 376# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 377INTERCEPTOR(char*, index, const char *string, int c) 378 ALIAS(WRAPPER_NAME(strchr)); 379# else 380# if SANITIZER_MAC 381DECLARE_REAL(char*, index, const char *string, int c) 382OVERRIDE_FUNCTION(index, strchr); 383# else 384DEFINE_REAL(char*, index, const char *string, int c) 385# endif 386# endif 387#endif // ASAN_INTERCEPT_INDEX 388 389// For both strcat() and strncat() we need to check the validity of |to| 390// argument irrespective of the |from| length. 391INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 392 ENSURE_ASAN_INITED(); 393 if (flags()->replace_str) { 394 uptr from_length = REAL(strlen)(from); 395 ASAN_READ_RANGE(from, from_length + 1); 396 uptr to_length = REAL(strlen)(to); 397 ASAN_READ_RANGE(to, to_length); 398 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 399 // If the copying actually happens, the |from| string should not overlap 400 // with the resulting string starting at |to|, which has a length of 401 // to_length + from_length + 1. 402 if (from_length > 0) { 403 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 404 from, from_length + 1); 405 } 406 } 407 return REAL(strcat)(to, from); // NOLINT 408} 409 410INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 411 ENSURE_ASAN_INITED(); 412 if (flags()->replace_str) { 413 uptr from_length = MaybeRealStrnlen(from, size); 414 uptr copy_length = Min(size, from_length + 1); 415 ASAN_READ_RANGE(from, copy_length); 416 uptr to_length = REAL(strlen)(to); 417 ASAN_READ_RANGE(to, to_length); 418 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 419 if (from_length > 0) { 420 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 421 from, copy_length); 422 } 423 } 424 return REAL(strncat)(to, from, size); 425} 426 427INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 428 if (!asan_inited) return internal_strcmp(s1, s2); 429 if (asan_init_is_running) { 430 return REAL(strcmp)(s1, s2); 431 } 432 ENSURE_ASAN_INITED(); 433 unsigned char c1, c2; 434 uptr i; 435 for (i = 0; ; i++) { 436 c1 = (unsigned char)s1[i]; 437 c2 = (unsigned char)s2[i]; 438 if (c1 != c2 || c1 == '\0') break; 439 } 440 ASAN_READ_RANGE(s1, i + 1); 441 ASAN_READ_RANGE(s2, i + 1); 442 return CharCmp(c1, c2); 443} 444 445INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 446#if SANITIZER_MAC 447 if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT 448#endif 449 // strcpy is called from malloc_default_purgeable_zone() 450 // in __asan::ReplaceSystemAlloc() on Mac. 451 if (asan_init_is_running) { 452 return REAL(strcpy)(to, from); // NOLINT 453 } 454 ENSURE_ASAN_INITED(); 455 if (flags()->replace_str) { 456 uptr from_size = REAL(strlen)(from) + 1; 457 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 458 ASAN_READ_RANGE(from, from_size); 459 ASAN_WRITE_RANGE(to, from_size); 460 } 461 return REAL(strcpy)(to, from); // NOLINT 462} 463 464#if ASAN_INTERCEPT_STRDUP 465INTERCEPTOR(char*, strdup, const char *s) { 466 if (!asan_inited) return internal_strdup(s); 467 ENSURE_ASAN_INITED(); 468 uptr length = REAL(strlen)(s); 469 if (flags()->replace_str) { 470 ASAN_READ_RANGE(s, length + 1); 471 } 472 GET_STACK_TRACE_MALLOC; 473 void *new_mem = asan_malloc(length + 1, &stack); 474 REAL(memcpy)(new_mem, s, length + 1); 475 return reinterpret_cast<char*>(new_mem); 476} 477#endif 478 479INTERCEPTOR(uptr, strlen, const char *s) { 480 if (!asan_inited) return internal_strlen(s); 481 // strlen is called from malloc_default_purgeable_zone() 482 // in __asan::ReplaceSystemAlloc() on Mac. 483 if (asan_init_is_running) { 484 return REAL(strlen)(s); 485 } 486 ENSURE_ASAN_INITED(); 487 uptr length = REAL(strlen)(s); 488 if (flags()->replace_str) { 489 ASAN_READ_RANGE(s, length + 1); 490 } 491 return length; 492} 493 494INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 495 if (!asan_inited) return internal_strncmp(s1, s2, size); 496 // strncmp is called from malloc_default_purgeable_zone() 497 // in __asan::ReplaceSystemAlloc() on Mac. 498 if (asan_init_is_running) { 499 return REAL(strncmp)(s1, s2, size); 500 } 501 ENSURE_ASAN_INITED(); 502 unsigned char c1 = 0, c2 = 0; 503 uptr i; 504 for (i = 0; i < size; i++) { 505 c1 = (unsigned char)s1[i]; 506 c2 = (unsigned char)s2[i]; 507 if (c1 != c2 || c1 == '\0') break; 508 } 509 ASAN_READ_RANGE(s1, Min(i + 1, size)); 510 ASAN_READ_RANGE(s2, Min(i + 1, size)); 511 return CharCmp(c1, c2); 512} 513 514INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 515 ENSURE_ASAN_INITED(); 516 if (flags()->replace_str) { 517 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 518 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 519 ASAN_READ_RANGE(from, from_size); 520 ASAN_WRITE_RANGE(to, size); 521 } 522 return REAL(strncpy)(to, from, size); 523} 524 525#if ASAN_INTERCEPT_STRNLEN 526INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 527 ENSURE_ASAN_INITED(); 528 uptr length = REAL(strnlen)(s, maxlen); 529 if (flags()->replace_str) { 530 ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 531 } 532 return length; 533} 534#endif // ASAN_INTERCEPT_STRNLEN 535 536static inline bool IsValidStrtolBase(int base) { 537 return (base == 0) || (2 <= base && base <= 36); 538} 539 540static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 541 CHECK(endptr); 542 if (nptr == *endptr) { 543 // No digits were found at strtol call, we need to find out the last 544 // symbol accessed by strtoll on our own. 545 // We get this symbol by skipping leading blanks and optional +/- sign. 546 while (IsSpace(*nptr)) nptr++; 547 if (*nptr == '+' || *nptr == '-') nptr++; 548 *endptr = (char*)nptr; 549 } 550 CHECK(*endptr >= nptr); 551} 552 553INTERCEPTOR(long, strtol, const char *nptr, // NOLINT 554 char **endptr, int base) { 555 ENSURE_ASAN_INITED(); 556 if (!flags()->replace_str) { 557 return REAL(strtol)(nptr, endptr, base); 558 } 559 char *real_endptr; 560 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 561 if (endptr != 0) { 562 *endptr = real_endptr; 563 } 564 if (IsValidStrtolBase(base)) { 565 FixRealStrtolEndptr(nptr, &real_endptr); 566 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 567 } 568 return result; 569} 570 571INTERCEPTOR(int, atoi, const char *nptr) { 572#if SANITIZER_MAC 573 if (!asan_inited) return REAL(atoi)(nptr); 574#endif 575 ENSURE_ASAN_INITED(); 576 if (!flags()->replace_str) { 577 return REAL(atoi)(nptr); 578 } 579 char *real_endptr; 580 // "man atoi" tells that behavior of atoi(nptr) is the same as 581 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 582 // parsed integer can't be stored in *long* type (even if it's 583 // different from int). So, we just imitate this behavior. 584 int result = REAL(strtol)(nptr, &real_endptr, 10); 585 FixRealStrtolEndptr(nptr, &real_endptr); 586 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 587 return result; 588} 589 590INTERCEPTOR(long, atol, const char *nptr) { // NOLINT 591#if SANITIZER_MAC 592 if (!asan_inited) return REAL(atol)(nptr); 593#endif 594 ENSURE_ASAN_INITED(); 595 if (!flags()->replace_str) { 596 return REAL(atol)(nptr); 597 } 598 char *real_endptr; 599 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 600 FixRealStrtolEndptr(nptr, &real_endptr); 601 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 602 return result; 603} 604 605#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 606INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 607 char **endptr, int base) { 608 ENSURE_ASAN_INITED(); 609 if (!flags()->replace_str) { 610 return REAL(strtoll)(nptr, endptr, base); 611 } 612 char *real_endptr; 613 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 614 if (endptr != 0) { 615 *endptr = real_endptr; 616 } 617 // If base has unsupported value, strtoll can exit with EINVAL 618 // without reading any characters. So do additional checks only 619 // if base is valid. 620 if (IsValidStrtolBase(base)) { 621 FixRealStrtolEndptr(nptr, &real_endptr); 622 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 623 } 624 return result; 625} 626 627INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 628 ENSURE_ASAN_INITED(); 629 if (!flags()->replace_str) { 630 return REAL(atoll)(nptr); 631 } 632 char *real_endptr; 633 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 634 FixRealStrtolEndptr(nptr, &real_endptr); 635 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 636 return result; 637} 638#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 639 640static void AtCxaAtexit(void *unused) { 641 (void)unused; 642 StopInitOrderChecking(); 643} 644 645#if ASAN_INTERCEPT___CXA_ATEXIT 646INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 647 void *dso_handle) { 648 ENSURE_ASAN_INITED(); 649 int res = REAL(__cxa_atexit)(func, arg, dso_handle); 650 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0); 651 return res; 652} 653#endif // ASAN_INTERCEPT___CXA_ATEXIT 654 655#if !SANITIZER_MAC 656#define ASAN_INTERCEPT_FUNC(name) do { \ 657 if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \ 658 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 659 } while (0) 660#else 661// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. 662#define ASAN_INTERCEPT_FUNC(name) 663#endif // SANITIZER_MAC 664 665#if SANITIZER_WINDOWS 666INTERCEPTOR_WINAPI(DWORD, CreateThread, 667 void* security, uptr stack_size, 668 DWORD (__stdcall *start_routine)(void*), void* arg, 669 DWORD thr_flags, void* tid) { 670 // Strict init-order checking in thread-hostile. 671 if (flags()->strict_init_order) 672 StopInitOrderChecking(); 673 GET_STACK_TRACE_THREAD; 674 u32 current_tid = GetCurrentTidOrInvalid(); 675 AsanThread *t = AsanThread::Create(start_routine, arg); 676 CreateThreadContextArgs args = { t, &stack }; 677 bool detached = false; // FIXME: how can we determine it on Windows? 678 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 679 return REAL(CreateThread)(security, stack_size, 680 asan_thread_start, t, thr_flags, tid); 681} 682 683namespace __asan { 684void InitializeWindowsInterceptors() { 685 ASAN_INTERCEPT_FUNC(CreateThread); 686} 687 688} // namespace __asan 689#endif 690 691// ---------------------- InitializeAsanInterceptors ---------------- {{{1 692namespace __asan { 693void InitializeAsanInterceptors() { 694 static bool was_called_once; 695 CHECK(was_called_once == false); 696 was_called_once = true; 697 SANITIZER_COMMON_INTERCEPTORS_INIT; 698 699 // Intercept mem* functions. 700 ASAN_INTERCEPT_FUNC(memcmp); 701 ASAN_INTERCEPT_FUNC(memmove); 702 ASAN_INTERCEPT_FUNC(memset); 703 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 704 ASAN_INTERCEPT_FUNC(memcpy); 705 } 706 707 // Intercept str* functions. 708 ASAN_INTERCEPT_FUNC(strcat); // NOLINT 709 ASAN_INTERCEPT_FUNC(strchr); 710 ASAN_INTERCEPT_FUNC(strcmp); 711 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 712 ASAN_INTERCEPT_FUNC(strlen); 713 ASAN_INTERCEPT_FUNC(strncat); 714 ASAN_INTERCEPT_FUNC(strncmp); 715 ASAN_INTERCEPT_FUNC(strncpy); 716#if ASAN_INTERCEPT_STRDUP 717 ASAN_INTERCEPT_FUNC(strdup); 718#endif 719#if ASAN_INTERCEPT_STRNLEN 720 ASAN_INTERCEPT_FUNC(strnlen); 721#endif 722#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 723 ASAN_INTERCEPT_FUNC(index); 724#endif 725 726 ASAN_INTERCEPT_FUNC(atoi); 727 ASAN_INTERCEPT_FUNC(atol); 728 ASAN_INTERCEPT_FUNC(strtol); 729#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 730 ASAN_INTERCEPT_FUNC(atoll); 731 ASAN_INTERCEPT_FUNC(strtoll); 732#endif 733 734#if ASAN_INTERCEPT_MLOCKX 735 // Intercept mlock/munlock. 736 ASAN_INTERCEPT_FUNC(mlock); 737 ASAN_INTERCEPT_FUNC(munlock); 738 ASAN_INTERCEPT_FUNC(mlockall); 739 ASAN_INTERCEPT_FUNC(munlockall); 740#endif 741 742 // Intecept signal- and jump-related functions. 743 ASAN_INTERCEPT_FUNC(longjmp); 744#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 745 ASAN_INTERCEPT_FUNC(sigaction); 746 ASAN_INTERCEPT_FUNC(signal); 747#endif 748#if ASAN_INTERCEPT_SWAPCONTEXT 749 ASAN_INTERCEPT_FUNC(swapcontext); 750#endif 751#if ASAN_INTERCEPT__LONGJMP 752 ASAN_INTERCEPT_FUNC(_longjmp); 753#endif 754#if ASAN_INTERCEPT_SIGLONGJMP 755 ASAN_INTERCEPT_FUNC(siglongjmp); 756#endif 757 758 // Intercept exception handling functions. 759#if ASAN_INTERCEPT___CXA_THROW 760 INTERCEPT_FUNCTION(__cxa_throw); 761#endif 762 763 // Intercept threading-related functions 764#if ASAN_INTERCEPT_PTHREAD_CREATE 765 ASAN_INTERCEPT_FUNC(pthread_create); 766#endif 767 768 // Intercept atexit function. 769#if ASAN_INTERCEPT___CXA_ATEXIT 770 ASAN_INTERCEPT_FUNC(__cxa_atexit); 771#endif 772 773 // Some Windows-specific interceptors. 774#if SANITIZER_WINDOWS 775 InitializeWindowsInterceptors(); 776#endif 777 778 if (flags()->verbosity > 0) { 779 Report("AddressSanitizer: libc interceptors initialized\n"); 780 } 781} 782 783} // namespace __asan 784