1353944Sdim//===-- msan_interceptors.cpp ---------------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// This file is a part of MemorySanitizer. 10353944Sdim// 11353944Sdim// Interceptors for standard library functions. 12353944Sdim// 13353944Sdim// FIXME: move as many interceptors as possible into 14353944Sdim// sanitizer_common/sanitizer_common_interceptors.h 15353944Sdim//===----------------------------------------------------------------------===// 16353944Sdim 17353944Sdim#include "interception/interception.h" 18353944Sdim#include "msan.h" 19353944Sdim#include "msan_chained_origin_depot.h" 20353944Sdim#include "msan_origin.h" 21353944Sdim#include "msan_report.h" 22353944Sdim#include "msan_thread.h" 23353944Sdim#include "msan_poisoning.h" 24353944Sdim#include "sanitizer_common/sanitizer_platform_limits_posix.h" 25353944Sdim#include "sanitizer_common/sanitizer_platform_limits_netbsd.h" 26353944Sdim#include "sanitizer_common/sanitizer_allocator.h" 27353944Sdim#include "sanitizer_common/sanitizer_allocator_interface.h" 28353944Sdim#include "sanitizer_common/sanitizer_allocator_internal.h" 29353944Sdim#include "sanitizer_common/sanitizer_atomic.h" 30353944Sdim#include "sanitizer_common/sanitizer_common.h" 31353944Sdim#include "sanitizer_common/sanitizer_errno.h" 32353944Sdim#include "sanitizer_common/sanitizer_stackdepot.h" 33353944Sdim#include "sanitizer_common/sanitizer_libc.h" 34353944Sdim#include "sanitizer_common/sanitizer_linux.h" 35353944Sdim#include "sanitizer_common/sanitizer_tls_get_addr.h" 36353944Sdim#include "sanitizer_common/sanitizer_vector.h" 37353944Sdim 38353944Sdim#if SANITIZER_NETBSD 39353944Sdim#define fstat __fstat50 40353944Sdim#define gettimeofday __gettimeofday50 41353944Sdim#define getrusage __getrusage50 42353944Sdim#define tzset __tzset50 43353944Sdim#endif 44353944Sdim 45353944Sdim#include <stdarg.h> 46353944Sdim// ACHTUNG! No other system header includes in this file. 47353944Sdim// Ideally, we should get rid of stdarg.h as well. 48353944Sdim 49353944Sdimusing namespace __msan; 50353944Sdim 51353944Sdimusing __sanitizer::memory_order; 52353944Sdimusing __sanitizer::atomic_load; 53353944Sdimusing __sanitizer::atomic_store; 54353944Sdimusing __sanitizer::atomic_uintptr_t; 55353944Sdim 56353944SdimDECLARE_REAL(SIZE_T, strlen, const char *s) 57353944SdimDECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen) 58353944SdimDECLARE_REAL(void *, memcpy, void *dest, const void *src, uptr n) 59353944SdimDECLARE_REAL(void *, memset, void *dest, int c, uptr n) 60353944Sdim 61353944Sdim// True if this is a nested interceptor. 62353944Sdimstatic THREADLOCAL int in_interceptor_scope; 63353944Sdim 64353944Sdimvoid __msan_scoped_disable_interceptor_checks() { ++in_interceptor_scope; } 65353944Sdimvoid __msan_scoped_enable_interceptor_checks() { --in_interceptor_scope; } 66353944Sdim 67353944Sdimstruct InterceptorScope { 68353944Sdim InterceptorScope() { ++in_interceptor_scope; } 69353944Sdim ~InterceptorScope() { --in_interceptor_scope; } 70353944Sdim}; 71353944Sdim 72353944Sdimbool IsInInterceptorScope() { 73353944Sdim return in_interceptor_scope; 74353944Sdim} 75353944Sdim 76353944Sdimstatic uptr allocated_for_dlsym; 77353944Sdimstatic const uptr kDlsymAllocPoolSize = 1024; 78353944Sdimstatic uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; 79353944Sdim 80353944Sdimstatic bool IsInDlsymAllocPool(const void *ptr) { 81353944Sdim uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym; 82353944Sdim return off < sizeof(alloc_memory_for_dlsym); 83353944Sdim} 84353944Sdim 85353944Sdimstatic void *AllocateFromLocalPool(uptr size_in_bytes) { 86353944Sdim uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; 87353944Sdim void *mem = (void *)&alloc_memory_for_dlsym[allocated_for_dlsym]; 88353944Sdim allocated_for_dlsym += size_in_words; 89353944Sdim CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); 90353944Sdim return mem; 91353944Sdim} 92353944Sdim 93353944Sdim#define ENSURE_MSAN_INITED() do { \ 94353944Sdim CHECK(!msan_init_is_running); \ 95353944Sdim if (!msan_inited) { \ 96353944Sdim __msan_init(); \ 97353944Sdim } \ 98353944Sdim} while (0) 99353944Sdim 100353944Sdim// Check that [x, x+n) range is unpoisoned. 101353944Sdim#define CHECK_UNPOISONED_0(x, n) \ 102353944Sdim do { \ 103353944Sdim sptr __offset = __msan_test_shadow(x, n); \ 104353944Sdim if (__msan::IsInSymbolizer()) break; \ 105353944Sdim if (__offset >= 0 && __msan::flags()->report_umrs) { \ 106353944Sdim GET_CALLER_PC_BP_SP; \ 107353944Sdim (void)sp; \ 108353944Sdim ReportUMRInsideAddressRange(__func__, x, n, __offset); \ 109353944Sdim __msan::PrintWarningWithOrigin( \ 110353944Sdim pc, bp, __msan_get_origin((const char *)x + __offset)); \ 111353944Sdim if (__msan::flags()->halt_on_error) { \ 112353944Sdim Printf("Exiting\n"); \ 113353944Sdim Die(); \ 114353944Sdim } \ 115353944Sdim } \ 116353944Sdim } while (0) 117353944Sdim 118353944Sdim// Check that [x, x+n) range is unpoisoned unless we are in a nested 119353944Sdim// interceptor. 120353944Sdim#define CHECK_UNPOISONED(x, n) \ 121353944Sdim do { \ 122353944Sdim if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \ 123353944Sdim } while (0) 124353944Sdim 125353944Sdim#define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \ 126353944Sdim CHECK_UNPOISONED((x), \ 127353944Sdim common_flags()->strict_string_checks ? (len) + 1 : (n) ) 128353944Sdim 129353944Sdim#define CHECK_UNPOISONED_STRING(x, n) \ 130353944Sdim CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n)) 131353944Sdim 132353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 133353944SdimINTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb, 134353944Sdim void *file) { 135353944Sdim ENSURE_MSAN_INITED(); 136353944Sdim SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file); 137353944Sdim if (res > 0) 138353944Sdim __msan_unpoison(ptr, res *size); 139353944Sdim return res; 140353944Sdim} 141353944Sdim#define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked) 142353944Sdim#else 143353944Sdim#define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED 144353944Sdim#endif 145353944Sdim 146353944Sdim#if !SANITIZER_NETBSD 147353944SdimINTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) { 148353944Sdim return (char *)__msan_memcpy(dest, src, n) + n; 149353944Sdim} 150353944Sdim#define MSAN_MAYBE_INTERCEPT_MEMPCPY INTERCEPT_FUNCTION(mempcpy) 151353944Sdim#else 152353944Sdim#define MSAN_MAYBE_INTERCEPT_MEMPCPY 153353944Sdim#endif 154353944Sdim 155353944SdimINTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) { 156353944Sdim ENSURE_MSAN_INITED(); 157353944Sdim void *res = REAL(memccpy)(dest, src, c, n); 158353944Sdim CHECK(!res || (res >= dest && res <= (char *)dest + n)); 159353944Sdim SIZE_T sz = res ? (char *)res - (char *)dest : n; 160353944Sdim CHECK_UNPOISONED(src, sz); 161353944Sdim __msan_unpoison(dest, sz); 162353944Sdim return res; 163353944Sdim} 164353944Sdim 165353944SdimINTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) { 166353944Sdim return __msan_memmove(dest, src, n); 167353944Sdim} 168353944Sdim 169353944SdimINTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) { 170353944Sdim GET_MALLOC_STACK_TRACE; 171353944Sdim CHECK_NE(memptr, 0); 172353944Sdim int res = msan_posix_memalign(memptr, alignment, size, &stack); 173353944Sdim if (!res) 174353944Sdim __msan_unpoison(memptr, sizeof(*memptr)); 175353944Sdim return res; 176353944Sdim} 177353944Sdim 178353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 179353944SdimINTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) { 180353944Sdim GET_MALLOC_STACK_TRACE; 181353944Sdim return msan_memalign(alignment, size, &stack); 182353944Sdim} 183353944Sdim#define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign) 184353944Sdim#else 185353944Sdim#define MSAN_MAYBE_INTERCEPT_MEMALIGN 186353944Sdim#endif 187353944Sdim 188353944SdimINTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) { 189353944Sdim GET_MALLOC_STACK_TRACE; 190353944Sdim return msan_aligned_alloc(alignment, size, &stack); 191353944Sdim} 192353944Sdim 193353944Sdim#if !SANITIZER_NETBSD 194353944SdimINTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) { 195353944Sdim GET_MALLOC_STACK_TRACE; 196353944Sdim void *ptr = msan_memalign(alignment, size, &stack); 197353944Sdim if (ptr) 198353944Sdim DTLS_on_libc_memalign(ptr, size); 199353944Sdim return ptr; 200353944Sdim} 201353944Sdim#define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign) 202353944Sdim#else 203353944Sdim#define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN 204353944Sdim#endif 205353944Sdim 206353944SdimINTERCEPTOR(void *, valloc, SIZE_T size) { 207353944Sdim GET_MALLOC_STACK_TRACE; 208353944Sdim return msan_valloc(size, &stack); 209353944Sdim} 210353944Sdim 211353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 212353944SdimINTERCEPTOR(void *, pvalloc, SIZE_T size) { 213353944Sdim GET_MALLOC_STACK_TRACE; 214353944Sdim return msan_pvalloc(size, &stack); 215353944Sdim} 216353944Sdim#define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc) 217353944Sdim#else 218353944Sdim#define MSAN_MAYBE_INTERCEPT_PVALLOC 219353944Sdim#endif 220353944Sdim 221353944SdimINTERCEPTOR(void, free, void *ptr) { 222353944Sdim GET_MALLOC_STACK_TRACE; 223353944Sdim if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return; 224353944Sdim MsanDeallocate(&stack, ptr); 225353944Sdim} 226353944Sdim 227353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 228353944SdimINTERCEPTOR(void, cfree, void *ptr) { 229353944Sdim GET_MALLOC_STACK_TRACE; 230353944Sdim if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return; 231353944Sdim MsanDeallocate(&stack, ptr); 232353944Sdim} 233353944Sdim#define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree) 234353944Sdim#else 235353944Sdim#define MSAN_MAYBE_INTERCEPT_CFREE 236353944Sdim#endif 237353944Sdim 238353944Sdim#if !SANITIZER_NETBSD 239353944SdimINTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 240353944Sdim return __sanitizer_get_allocated_size(ptr); 241353944Sdim} 242353944Sdim#define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \ 243353944Sdim INTERCEPT_FUNCTION(malloc_usable_size) 244353944Sdim#else 245353944Sdim#define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE 246353944Sdim#endif 247353944Sdim 248353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 249353944Sdim// This function actually returns a struct by value, but we can't unpoison a 250353944Sdim// temporary! The following is equivalent on all supported platforms but 251353944Sdim// aarch64 (which uses a different register for sret value). We have a test 252353944Sdim// to confirm that. 253353944SdimINTERCEPTOR(void, mallinfo, __sanitizer_struct_mallinfo *sret) { 254353944Sdim#ifdef __aarch64__ 255353944Sdim uptr r8; 256353944Sdim asm volatile("mov %0,x8" : "=r" (r8)); 257353944Sdim sret = reinterpret_cast<__sanitizer_struct_mallinfo*>(r8); 258353944Sdim#endif 259353944Sdim REAL(memset)(sret, 0, sizeof(*sret)); 260353944Sdim __msan_unpoison(sret, sizeof(*sret)); 261353944Sdim} 262353944Sdim#define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo) 263353944Sdim#else 264353944Sdim#define MSAN_MAYBE_INTERCEPT_MALLINFO 265353944Sdim#endif 266353944Sdim 267353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 268353944SdimINTERCEPTOR(int, mallopt, int cmd, int value) { 269353944Sdim return 0; 270353944Sdim} 271353944Sdim#define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt) 272353944Sdim#else 273353944Sdim#define MSAN_MAYBE_INTERCEPT_MALLOPT 274353944Sdim#endif 275353944Sdim 276353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 277353944SdimINTERCEPTOR(void, malloc_stats, void) { 278353944Sdim // FIXME: implement, but don't call REAL(malloc_stats)! 279353944Sdim} 280353944Sdim#define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats) 281353944Sdim#else 282353944Sdim#define MSAN_MAYBE_INTERCEPT_MALLOC_STATS 283353944Sdim#endif 284353944Sdim 285353944SdimINTERCEPTOR(char *, strcpy, char *dest, const char *src) { 286353944Sdim ENSURE_MSAN_INITED(); 287353944Sdim GET_STORE_STACK_TRACE; 288353944Sdim SIZE_T n = REAL(strlen)(src); 289353944Sdim CHECK_UNPOISONED_STRING(src + n, 0); 290353944Sdim char *res = REAL(strcpy)(dest, src); 291353944Sdim CopyShadowAndOrigin(dest, src, n + 1, &stack); 292353944Sdim return res; 293353944Sdim} 294353944Sdim 295353944SdimINTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) { 296353944Sdim ENSURE_MSAN_INITED(); 297353944Sdim GET_STORE_STACK_TRACE; 298353944Sdim SIZE_T copy_size = REAL(strnlen)(src, n); 299353944Sdim if (copy_size < n) 300353944Sdim copy_size++; // trailing \0 301353944Sdim char *res = REAL(strncpy)(dest, src, n); 302353944Sdim CopyShadowAndOrigin(dest, src, copy_size, &stack); 303353944Sdim __msan_unpoison(dest + copy_size, n - copy_size); 304353944Sdim return res; 305353944Sdim} 306353944Sdim 307353944Sdim#if !SANITIZER_NETBSD 308353944SdimINTERCEPTOR(char *, stpcpy, char *dest, const char *src) { 309353944Sdim ENSURE_MSAN_INITED(); 310353944Sdim GET_STORE_STACK_TRACE; 311353944Sdim SIZE_T n = REAL(strlen)(src); 312353944Sdim CHECK_UNPOISONED_STRING(src + n, 0); 313353944Sdim char *res = REAL(stpcpy)(dest, src); 314353944Sdim CopyShadowAndOrigin(dest, src, n + 1, &stack); 315353944Sdim return res; 316353944Sdim} 317353944Sdim#define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy) 318353944Sdim#else 319353944Sdim#define MSAN_MAYBE_INTERCEPT_STPCPY 320353944Sdim#endif 321353944Sdim 322353944SdimINTERCEPTOR(char *, strdup, char *src) { 323353944Sdim ENSURE_MSAN_INITED(); 324353944Sdim GET_STORE_STACK_TRACE; 325353944Sdim // On FreeBSD strdup() leverages strlen(). 326353944Sdim InterceptorScope interceptor_scope; 327353944Sdim SIZE_T n = REAL(strlen)(src); 328353944Sdim CHECK_UNPOISONED_STRING(src + n, 0); 329353944Sdim char *res = REAL(strdup)(src); 330353944Sdim CopyShadowAndOrigin(res, src, n + 1, &stack); 331353944Sdim return res; 332353944Sdim} 333353944Sdim 334353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 335353944SdimINTERCEPTOR(char *, __strdup, char *src) { 336353944Sdim ENSURE_MSAN_INITED(); 337353944Sdim GET_STORE_STACK_TRACE; 338353944Sdim SIZE_T n = REAL(strlen)(src); 339353944Sdim CHECK_UNPOISONED_STRING(src + n, 0); 340353944Sdim char *res = REAL(__strdup)(src); 341353944Sdim CopyShadowAndOrigin(res, src, n + 1, &stack); 342353944Sdim return res; 343353944Sdim} 344353944Sdim#define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup) 345353944Sdim#else 346353944Sdim#define MSAN_MAYBE_INTERCEPT___STRDUP 347353944Sdim#endif 348353944Sdim 349353944Sdim#if !SANITIZER_NETBSD 350353944SdimINTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) { 351353944Sdim ENSURE_MSAN_INITED(); 352353944Sdim char *res = REAL(gcvt)(number, ndigit, buf); 353353944Sdim SIZE_T n = REAL(strlen)(buf); 354353944Sdim __msan_unpoison(buf, n + 1); 355353944Sdim return res; 356353944Sdim} 357353944Sdim#define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt) 358353944Sdim#else 359353944Sdim#define MSAN_MAYBE_INTERCEPT_GCVT 360353944Sdim#endif 361353944Sdim 362353944SdimINTERCEPTOR(char *, strcat, char *dest, const char *src) { 363353944Sdim ENSURE_MSAN_INITED(); 364353944Sdim GET_STORE_STACK_TRACE; 365353944Sdim SIZE_T src_size = REAL(strlen)(src); 366353944Sdim SIZE_T dest_size = REAL(strlen)(dest); 367353944Sdim CHECK_UNPOISONED_STRING(src + src_size, 0); 368353944Sdim CHECK_UNPOISONED_STRING(dest + dest_size, 0); 369353944Sdim char *res = REAL(strcat)(dest, src); 370353944Sdim CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack); 371353944Sdim return res; 372353944Sdim} 373353944Sdim 374353944SdimINTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { 375353944Sdim ENSURE_MSAN_INITED(); 376353944Sdim GET_STORE_STACK_TRACE; 377353944Sdim SIZE_T dest_size = REAL(strlen)(dest); 378353944Sdim SIZE_T copy_size = REAL(strnlen)(src, n); 379353944Sdim CHECK_UNPOISONED_STRING(dest + dest_size, 0); 380353944Sdim char *res = REAL(strncat)(dest, src, n); 381353944Sdim CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack); 382353944Sdim __msan_unpoison(dest + dest_size + copy_size, 1); // \0 383353944Sdim return res; 384353944Sdim} 385353944Sdim 386353944Sdim// Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to 387353944Sdim// deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO. 388353944Sdim#define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \ 389353944Sdim ENSURE_MSAN_INITED(); \ 390353944Sdim ret_type res = REAL(func)(__VA_ARGS__); \ 391353944Sdim __msan_unpoison(endptr, sizeof(*endptr)); \ 392353944Sdim return res; 393353944Sdim 394353944Sdim#define INTERCEPTOR_STRTO(ret_type, func, char_type) \ 395353944Sdim INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \ 396353944Sdim INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \ 397353944Sdim } 398353944Sdim 399353944Sdim#define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \ 400353944Sdim INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \ 401353944Sdim int base) { \ 402353944Sdim INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \ 403353944Sdim } 404353944Sdim 405353944Sdim#define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \ 406353944Sdim INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \ 407353944Sdim void *loc) { \ 408353944Sdim INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \ 409353944Sdim } 410353944Sdim 411353944Sdim#define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \ 412353944Sdim INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \ 413353944Sdim int base, void *loc) { \ 414353944Sdim INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \ 415353944Sdim } 416353944Sdim 417353944Sdim#if SANITIZER_NETBSD 418353944Sdim#define INTERCEPTORS_STRTO(ret_type, func, char_type) \ 419353944Sdim INTERCEPTOR_STRTO(ret_type, func, char_type) \ 420353944Sdim INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) 421353944Sdim 422353944Sdim#define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \ 423353944Sdim INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \ 424353944Sdim INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) 425353944Sdim 426353944Sdim#else 427353944Sdim#define INTERCEPTORS_STRTO(ret_type, func, char_type) \ 428353944Sdim INTERCEPTOR_STRTO(ret_type, func, char_type) \ 429353944Sdim INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \ 430353944Sdim INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \ 431353944Sdim INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type) 432353944Sdim 433353944Sdim#define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \ 434353944Sdim INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \ 435353944Sdim INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \ 436353944Sdim INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \ 437353944Sdim INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type) 438353944Sdim#endif 439353944Sdim 440353944SdimINTERCEPTORS_STRTO(double, strtod, char) 441353944SdimINTERCEPTORS_STRTO(float, strtof, char) 442353944SdimINTERCEPTORS_STRTO(long double, strtold, char) 443353944SdimINTERCEPTORS_STRTO_BASE(long, strtol, char) 444353944SdimINTERCEPTORS_STRTO_BASE(long long, strtoll, char) 445353944SdimINTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char) 446353944SdimINTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char) 447353944SdimINTERCEPTORS_STRTO_BASE(u64, strtouq, char) 448353944Sdim 449353944SdimINTERCEPTORS_STRTO(double, wcstod, wchar_t) 450353944SdimINTERCEPTORS_STRTO(float, wcstof, wchar_t) 451353944SdimINTERCEPTORS_STRTO(long double, wcstold, wchar_t) 452353944SdimINTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t) 453353944SdimINTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t) 454353944SdimINTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t) 455353944SdimINTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t) 456353944Sdim 457353944Sdim#if SANITIZER_NETBSD 458353944Sdim#define INTERCEPT_STRTO(func) \ 459353944Sdim INTERCEPT_FUNCTION(func); \ 460353944Sdim INTERCEPT_FUNCTION(func##_l); 461353944Sdim#else 462353944Sdim#define INTERCEPT_STRTO(func) \ 463353944Sdim INTERCEPT_FUNCTION(func); \ 464353944Sdim INTERCEPT_FUNCTION(func##_l); \ 465353944Sdim INTERCEPT_FUNCTION(__##func##_l); \ 466353944Sdim INTERCEPT_FUNCTION(__##func##_internal); 467353944Sdim#endif 468353944Sdim 469353944Sdim 470353944Sdim// FIXME: support *wprintf in common format interceptors. 471353944SdimINTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) { 472353944Sdim ENSURE_MSAN_INITED(); 473353944Sdim int res = REAL(vswprintf)(str, size, format, ap); 474353944Sdim if (res >= 0) { 475353944Sdim __msan_unpoison(str, 4 * (res + 1)); 476353944Sdim } 477353944Sdim return res; 478353944Sdim} 479353944Sdim 480353944SdimINTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) { 481353944Sdim ENSURE_MSAN_INITED(); 482353944Sdim va_list ap; 483353944Sdim va_start(ap, format); 484353944Sdim int res = vswprintf(str, size, format, ap); 485353944Sdim va_end(ap); 486353944Sdim return res; 487353944Sdim} 488353944Sdim 489353944Sdim#define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \ 490353944Sdim ENSURE_MSAN_INITED(); \ 491353944Sdim InterceptorScope interceptor_scope; \ 492353944Sdim ret_type res = REAL(func)(s, __VA_ARGS__); \ 493353944Sdim if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \ 494353944Sdim return res; 495353944Sdim 496353944SdimINTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format, 497353944Sdim __sanitizer_tm *tm) { 498353944Sdim INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm); 499353944Sdim} 500353944Sdim 501353944SdimINTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format, 502353944Sdim __sanitizer_tm *tm, void *loc) { 503353944Sdim INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc); 504353944Sdim} 505353944Sdim 506353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 507353944SdimINTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format, 508353944Sdim __sanitizer_tm *tm, void *loc) { 509353944Sdim INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm, 510353944Sdim loc); 511353944Sdim} 512353944Sdim#define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l) 513353944Sdim#else 514353944Sdim#define MSAN_MAYBE_INTERCEPT___STRFTIME_L 515353944Sdim#endif 516353944Sdim 517353944SdimINTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format, 518353944Sdim __sanitizer_tm *tm) { 519353944Sdim INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm); 520353944Sdim} 521353944Sdim 522353944SdimINTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format, 523353944Sdim __sanitizer_tm *tm, void *loc) { 524353944Sdim INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm, 525353944Sdim loc); 526353944Sdim} 527353944Sdim 528353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 529353944SdimINTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format, 530353944Sdim __sanitizer_tm *tm, void *loc) { 531353944Sdim INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm, 532353944Sdim loc); 533353944Sdim} 534353944Sdim#define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l) 535353944Sdim#else 536353944Sdim#define MSAN_MAYBE_INTERCEPT___WCSFTIME_L 537353944Sdim#endif 538353944Sdim 539353944SdimINTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) { 540353944Sdim ENSURE_MSAN_INITED(); 541353944Sdim int res = REAL(mbtowc)(dest, src, n); 542353944Sdim if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t)); 543353944Sdim return res; 544353944Sdim} 545353944Sdim 546353944SdimINTERCEPTOR(SIZE_T, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, 547353944Sdim void *ps) { 548353944Sdim ENSURE_MSAN_INITED(); 549353944Sdim SIZE_T res = REAL(mbrtowc)(dest, src, n, ps); 550353944Sdim if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t)); 551353944Sdim return res; 552353944Sdim} 553353944Sdim 554353944Sdim// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n); 555353944SdimINTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { 556353944Sdim ENSURE_MSAN_INITED(); 557353944Sdim GET_STORE_STACK_TRACE; 558353944Sdim wchar_t *res = REAL(wmemcpy)(dest, src, n); 559353944Sdim CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack); 560353944Sdim return res; 561353944Sdim} 562353944Sdim 563353944Sdim#if !SANITIZER_NETBSD 564353944SdimINTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { 565353944Sdim ENSURE_MSAN_INITED(); 566353944Sdim GET_STORE_STACK_TRACE; 567353944Sdim wchar_t *res = REAL(wmempcpy)(dest, src, n); 568353944Sdim CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack); 569353944Sdim return res; 570353944Sdim} 571353944Sdim#define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy) 572353944Sdim#else 573353944Sdim#define MSAN_MAYBE_INTERCEPT_WMEMPCPY 574353944Sdim#endif 575353944Sdim 576353944SdimINTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) { 577353944Sdim CHECK(MEM_IS_APP(s)); 578353944Sdim ENSURE_MSAN_INITED(); 579353944Sdim wchar_t *res = REAL(wmemset)(s, c, n); 580353944Sdim __msan_unpoison(s, n * sizeof(wchar_t)); 581353944Sdim return res; 582353944Sdim} 583353944Sdim 584353944SdimINTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) { 585353944Sdim ENSURE_MSAN_INITED(); 586353944Sdim GET_STORE_STACK_TRACE; 587353944Sdim wchar_t *res = REAL(wmemmove)(dest, src, n); 588353944Sdim MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack); 589353944Sdim return res; 590353944Sdim} 591353944Sdim 592353944SdimINTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) { 593353944Sdim ENSURE_MSAN_INITED(); 594353944Sdim int res = REAL(wcscmp)(s1, s2); 595353944Sdim return res; 596353944Sdim} 597353944Sdim 598353944SdimINTERCEPTOR(int, gettimeofday, void *tv, void *tz) { 599353944Sdim ENSURE_MSAN_INITED(); 600353944Sdim int res = REAL(gettimeofday)(tv, tz); 601353944Sdim if (tv) 602353944Sdim __msan_unpoison(tv, 16); 603353944Sdim if (tz) 604353944Sdim __msan_unpoison(tz, 8); 605353944Sdim return res; 606353944Sdim} 607353944Sdim 608353944Sdim#if !SANITIZER_NETBSD 609353944SdimINTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) { 610353944Sdim ENSURE_MSAN_INITED(); 611353944Sdim char *res = REAL(fcvt)(x, a, b, c); 612353944Sdim __msan_unpoison(b, sizeof(*b)); 613353944Sdim __msan_unpoison(c, sizeof(*c)); 614353944Sdim if (res) __msan_unpoison(res, REAL(strlen)(res) + 1); 615353944Sdim return res; 616353944Sdim} 617353944Sdim#define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt) 618353944Sdim#else 619353944Sdim#define MSAN_MAYBE_INTERCEPT_FCVT 620353944Sdim#endif 621353944Sdim 622353944SdimINTERCEPTOR(char *, getenv, char *name) { 623353944Sdim if (msan_init_is_running) 624353944Sdim return REAL(getenv)(name); 625353944Sdim ENSURE_MSAN_INITED(); 626353944Sdim char *res = REAL(getenv)(name); 627353944Sdim if (res) __msan_unpoison(res, REAL(strlen)(res) + 1); 628353944Sdim return res; 629353944Sdim} 630353944Sdim 631353944Sdimextern char **environ; 632353944Sdim 633353944Sdimstatic void UnpoisonEnviron() { 634353944Sdim char **envp = environ; 635353944Sdim for (; *envp; ++envp) { 636353944Sdim __msan_unpoison(envp, sizeof(*envp)); 637353944Sdim __msan_unpoison(*envp, REAL(strlen)(*envp) + 1); 638353944Sdim } 639353944Sdim // Trailing NULL pointer. 640353944Sdim __msan_unpoison(envp, sizeof(*envp)); 641353944Sdim} 642353944Sdim 643353944SdimINTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) { 644353944Sdim ENSURE_MSAN_INITED(); 645353944Sdim CHECK_UNPOISONED_STRING(name, 0); 646353944Sdim int res = REAL(setenv)(name, value, overwrite); 647353944Sdim if (!res) UnpoisonEnviron(); 648353944Sdim return res; 649353944Sdim} 650353944Sdim 651353944SdimINTERCEPTOR(int, putenv, char *string) { 652353944Sdim ENSURE_MSAN_INITED(); 653353944Sdim int res = REAL(putenv)(string); 654353944Sdim if (!res) UnpoisonEnviron(); 655353944Sdim return res; 656353944Sdim} 657353944Sdim 658353944Sdim#if SANITIZER_FREEBSD || SANITIZER_NETBSD 659353944SdimINTERCEPTOR(int, fstat, int fd, void *buf) { 660353944Sdim ENSURE_MSAN_INITED(); 661353944Sdim int res = REAL(fstat)(fd, buf); 662353944Sdim if (!res) 663353944Sdim __msan_unpoison(buf, __sanitizer::struct_stat_sz); 664353944Sdim return res; 665353944Sdim} 666353944Sdim#define MSAN_MAYBE_INTERCEPT_FSTAT INTERCEPT_FUNCTION(fstat) 667353944Sdim#else 668353944Sdim#define MSAN_MAYBE_INTERCEPT_FSTAT 669353944Sdim#endif 670353944Sdim 671353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 672353944SdimINTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) { 673353944Sdim ENSURE_MSAN_INITED(); 674353944Sdim int res = REAL(__fxstat)(magic, fd, buf); 675353944Sdim if (!res) 676353944Sdim __msan_unpoison(buf, __sanitizer::struct_stat_sz); 677353944Sdim return res; 678353944Sdim} 679353944Sdim#define MSAN_MAYBE_INTERCEPT___FXSTAT INTERCEPT_FUNCTION(__fxstat) 680353944Sdim#else 681353944Sdim#define MSAN_MAYBE_INTERCEPT___FXSTAT 682353944Sdim#endif 683353944Sdim 684353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 685353944SdimINTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) { 686353944Sdim ENSURE_MSAN_INITED(); 687353944Sdim int res = REAL(__fxstat64)(magic, fd, buf); 688353944Sdim if (!res) 689353944Sdim __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 690353944Sdim return res; 691353944Sdim} 692353944Sdim#define MSAN_MAYBE_INTERCEPT___FXSTAT64 INTERCEPT_FUNCTION(__fxstat64) 693353944Sdim#else 694353944Sdim#define MSAN_MAYBE_INTERCEPT___FXSTAT64 695353944Sdim#endif 696353944Sdim 697353944Sdim#if SANITIZER_FREEBSD || SANITIZER_NETBSD 698353944SdimINTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) { 699353944Sdim ENSURE_MSAN_INITED(); 700353944Sdim int res = REAL(fstatat)(fd, pathname, buf, flags); 701353944Sdim if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz); 702353944Sdim return res; 703353944Sdim} 704353944Sdim# define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(fstatat) 705353944Sdim#else 706353944SdimINTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf, 707353944Sdim int flags) { 708353944Sdim ENSURE_MSAN_INITED(); 709353944Sdim int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags); 710353944Sdim if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz); 711353944Sdim return res; 712353944Sdim} 713353944Sdim# define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(__fxstatat) 714353944Sdim#endif 715353944Sdim 716353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 717353944SdimINTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf, 718353944Sdim int flags) { 719353944Sdim ENSURE_MSAN_INITED(); 720353944Sdim int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags); 721353944Sdim if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 722353944Sdim return res; 723353944Sdim} 724353944Sdim#define MSAN_MAYBE_INTERCEPT___FXSTATAT64 INTERCEPT_FUNCTION(__fxstatat64) 725353944Sdim#else 726353944Sdim#define MSAN_MAYBE_INTERCEPT___FXSTATAT64 727353944Sdim#endif 728353944Sdim 729353944SdimINTERCEPTOR(int, pipe, int pipefd[2]) { 730353944Sdim if (msan_init_is_running) 731353944Sdim return REAL(pipe)(pipefd); 732353944Sdim ENSURE_MSAN_INITED(); 733353944Sdim int res = REAL(pipe)(pipefd); 734353944Sdim if (!res) 735353944Sdim __msan_unpoison(pipefd, sizeof(int[2])); 736353944Sdim return res; 737353944Sdim} 738353944Sdim 739353944SdimINTERCEPTOR(int, pipe2, int pipefd[2], int flags) { 740353944Sdim ENSURE_MSAN_INITED(); 741353944Sdim int res = REAL(pipe2)(pipefd, flags); 742353944Sdim if (!res) 743353944Sdim __msan_unpoison(pipefd, sizeof(int[2])); 744353944Sdim return res; 745353944Sdim} 746353944Sdim 747353944SdimINTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) { 748353944Sdim ENSURE_MSAN_INITED(); 749353944Sdim int res = REAL(socketpair)(domain, type, protocol, sv); 750353944Sdim if (!res) 751353944Sdim __msan_unpoison(sv, sizeof(int[2])); 752353944Sdim return res; 753353944Sdim} 754353944Sdim 755353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 756353944SdimINTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) { 757353944Sdim ENSURE_MSAN_INITED(); 758353944Sdim char *res = REAL(fgets_unlocked)(s, size, stream); 759353944Sdim if (res) 760353944Sdim __msan_unpoison(s, REAL(strlen)(s) + 1); 761353944Sdim return res; 762353944Sdim} 763353944Sdim#define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked) 764353944Sdim#else 765353944Sdim#define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED 766353944Sdim#endif 767353944Sdim 768353944Sdim#define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim) \ 769353944Sdim if (msan_init_is_running) \ 770353944Sdim return REAL(getrlimit)(resource, rlim); \ 771353944Sdim ENSURE_MSAN_INITED(); \ 772353944Sdim int res = REAL(func)(resource, rlim); \ 773353944Sdim if (!res) \ 774353944Sdim __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \ 775353944Sdim return res 776353944Sdim 777353944SdimINTERCEPTOR(int, getrlimit, int resource, void *rlim) { 778353944Sdim INTERCEPTOR_GETRLIMIT_BODY(getrlimit, resource, rlim); 779353944Sdim} 780353944Sdim 781353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 782353944SdimINTERCEPTOR(int, __getrlimit, int resource, void *rlim) { 783353944Sdim INTERCEPTOR_GETRLIMIT_BODY(__getrlimit, resource, rlim); 784353944Sdim} 785353944Sdim 786353944SdimINTERCEPTOR(int, getrlimit64, int resource, void *rlim) { 787353944Sdim if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim); 788353944Sdim ENSURE_MSAN_INITED(); 789353944Sdim int res = REAL(getrlimit64)(resource, rlim); 790353944Sdim if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz); 791353944Sdim return res; 792353944Sdim} 793353944Sdim 794353944SdimINTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit, 795353944Sdim void *old_rlimit) { 796353944Sdim if (msan_init_is_running) 797353944Sdim return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit); 798353944Sdim ENSURE_MSAN_INITED(); 799353944Sdim CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz); 800353944Sdim int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit); 801353944Sdim if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz); 802353944Sdim return res; 803353944Sdim} 804353944Sdim 805353944SdimINTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit, 806353944Sdim void *old_rlimit) { 807353944Sdim if (msan_init_is_running) 808353944Sdim return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit); 809353944Sdim ENSURE_MSAN_INITED(); 810353944Sdim CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz); 811353944Sdim int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit); 812353944Sdim if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz); 813353944Sdim return res; 814353944Sdim} 815353944Sdim 816353944Sdim#define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit) 817353944Sdim#define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64) 818353944Sdim#define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit) 819353944Sdim#define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64) 820353944Sdim#else 821353944Sdim#define MSAN_MAYBE_INTERCEPT___GETRLIMIT 822353944Sdim#define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 823353944Sdim#define MSAN_MAYBE_INTERCEPT_PRLIMIT 824353944Sdim#define MSAN_MAYBE_INTERCEPT_PRLIMIT64 825353944Sdim#endif 826353944Sdim 827353944Sdim#if SANITIZER_FREEBSD 828353944Sdim// FreeBSD's <sys/utsname.h> define uname() as 829353944Sdim// static __inline int uname(struct utsname *name) { 830353944Sdim// return __xuname(SYS_NMLN, (void*)name); 831353944Sdim// } 832353944SdimINTERCEPTOR(int, __xuname, int size, void *utsname) { 833353944Sdim ENSURE_MSAN_INITED(); 834353944Sdim int res = REAL(__xuname)(size, utsname); 835353944Sdim if (!res) 836353944Sdim __msan_unpoison(utsname, __sanitizer::struct_utsname_sz); 837353944Sdim return res; 838353944Sdim} 839353944Sdim#define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(__xuname) 840353944Sdim#else 841353944SdimINTERCEPTOR(int, uname, struct utsname *utsname) { 842353944Sdim ENSURE_MSAN_INITED(); 843353944Sdim int res = REAL(uname)(utsname); 844353944Sdim if (!res) 845353944Sdim __msan_unpoison(utsname, __sanitizer::struct_utsname_sz); 846353944Sdim return res; 847353944Sdim} 848353944Sdim#define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(uname) 849353944Sdim#endif 850353944Sdim 851353944SdimINTERCEPTOR(int, gethostname, char *name, SIZE_T len) { 852353944Sdim ENSURE_MSAN_INITED(); 853353944Sdim int res = REAL(gethostname)(name, len); 854353944Sdim if (!res) { 855353944Sdim SIZE_T real_len = REAL(strnlen)(name, len); 856353944Sdim if (real_len < len) 857353944Sdim ++real_len; 858353944Sdim __msan_unpoison(name, real_len); 859353944Sdim } 860353944Sdim return res; 861353944Sdim} 862353944Sdim 863353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 864353944SdimINTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents, 865353944Sdim int timeout) { 866353944Sdim ENSURE_MSAN_INITED(); 867353944Sdim int res = REAL(epoll_wait)(epfd, events, maxevents, timeout); 868353944Sdim if (res > 0) { 869353944Sdim __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res); 870353944Sdim } 871353944Sdim return res; 872353944Sdim} 873353944Sdim#define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait) 874353944Sdim#else 875353944Sdim#define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT 876353944Sdim#endif 877353944Sdim 878353944Sdim#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 879353944SdimINTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents, 880353944Sdim int timeout, void *sigmask) { 881353944Sdim ENSURE_MSAN_INITED(); 882353944Sdim int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask); 883353944Sdim if (res > 0) { 884353944Sdim __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res); 885353944Sdim } 886353944Sdim return res; 887353944Sdim} 888353944Sdim#define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait) 889353944Sdim#else 890353944Sdim#define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT 891353944Sdim#endif 892353944Sdim 893353944SdimINTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { 894353944Sdim GET_MALLOC_STACK_TRACE; 895353944Sdim if (UNLIKELY(!msan_inited)) 896353944Sdim // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 897353944Sdim return AllocateFromLocalPool(nmemb * size); 898353944Sdim return msan_calloc(nmemb, size, &stack); 899353944Sdim} 900353944Sdim 901353944SdimINTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) { 902353944Sdim GET_MALLOC_STACK_TRACE; 903353944Sdim if (UNLIKELY(IsInDlsymAllocPool(ptr))) { 904353944Sdim uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; 905353944Sdim uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); 906353944Sdim void *new_ptr; 907353944Sdim if (UNLIKELY(!msan_inited)) { 908353944Sdim new_ptr = AllocateFromLocalPool(copy_size); 909353944Sdim } else { 910353944Sdim copy_size = size; 911353944Sdim new_ptr = msan_malloc(copy_size, &stack); 912353944Sdim } 913353944Sdim internal_memcpy(new_ptr, ptr, copy_size); 914353944Sdim return new_ptr; 915353944Sdim } 916353944Sdim return msan_realloc(ptr, size, &stack); 917353944Sdim} 918353944Sdim 919353944SdimINTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) { 920353944Sdim GET_MALLOC_STACK_TRACE; 921353944Sdim return msan_reallocarray(ptr, nmemb, size, &stack); 922353944Sdim} 923353944Sdim 924353944SdimINTERCEPTOR(void *, malloc, SIZE_T size) { 925353944Sdim GET_MALLOC_STACK_TRACE; 926353944Sdim if (UNLIKELY(!msan_inited)) 927353944Sdim // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. 928353944Sdim return AllocateFromLocalPool(size); 929353944Sdim return msan_malloc(size, &stack); 930353944Sdim} 931353944Sdim 932353944Sdimvoid __msan_allocated_memory(const void *data, uptr size) { 933353944Sdim GET_MALLOC_STACK_TRACE; 934353944Sdim if (flags()->poison_in_malloc) { 935353944Sdim stack.tag = STACK_TRACE_TAG_POISON; 936353944Sdim PoisonMemory(data, size, &stack); 937353944Sdim } 938353944Sdim} 939353944Sdim 940353944Sdimvoid __msan_copy_shadow(void *dest, const void *src, uptr n) { 941353944Sdim GET_STORE_STACK_TRACE; 942353944Sdim MoveShadowAndOrigin(dest, src, n, &stack); 943353944Sdim} 944353944Sdim 945353944Sdimvoid __sanitizer_dtor_callback(const void *data, uptr size) { 946353944Sdim GET_MALLOC_STACK_TRACE; 947353944Sdim if (flags()->poison_in_dtor) { 948353944Sdim stack.tag = STACK_TRACE_TAG_POISON; 949353944Sdim PoisonMemory(data, size, &stack); 950353944Sdim } 951353944Sdim} 952353944Sdim 953353944Sdimtemplate <class Mmap> 954353944Sdimstatic void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length, 955353944Sdim int prot, int flags, int fd, OFF64_T offset) { 956353944Sdim if (addr && !MEM_IS_APP(addr)) { 957353944Sdim if (flags & map_fixed) { 958353944Sdim errno = errno_EINVAL; 959353944Sdim return (void *)-1; 960353944Sdim } else { 961353944Sdim addr = nullptr; 962353944Sdim } 963353944Sdim } 964353944Sdim void *res = real_mmap(addr, length, prot, flags, fd, offset); 965353944Sdim if (res != (void *)-1) __msan_unpoison(res, RoundUpTo(length, GetPageSize())); 966353944Sdim return res; 967353944Sdim} 968353944Sdim 969353944SdimINTERCEPTOR(int, getrusage, int who, void *usage) { 970353944Sdim ENSURE_MSAN_INITED(); 971353944Sdim int res = REAL(getrusage)(who, usage); 972353944Sdim if (res == 0) { 973353944Sdim __msan_unpoison(usage, __sanitizer::struct_rusage_sz); 974353944Sdim } 975353944Sdim return res; 976353944Sdim} 977353944Sdim 978353944Sdimclass SignalHandlerScope { 979353944Sdim public: 980353944Sdim SignalHandlerScope() { 981353944Sdim if (MsanThread *t = GetCurrentThread()) 982353944Sdim t->EnterSignalHandler(); 983353944Sdim } 984353944Sdim ~SignalHandlerScope() { 985353944Sdim if (MsanThread *t = GetCurrentThread()) 986353944Sdim t->LeaveSignalHandler(); 987353944Sdim } 988353944Sdim}; 989353944Sdim 990353944Sdim// sigactions_mu guarantees atomicity of sigaction() and signal() calls. 991353944Sdim// Access to sigactions[] is gone with relaxed atomics to avoid data race with 992353944Sdim// the signal handler. 993353944Sdimconst int kMaxSignals = 1024; 994353944Sdimstatic atomic_uintptr_t sigactions[kMaxSignals]; 995353944Sdimstatic StaticSpinMutex sigactions_mu; 996353944Sdim 997353944Sdimstatic void SignalHandler(int signo) { 998353944Sdim SignalHandlerScope signal_handler_scope; 999353944Sdim ScopedThreadLocalStateBackup stlsb; 1000353944Sdim UnpoisonParam(1); 1001353944Sdim 1002353944Sdim typedef void (*signal_cb)(int x); 1003353944Sdim signal_cb cb = 1004353944Sdim (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 1005353944Sdim cb(signo); 1006353944Sdim} 1007353944Sdim 1008353944Sdimstatic void SignalAction(int signo, void *si, void *uc) { 1009353944Sdim SignalHandlerScope signal_handler_scope; 1010353944Sdim ScopedThreadLocalStateBackup stlsb; 1011353944Sdim UnpoisonParam(3); 1012353944Sdim __msan_unpoison(si, sizeof(__sanitizer_sigaction)); 1013353944Sdim __msan_unpoison(uc, __sanitizer::ucontext_t_sz); 1014353944Sdim 1015353944Sdim typedef void (*sigaction_cb)(int, void *, void *); 1016353944Sdim sigaction_cb cb = 1017353944Sdim (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 1018353944Sdim cb(signo, si, uc); 1019353944Sdim} 1020353944Sdim 1021353944Sdimstatic void read_sigaction(const __sanitizer_sigaction *act) { 1022353944Sdim CHECK_UNPOISONED(&act->sa_flags, sizeof(act->sa_flags)); 1023353944Sdim if (act->sa_flags & __sanitizer::sa_siginfo) 1024353944Sdim CHECK_UNPOISONED(&act->sigaction, sizeof(act->sigaction)); 1025353944Sdim else 1026353944Sdim CHECK_UNPOISONED(&act->handler, sizeof(act->handler)); 1027353944Sdim CHECK_UNPOISONED(&act->sa_mask, sizeof(act->sa_mask)); 1028353944Sdim} 1029353944Sdim 1030353944Sdimextern "C" int pthread_attr_init(void *attr); 1031353944Sdimextern "C" int pthread_attr_destroy(void *attr); 1032353944Sdim 1033353944Sdimstatic void *MsanThreadStartFunc(void *arg) { 1034353944Sdim MsanThread *t = (MsanThread *)arg; 1035353944Sdim SetCurrentThread(t); 1036353944Sdim return t->ThreadStart(); 1037353944Sdim} 1038353944Sdim 1039353944SdimINTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), 1040353944Sdim void * param) { 1041353944Sdim ENSURE_MSAN_INITED(); // for GetTlsSize() 1042353944Sdim __sanitizer_pthread_attr_t myattr; 1043353944Sdim if (!attr) { 1044353944Sdim pthread_attr_init(&myattr); 1045353944Sdim attr = &myattr; 1046353944Sdim } 1047353944Sdim 1048353944Sdim AdjustStackSize(attr); 1049353944Sdim 1050353944Sdim MsanThread *t = MsanThread::Create(callback, param); 1051353944Sdim 1052353944Sdim int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t); 1053353944Sdim 1054353944Sdim if (attr == &myattr) 1055353944Sdim pthread_attr_destroy(&myattr); 1056353944Sdim if (!res) { 1057353944Sdim __msan_unpoison(th, __sanitizer::pthread_t_sz); 1058353944Sdim } 1059353944Sdim return res; 1060353944Sdim} 1061353944Sdim 1062353944SdimINTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key, 1063353944Sdim void (*dtor)(void *value)) { 1064353944Sdim if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor); 1065353944Sdim ENSURE_MSAN_INITED(); 1066353944Sdim int res = REAL(pthread_key_create)(key, dtor); 1067353944Sdim if (!res && key) 1068353944Sdim __msan_unpoison(key, sizeof(*key)); 1069353944Sdim return res; 1070353944Sdim} 1071353944Sdim 1072353944Sdim#if SANITIZER_NETBSD 1073357095SdimINTERCEPTOR(int, __libc_thr_keycreate, __sanitizer_pthread_key_t *m, 1074357095Sdim void (*dtor)(void *value)) 1075357095SdimALIAS(WRAPPER_NAME(pthread_key_create)); 1076353944Sdim#endif 1077353944Sdim 1078353944SdimINTERCEPTOR(int, pthread_join, void *th, void **retval) { 1079353944Sdim ENSURE_MSAN_INITED(); 1080353944Sdim int res = REAL(pthread_join)(th, retval); 1081353944Sdim if (!res && retval) 1082353944Sdim __msan_unpoison(retval, sizeof(*retval)); 1083353944Sdim return res; 1084353944Sdim} 1085353944Sdim 1086353944Sdimextern char *tzname[2]; 1087353944Sdim 1088353944SdimINTERCEPTOR(void, tzset, int fake) { 1089353944Sdim ENSURE_MSAN_INITED(); 1090353944Sdim InterceptorScope interceptor_scope; 1091353944Sdim REAL(tzset)(fake); 1092353944Sdim if (tzname[0]) 1093353944Sdim __msan_unpoison(tzname[0], REAL(strlen)(tzname[0]) + 1); 1094353944Sdim if (tzname[1]) 1095353944Sdim __msan_unpoison(tzname[1], REAL(strlen)(tzname[1]) + 1); 1096353944Sdim return; 1097353944Sdim} 1098353944Sdim 1099353944Sdimstruct MSanAtExitRecord { 1100353944Sdim void (*func)(void *arg); 1101353944Sdim void *arg; 1102353944Sdim}; 1103353944Sdim 1104353944Sdimstruct InterceptorContext { 1105353944Sdim BlockingMutex atexit_mu; 1106353944Sdim Vector<struct MSanAtExitRecord *> AtExitStack; 1107353944Sdim 1108353944Sdim InterceptorContext() 1109353944Sdim : AtExitStack() { 1110353944Sdim } 1111353944Sdim}; 1112353944Sdim 1113353944Sdimstatic ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)]; 1114353944SdimInterceptorContext *interceptor_ctx() { 1115353944Sdim return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]); 1116353944Sdim} 1117353944Sdim 1118353944Sdimvoid MSanAtExitWrapper() { 1119353944Sdim MSanAtExitRecord *r; 1120353944Sdim { 1121353944Sdim BlockingMutexLock l(&interceptor_ctx()->atexit_mu); 1122353944Sdim 1123353944Sdim uptr element = interceptor_ctx()->AtExitStack.Size() - 1; 1124353944Sdim r = interceptor_ctx()->AtExitStack[element]; 1125353944Sdim interceptor_ctx()->AtExitStack.PopBack(); 1126353944Sdim } 1127353944Sdim 1128353944Sdim UnpoisonParam(1); 1129353944Sdim ((void(*)())r->func)(); 1130353944Sdim InternalFree(r); 1131353944Sdim} 1132353944Sdim 1133353944Sdimvoid MSanCxaAtExitWrapper(void *arg) { 1134353944Sdim UnpoisonParam(1); 1135353944Sdim MSanAtExitRecord *r = (MSanAtExitRecord *)arg; 1136353944Sdim // libc before 2.27 had race which caused occasional double handler execution 1137353944Sdim // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html 1138353944Sdim if (!r->func) 1139353944Sdim return; 1140353944Sdim r->func(r->arg); 1141353944Sdim r->func = nullptr; 1142353944Sdim} 1143353944Sdim 1144353944Sdimstatic int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso); 1145353944Sdim 1146353944Sdim// Unpoison argument shadow for C++ module destructors. 1147353944SdimINTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 1148353944Sdim void *dso_handle) { 1149353944Sdim if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle); 1150353944Sdim return setup_at_exit_wrapper((void(*)())func, arg, dso_handle); 1151353944Sdim} 1152353944Sdim 1153353944Sdim// Unpoison argument shadow for C++ module destructors. 1154353944SdimINTERCEPTOR(int, atexit, void (*func)()) { 1155353944Sdim // Avoid calling real atexit as it is unrechable on at least on Linux. 1156353944Sdim if (msan_init_is_running) 1157353944Sdim return REAL(__cxa_atexit)((void (*)(void *a))func, 0, 0); 1158353944Sdim return setup_at_exit_wrapper((void(*)())func, 0, 0); 1159353944Sdim} 1160353944Sdim 1161353944Sdimstatic int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso) { 1162353944Sdim ENSURE_MSAN_INITED(); 1163353944Sdim MSanAtExitRecord *r = 1164353944Sdim (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord)); 1165353944Sdim r->func = (void(*)(void *a))f; 1166353944Sdim r->arg = arg; 1167353944Sdim int res; 1168353944Sdim if (!dso) { 1169353944Sdim // NetBSD does not preserve the 2nd argument if dso is equal to 0 1170353944Sdim // Store ctx in a local stack-like structure 1171353944Sdim 1172353944Sdim BlockingMutexLock l(&interceptor_ctx()->atexit_mu); 1173353944Sdim 1174353944Sdim res = REAL(__cxa_atexit)((void (*)(void *a))MSanAtExitWrapper, 0, 0); 1175353944Sdim if (!res) { 1176353944Sdim interceptor_ctx()->AtExitStack.PushBack(r); 1177353944Sdim } 1178353944Sdim } else { 1179353944Sdim res = REAL(__cxa_atexit)(MSanCxaAtExitWrapper, r, dso); 1180353944Sdim } 1181353944Sdim return res; 1182353944Sdim} 1183353944Sdim 1184353944Sdimstatic void BeforeFork() { 1185353944Sdim StackDepotLockAll(); 1186353944Sdim ChainedOriginDepotLockAll(); 1187353944Sdim} 1188353944Sdim 1189353944Sdimstatic void AfterFork() { 1190353944Sdim ChainedOriginDepotUnlockAll(); 1191353944Sdim StackDepotUnlockAll(); 1192353944Sdim} 1193353944Sdim 1194353944SdimINTERCEPTOR(int, fork, void) { 1195353944Sdim ENSURE_MSAN_INITED(); 1196353944Sdim BeforeFork(); 1197353944Sdim int pid = REAL(fork)(); 1198353944Sdim AfterFork(); 1199353944Sdim return pid; 1200353944Sdim} 1201353944Sdim 1202353944Sdim// NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly 1203353944Sdim// with MSan. 1204353944Sdim#if SANITIZER_LINUX 1205353944SdimINTERCEPTOR(int, openpty, int *aparent, int *aworker, char *name, 1206353944Sdim const void *termp, const void *winp) { 1207353944Sdim ENSURE_MSAN_INITED(); 1208353944Sdim InterceptorScope interceptor_scope; 1209353944Sdim int res = REAL(openpty)(aparent, aworker, name, termp, winp); 1210353944Sdim if (!res) { 1211353944Sdim __msan_unpoison(aparent, sizeof(*aparent)); 1212353944Sdim __msan_unpoison(aworker, sizeof(*aworker)); 1213353944Sdim } 1214353944Sdim return res; 1215353944Sdim} 1216353944Sdim#define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty) 1217353944Sdim#else 1218353944Sdim#define MSAN_MAYBE_INTERCEPT_OPENPTY 1219353944Sdim#endif 1220353944Sdim 1221353944Sdim// NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly 1222353944Sdim// with MSan. 1223353944Sdim#if SANITIZER_LINUX 1224353944SdimINTERCEPTOR(int, forkpty, int *aparent, char *name, const void *termp, 1225353944Sdim const void *winp) { 1226353944Sdim ENSURE_MSAN_INITED(); 1227353944Sdim InterceptorScope interceptor_scope; 1228353944Sdim int res = REAL(forkpty)(aparent, name, termp, winp); 1229353944Sdim if (res != -1) 1230353944Sdim __msan_unpoison(aparent, sizeof(*aparent)); 1231353944Sdim return res; 1232353944Sdim} 1233353944Sdim#define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty) 1234353944Sdim#else 1235353944Sdim#define MSAN_MAYBE_INTERCEPT_FORKPTY 1236353944Sdim#endif 1237353944Sdim 1238353944Sdimstruct MSanInterceptorContext { 1239353944Sdim bool in_interceptor_scope; 1240353944Sdim}; 1241353944Sdim 1242353944Sdimnamespace __msan { 1243353944Sdim 1244353944Sdimint OnExit() { 1245353944Sdim // FIXME: ask frontend whether we need to return failure. 1246353944Sdim return 0; 1247353944Sdim} 1248353944Sdim 1249353944Sdim} // namespace __msan 1250353944Sdim 1251353944Sdim// A version of CHECK_UNPOISONED using a saved scope value. Used in common 1252353944Sdim// interceptors. 1253353944Sdim#define CHECK_UNPOISONED_CTX(ctx, x, n) \ 1254353944Sdim do { \ 1255353944Sdim if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \ 1256353944Sdim CHECK_UNPOISONED_0(x, n); \ 1257353944Sdim } while (0) 1258353944Sdim 1259353944Sdim#define MSAN_INTERCEPT_FUNC(name) \ 1260353944Sdim do { \ 1261353944Sdim if (!INTERCEPT_FUNCTION(name)) \ 1262353944Sdim VReport(1, "MemorySanitizer: failed to intercept '%s'\n'", #name); \ 1263353944Sdim } while (0) 1264353944Sdim 1265353944Sdim#define MSAN_INTERCEPT_FUNC_VER(name, ver) \ 1266353944Sdim do { \ 1267353944Sdim if (!INTERCEPT_FUNCTION_VER(name, ver)) \ 1268353944Sdim VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \ 1269353944Sdim #ver); \ 1270353944Sdim } while (0) 1271353944Sdim 1272353944Sdim#define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name) 1273353944Sdim#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ 1274353944Sdim MSAN_INTERCEPT_FUNC_VER(name, ver) 1275353944Sdim#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \ 1276353944Sdim UnpoisonParam(count) 1277353944Sdim#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 1278353944Sdim __msan_unpoison(ptr, size) 1279353944Sdim#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ 1280353944Sdim CHECK_UNPOISONED_CTX(ctx, ptr, size) 1281353944Sdim#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \ 1282353944Sdim __msan_unpoison(ptr, size) 1283353944Sdim#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 1284353944Sdim if (msan_init_is_running) return REAL(func)(__VA_ARGS__); \ 1285353944Sdim ENSURE_MSAN_INITED(); \ 1286353944Sdim MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \ 1287353944Sdim ctx = (void *)&msan_ctx; \ 1288353944Sdim (void)ctx; \ 1289353944Sdim InterceptorScope interceptor_scope; \ 1290353944Sdim __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */ 1291353944Sdim#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ 1292353944Sdim do { \ 1293353944Sdim } while (false) 1294353944Sdim#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 1295353944Sdim do { \ 1296353944Sdim } while (false) 1297353944Sdim#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 1298353944Sdim do { \ 1299353944Sdim } while (false) 1300353944Sdim#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 1301353944Sdim do { \ 1302353944Sdim } while (false) 1303353944Sdim#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ 1304353944Sdim do { \ 1305353944Sdim } while (false) // FIXME 1306353944Sdim#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ 1307353944Sdim do { \ 1308353944Sdim } while (false) // FIXME 1309353944Sdim#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) 1310353944Sdim#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() 1311353944Sdim#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ 1312353944Sdim do { \ 1313353944Sdim link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \ 1314353944Sdim if (filename && map) \ 1315353944Sdim ForEachMappedRegion(map, __msan_unpoison); \ 1316353944Sdim } while (false) 1317353944Sdim 1318353944Sdim#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ 1319353944Sdim if (MsanThread *t = GetCurrentThread()) { \ 1320353944Sdim *begin = t->tls_begin(); \ 1321353944Sdim *end = t->tls_end(); \ 1322353944Sdim } else { \ 1323353944Sdim *begin = *end = 0; \ 1324353944Sdim } 1325353944Sdim 1326353944Sdim#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ 1327353944Sdim { \ 1328353944Sdim (void)ctx; \ 1329353944Sdim return __msan_memset(block, c, size); \ 1330353944Sdim } 1331353944Sdim#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ 1332353944Sdim { \ 1333353944Sdim (void)ctx; \ 1334353944Sdim return __msan_memmove(to, from, size); \ 1335353944Sdim } 1336353944Sdim#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \ 1337353944Sdim { \ 1338353944Sdim (void)ctx; \ 1339353944Sdim return __msan_memcpy(to, from, size); \ 1340353944Sdim } 1341353944Sdim 1342353944Sdim#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \ 1343353944Sdim do { \ 1344353944Sdim GET_STORE_STACK_TRACE; \ 1345353944Sdim CopyShadowAndOrigin(to, from, size, &stack); \ 1346353944Sdim __msan_unpoison(to + size, 1); \ 1347353944Sdim } while (false) 1348353944Sdim 1349353944Sdim#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \ 1350353944Sdim offset) \ 1351353944Sdim do { \ 1352353944Sdim return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \ 1353353944Sdim } while (false) 1354353944Sdim 1355353944Sdim#include "sanitizer_common/sanitizer_platform_interceptors.h" 1356353944Sdim#include "sanitizer_common/sanitizer_common_interceptors.inc" 1357353944Sdim 1358353944Sdimstatic uptr signal_impl(int signo, uptr cb); 1359353944Sdimstatic int sigaction_impl(int signo, const __sanitizer_sigaction *act, 1360353944Sdim __sanitizer_sigaction *oldact); 1361353944Sdim 1362353944Sdim#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \ 1363353944Sdim { return sigaction_impl(signo, act, oldact); } 1364353944Sdim 1365353944Sdim#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \ 1366353944Sdim { \ 1367353944Sdim handler = signal_impl(signo, handler); \ 1368353944Sdim InterceptorScope interceptor_scope; \ 1369353944Sdim return REAL(func)(signo, handler); \ 1370353944Sdim } 1371353944Sdim 1372353944Sdim#include "sanitizer_common/sanitizer_signal_interceptors.inc" 1373353944Sdim 1374353944Sdimstatic int sigaction_impl(int signo, const __sanitizer_sigaction *act, 1375353944Sdim __sanitizer_sigaction *oldact) { 1376353944Sdim ENSURE_MSAN_INITED(); 1377353944Sdim if (act) read_sigaction(act); 1378353944Sdim int res; 1379353944Sdim if (flags()->wrap_signals) { 1380353944Sdim SpinMutexLock lock(&sigactions_mu); 1381353944Sdim CHECK_LT(signo, kMaxSignals); 1382353944Sdim uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed); 1383353944Sdim __sanitizer_sigaction new_act; 1384353944Sdim __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr; 1385353944Sdim if (act) { 1386353944Sdim REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction)); 1387353944Sdim uptr cb = (uptr)pnew_act->sigaction; 1388353944Sdim uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo) 1389353944Sdim ? (uptr)SignalAction 1390353944Sdim : (uptr)SignalHandler; 1391353944Sdim if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { 1392353944Sdim atomic_store(&sigactions[signo], cb, memory_order_relaxed); 1393353944Sdim pnew_act->sigaction = (decltype(pnew_act->sigaction))new_cb; 1394353944Sdim } 1395353944Sdim } 1396353944Sdim res = REAL(SIGACTION_SYMNAME)(signo, pnew_act, oldact); 1397353944Sdim if (res == 0 && oldact) { 1398353944Sdim uptr cb = (uptr)oldact->sigaction; 1399353944Sdim if (cb == (uptr)SignalAction || cb == (uptr)SignalHandler) { 1400353944Sdim oldact->sigaction = (decltype(oldact->sigaction))old_cb; 1401353944Sdim } 1402353944Sdim } 1403353944Sdim } else { 1404353944Sdim res = REAL(SIGACTION_SYMNAME)(signo, act, oldact); 1405353944Sdim } 1406353944Sdim 1407353944Sdim if (res == 0 && oldact) { 1408353944Sdim __msan_unpoison(oldact, sizeof(__sanitizer_sigaction)); 1409353944Sdim } 1410353944Sdim return res; 1411353944Sdim} 1412353944Sdim 1413353944Sdimstatic uptr signal_impl(int signo, uptr cb) { 1414353944Sdim ENSURE_MSAN_INITED(); 1415353944Sdim if (flags()->wrap_signals) { 1416353944Sdim CHECK_LT(signo, kMaxSignals); 1417353944Sdim SpinMutexLock lock(&sigactions_mu); 1418353944Sdim if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { 1419353944Sdim atomic_store(&sigactions[signo], cb, memory_order_relaxed); 1420353944Sdim cb = (uptr)&SignalHandler; 1421353944Sdim } 1422353944Sdim } 1423353944Sdim return cb; 1424353944Sdim} 1425353944Sdim 1426353944Sdim#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s) 1427353944Sdim#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \ 1428353944Sdim do { \ 1429353944Sdim } while (false) 1430353944Sdim#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 1431353944Sdim do { \ 1432353944Sdim } while (false) 1433353944Sdim#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s) 1434353944Sdim#include "sanitizer_common/sanitizer_common_syscalls.inc" 1435353944Sdim#include "sanitizer_common/sanitizer_syscalls_netbsd.inc" 1436353944Sdim 1437353944Sdimstruct dlinfo { 1438353944Sdim char *dli_fname; 1439353944Sdim void *dli_fbase; 1440353944Sdim char *dli_sname; 1441353944Sdim void *dli_saddr; 1442353944Sdim}; 1443353944Sdim 1444353944SdimINTERCEPTOR(int, dladdr, void *addr, dlinfo *info) { 1445353944Sdim void *ctx; 1446353944Sdim COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info); 1447353944Sdim int res = REAL(dladdr)(addr, info); 1448353944Sdim if (res != 0) { 1449353944Sdim __msan_unpoison(info, sizeof(*info)); 1450353944Sdim if (info->dli_fname) 1451353944Sdim __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1); 1452353944Sdim if (info->dli_sname) 1453353944Sdim __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1); 1454353944Sdim } 1455353944Sdim return res; 1456353944Sdim} 1457353944Sdim 1458353944SdimINTERCEPTOR(char *, dlerror, int fake) { 1459353944Sdim void *ctx; 1460353944Sdim COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake); 1461353944Sdim char *res = REAL(dlerror)(fake); 1462353944Sdim if (res) __msan_unpoison(res, REAL(strlen)(res) + 1); 1463353944Sdim return res; 1464353944Sdim} 1465353944Sdim 1466353944Sdimtypedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size, 1467353944Sdim void *data); 1468353944Sdimstruct dl_iterate_phdr_data { 1469353944Sdim dl_iterate_phdr_cb callback; 1470353944Sdim void *data; 1471353944Sdim}; 1472353944Sdim 1473353944Sdimstatic int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size, 1474353944Sdim void *data) { 1475353944Sdim if (info) { 1476353944Sdim __msan_unpoison(info, size); 1477353944Sdim if (info->dlpi_phdr && info->dlpi_phnum) 1478353944Sdim __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum); 1479353944Sdim if (info->dlpi_name) 1480353944Sdim __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1); 1481353944Sdim } 1482353944Sdim dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data; 1483353944Sdim UnpoisonParam(3); 1484353944Sdim return cbdata->callback(info, size, cbdata->data); 1485353944Sdim} 1486353944Sdim 1487353944SdimINTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) { 1488353944Sdim ENSURE_MSAN_INITED(); 1489353944Sdim void *p = REAL(shmat)(shmid, shmaddr, shmflg); 1490353944Sdim if (p != (void *)-1) { 1491353944Sdim __sanitizer_shmid_ds ds; 1492353944Sdim int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds); 1493353944Sdim if (!res) { 1494353944Sdim __msan_unpoison(p, ds.shm_segsz); 1495353944Sdim } 1496353944Sdim } 1497353944Sdim return p; 1498353944Sdim} 1499353944Sdim 1500353944SdimINTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) { 1501353944Sdim void *ctx; 1502353944Sdim COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data); 1503353944Sdim dl_iterate_phdr_data cbdata; 1504353944Sdim cbdata.callback = callback; 1505353944Sdim cbdata.data = data; 1506353944Sdim int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata); 1507353944Sdim return res; 1508353944Sdim} 1509353944Sdim 1510353944Sdim// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc); 1511353944SdimINTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) { 1512353944Sdim ENSURE_MSAN_INITED(); 1513353944Sdim wchar_t *res = REAL(wcschr)(s, wc, ps); 1514353944Sdim return res; 1515353944Sdim} 1516353944Sdim 1517353944Sdim// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src); 1518353944SdimINTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) { 1519353944Sdim ENSURE_MSAN_INITED(); 1520353944Sdim GET_STORE_STACK_TRACE; 1521353944Sdim wchar_t *res = REAL(wcscpy)(dest, src); 1522353944Sdim CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1), 1523353944Sdim &stack); 1524353944Sdim return res; 1525353944Sdim} 1526353944Sdim 1527353944SdimINTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { 1528353944Sdim ENSURE_MSAN_INITED(); 1529353944Sdim GET_STORE_STACK_TRACE; 1530353944Sdim SIZE_T copy_size = REAL(wcsnlen)(src, n); 1531353944Sdim if (copy_size < n) copy_size++; // trailing \0 1532353944Sdim wchar_t *res = REAL(wcsncpy)(dest, src, n); 1533353944Sdim CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack); 1534353944Sdim __msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t)); 1535353944Sdim return res; 1536353944Sdim} 1537353944Sdim 1538353944Sdim// These interface functions reside here so that they can use 1539353944Sdim// REAL(memset), etc. 1540353944Sdimvoid __msan_unpoison(const void *a, uptr size) { 1541353944Sdim if (!MEM_IS_APP(a)) return; 1542353944Sdim SetShadow(a, size, 0); 1543353944Sdim} 1544353944Sdim 1545353944Sdimvoid __msan_poison(const void *a, uptr size) { 1546353944Sdim if (!MEM_IS_APP(a)) return; 1547353944Sdim SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1); 1548353944Sdim} 1549353944Sdim 1550353944Sdimvoid __msan_poison_stack(void *a, uptr size) { 1551353944Sdim if (!MEM_IS_APP(a)) return; 1552353944Sdim SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1); 1553353944Sdim} 1554353944Sdim 1555353944Sdimvoid __msan_unpoison_param(uptr n) { UnpoisonParam(n); } 1556353944Sdim 1557353944Sdimvoid __msan_clear_and_unpoison(void *a, uptr size) { 1558353944Sdim REAL(memset)(a, 0, size); 1559353944Sdim SetShadow(a, size, 0); 1560353944Sdim} 1561353944Sdim 1562353944Sdimvoid *__msan_memcpy(void *dest, const void *src, SIZE_T n) { 1563353944Sdim if (!msan_inited) return internal_memcpy(dest, src, n); 1564353944Sdim if (msan_init_is_running || __msan::IsInSymbolizer()) 1565353944Sdim return REAL(memcpy)(dest, src, n); 1566353944Sdim ENSURE_MSAN_INITED(); 1567353944Sdim GET_STORE_STACK_TRACE; 1568353944Sdim void *res = REAL(memcpy)(dest, src, n); 1569353944Sdim CopyShadowAndOrigin(dest, src, n, &stack); 1570353944Sdim return res; 1571353944Sdim} 1572353944Sdim 1573353944Sdimvoid *__msan_memset(void *s, int c, SIZE_T n) { 1574353944Sdim if (!msan_inited) return internal_memset(s, c, n); 1575353944Sdim if (msan_init_is_running) return REAL(memset)(s, c, n); 1576353944Sdim ENSURE_MSAN_INITED(); 1577353944Sdim void *res = REAL(memset)(s, c, n); 1578353944Sdim __msan_unpoison(s, n); 1579353944Sdim return res; 1580353944Sdim} 1581353944Sdim 1582353944Sdimvoid *__msan_memmove(void *dest, const void *src, SIZE_T n) { 1583353944Sdim if (!msan_inited) return internal_memmove(dest, src, n); 1584353944Sdim if (msan_init_is_running) return REAL(memmove)(dest, src, n); 1585353944Sdim ENSURE_MSAN_INITED(); 1586353944Sdim GET_STORE_STACK_TRACE; 1587353944Sdim void *res = REAL(memmove)(dest, src, n); 1588353944Sdim MoveShadowAndOrigin(dest, src, n, &stack); 1589353944Sdim return res; 1590353944Sdim} 1591353944Sdim 1592353944Sdimvoid __msan_unpoison_string(const char* s) { 1593353944Sdim if (!MEM_IS_APP(s)) return; 1594353944Sdim __msan_unpoison(s, REAL(strlen)(s) + 1); 1595353944Sdim} 1596353944Sdim 1597353944Sdimnamespace __msan { 1598353944Sdim 1599353944Sdimvoid InitializeInterceptors() { 1600353944Sdim static int inited = 0; 1601353944Sdim CHECK_EQ(inited, 0); 1602353944Sdim 1603353944Sdim new(interceptor_ctx()) InterceptorContext(); 1604353944Sdim 1605353944Sdim InitializeCommonInterceptors(); 1606353944Sdim InitializeSignalInterceptors(); 1607353944Sdim 1608353944Sdim INTERCEPT_FUNCTION(posix_memalign); 1609353944Sdim MSAN_MAYBE_INTERCEPT_MEMALIGN; 1610353944Sdim MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN; 1611353944Sdim INTERCEPT_FUNCTION(valloc); 1612353944Sdim MSAN_MAYBE_INTERCEPT_PVALLOC; 1613353944Sdim INTERCEPT_FUNCTION(malloc); 1614353944Sdim INTERCEPT_FUNCTION(calloc); 1615353944Sdim INTERCEPT_FUNCTION(realloc); 1616353944Sdim INTERCEPT_FUNCTION(reallocarray); 1617353944Sdim INTERCEPT_FUNCTION(free); 1618353944Sdim MSAN_MAYBE_INTERCEPT_CFREE; 1619353944Sdim MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE; 1620353944Sdim MSAN_MAYBE_INTERCEPT_MALLINFO; 1621353944Sdim MSAN_MAYBE_INTERCEPT_MALLOPT; 1622353944Sdim MSAN_MAYBE_INTERCEPT_MALLOC_STATS; 1623353944Sdim INTERCEPT_FUNCTION(fread); 1624353944Sdim MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED; 1625353944Sdim INTERCEPT_FUNCTION(memccpy); 1626353944Sdim MSAN_MAYBE_INTERCEPT_MEMPCPY; 1627353944Sdim INTERCEPT_FUNCTION(bcopy); 1628353944Sdim INTERCEPT_FUNCTION(wmemset); 1629353944Sdim INTERCEPT_FUNCTION(wmemcpy); 1630353944Sdim MSAN_MAYBE_INTERCEPT_WMEMPCPY; 1631353944Sdim INTERCEPT_FUNCTION(wmemmove); 1632353944Sdim INTERCEPT_FUNCTION(strcpy); 1633353944Sdim MSAN_MAYBE_INTERCEPT_STPCPY; 1634353944Sdim INTERCEPT_FUNCTION(strdup); 1635353944Sdim MSAN_MAYBE_INTERCEPT___STRDUP; 1636353944Sdim INTERCEPT_FUNCTION(strncpy); 1637353944Sdim MSAN_MAYBE_INTERCEPT_GCVT; 1638353944Sdim INTERCEPT_FUNCTION(strcat); 1639353944Sdim INTERCEPT_FUNCTION(strncat); 1640353944Sdim INTERCEPT_STRTO(strtod); 1641353944Sdim INTERCEPT_STRTO(strtof); 1642353944Sdim INTERCEPT_STRTO(strtold); 1643353944Sdim INTERCEPT_STRTO(strtol); 1644353944Sdim INTERCEPT_STRTO(strtoul); 1645353944Sdim INTERCEPT_STRTO(strtoll); 1646353944Sdim INTERCEPT_STRTO(strtoull); 1647353944Sdim INTERCEPT_STRTO(strtouq); 1648353944Sdim INTERCEPT_STRTO(wcstod); 1649353944Sdim INTERCEPT_STRTO(wcstof); 1650353944Sdim INTERCEPT_STRTO(wcstold); 1651353944Sdim INTERCEPT_STRTO(wcstol); 1652353944Sdim INTERCEPT_STRTO(wcstoul); 1653353944Sdim INTERCEPT_STRTO(wcstoll); 1654353944Sdim INTERCEPT_STRTO(wcstoull); 1655353944Sdim#ifdef SANITIZER_NLDBL_VERSION 1656353944Sdim INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION); 1657353944Sdim INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION); 1658353944Sdim#else 1659353944Sdim INTERCEPT_FUNCTION(vswprintf); 1660353944Sdim INTERCEPT_FUNCTION(swprintf); 1661353944Sdim#endif 1662353944Sdim INTERCEPT_FUNCTION(strftime); 1663353944Sdim INTERCEPT_FUNCTION(strftime_l); 1664353944Sdim MSAN_MAYBE_INTERCEPT___STRFTIME_L; 1665353944Sdim INTERCEPT_FUNCTION(wcsftime); 1666353944Sdim INTERCEPT_FUNCTION(wcsftime_l); 1667353944Sdim MSAN_MAYBE_INTERCEPT___WCSFTIME_L; 1668353944Sdim INTERCEPT_FUNCTION(mbtowc); 1669353944Sdim INTERCEPT_FUNCTION(mbrtowc); 1670353944Sdim INTERCEPT_FUNCTION(wcslen); 1671353944Sdim INTERCEPT_FUNCTION(wcsnlen); 1672353944Sdim INTERCEPT_FUNCTION(wcschr); 1673353944Sdim INTERCEPT_FUNCTION(wcscpy); 1674353944Sdim INTERCEPT_FUNCTION(wcsncpy); 1675353944Sdim INTERCEPT_FUNCTION(wcscmp); 1676353944Sdim INTERCEPT_FUNCTION(getenv); 1677353944Sdim INTERCEPT_FUNCTION(setenv); 1678353944Sdim INTERCEPT_FUNCTION(putenv); 1679353944Sdim INTERCEPT_FUNCTION(gettimeofday); 1680353944Sdim MSAN_MAYBE_INTERCEPT_FCVT; 1681353944Sdim MSAN_MAYBE_INTERCEPT_FSTAT; 1682353944Sdim MSAN_MAYBE_INTERCEPT___FXSTAT; 1683353944Sdim MSAN_INTERCEPT_FSTATAT; 1684353944Sdim MSAN_MAYBE_INTERCEPT___FXSTAT64; 1685353944Sdim MSAN_MAYBE_INTERCEPT___FXSTATAT64; 1686353944Sdim INTERCEPT_FUNCTION(pipe); 1687353944Sdim INTERCEPT_FUNCTION(pipe2); 1688353944Sdim INTERCEPT_FUNCTION(socketpair); 1689353944Sdim MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED; 1690353944Sdim INTERCEPT_FUNCTION(getrlimit); 1691353944Sdim MSAN_MAYBE_INTERCEPT___GETRLIMIT; 1692353944Sdim MSAN_MAYBE_INTERCEPT_GETRLIMIT64; 1693353944Sdim MSAN_MAYBE_INTERCEPT_PRLIMIT; 1694353944Sdim MSAN_MAYBE_INTERCEPT_PRLIMIT64; 1695353944Sdim MSAN_INTERCEPT_UNAME; 1696353944Sdim INTERCEPT_FUNCTION(gethostname); 1697353944Sdim MSAN_MAYBE_INTERCEPT_EPOLL_WAIT; 1698353944Sdim MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT; 1699353944Sdim INTERCEPT_FUNCTION(dladdr); 1700353944Sdim INTERCEPT_FUNCTION(dlerror); 1701353944Sdim INTERCEPT_FUNCTION(dl_iterate_phdr); 1702353944Sdim INTERCEPT_FUNCTION(getrusage); 1703353944Sdim#if defined(__mips__) 1704353944Sdim INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2"); 1705353944Sdim#else 1706353944Sdim INTERCEPT_FUNCTION(pthread_create); 1707353944Sdim#endif 1708353944Sdim INTERCEPT_FUNCTION(pthread_key_create); 1709353944Sdim 1710353944Sdim#if SANITIZER_NETBSD 1711353944Sdim INTERCEPT_FUNCTION(__libc_thr_keycreate); 1712353944Sdim#endif 1713353944Sdim 1714353944Sdim INTERCEPT_FUNCTION(pthread_join); 1715353944Sdim INTERCEPT_FUNCTION(tzset); 1716353944Sdim INTERCEPT_FUNCTION(atexit); 1717353944Sdim INTERCEPT_FUNCTION(__cxa_atexit); 1718353944Sdim INTERCEPT_FUNCTION(shmat); 1719353944Sdim INTERCEPT_FUNCTION(fork); 1720353944Sdim MSAN_MAYBE_INTERCEPT_OPENPTY; 1721353944Sdim MSAN_MAYBE_INTERCEPT_FORKPTY; 1722353944Sdim 1723353944Sdim inited = 1; 1724353944Sdim} 1725353944Sdim} // namespace __msan 1726