1245614Sandrew//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===// 2245614Sandrew// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6245614Sandrew// 7245614Sandrew//===----------------------------------------------------------------------===// 8245614Sandrew// 9245614Sandrew// Common function interceptors for tools like AddressSanitizer, 10245614Sandrew// ThreadSanitizer, MemorySanitizer, etc. 11245614Sandrew// 12245614Sandrew// This file should be included into the tool's interceptor file, 13309124Sdim// which has to define its own macros: 14245614Sandrew// COMMON_INTERCEPTOR_ENTER 15276789Sdim// COMMON_INTERCEPTOR_ENTER_NOIGNORE 16245614Sandrew// COMMON_INTERCEPTOR_READ_RANGE 17245614Sandrew// COMMON_INTERCEPTOR_WRITE_RANGE 18274201Sdim// COMMON_INTERCEPTOR_INITIALIZE_RANGE 19280031Sdim// COMMON_INTERCEPTOR_DIR_ACQUIRE 20245614Sandrew// COMMON_INTERCEPTOR_FD_ACQUIRE 21245614Sandrew// COMMON_INTERCEPTOR_FD_RELEASE 22274201Sdim// COMMON_INTERCEPTOR_FD_ACCESS 23245614Sandrew// COMMON_INTERCEPTOR_SET_THREAD_NAME 24288943Sdim// COMMON_INTERCEPTOR_ON_DLOPEN 25274201Sdim// COMMON_INTERCEPTOR_ON_EXIT 26321369Sdim// COMMON_INTERCEPTOR_MUTEX_PRE_LOCK 27321369Sdim// COMMON_INTERCEPTOR_MUTEX_POST_LOCK 28274201Sdim// COMMON_INTERCEPTOR_MUTEX_UNLOCK 29274201Sdim// COMMON_INTERCEPTOR_MUTEX_REPAIR 30274201Sdim// COMMON_INTERCEPTOR_SET_PTHREAD_NAME 31276789Sdim// COMMON_INTERCEPTOR_HANDLE_RECVMSG 32276789Sdim// COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED 33314564Sdim// COMMON_INTERCEPTOR_MEMSET_IMPL 34314564Sdim// COMMON_INTERCEPTOR_MEMMOVE_IMPL 35314564Sdim// COMMON_INTERCEPTOR_MEMCPY_IMPL 36341825Sdim// COMMON_INTERCEPTOR_MMAP_IMPL 37321369Sdim// COMMON_INTERCEPTOR_COPY_STRING 38321369Sdim// COMMON_INTERCEPTOR_STRNDUP_IMPL 39360784Sdim// COMMON_INTERCEPTOR_STRERROR 40245614Sandrew//===----------------------------------------------------------------------===// 41296417Sdim 42245614Sandrew#include "interception/interception.h" 43276789Sdim#include "sanitizer_addrhashmap.h" 44321369Sdim#include "sanitizer_errno.h" 45276789Sdim#include "sanitizer_placement_new.h" 46245614Sandrew#include "sanitizer_platform_interceptors.h" 47327952Sdim#include "sanitizer_symbolizer.h" 48276789Sdim#include "sanitizer_tls_get_addr.h" 49245614Sandrew 50245614Sandrew#include <stdarg.h> 51245614Sandrew 52296417Sdim#if SANITIZER_INTERCEPTOR_HOOKS 53321369Sdim#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__); 54321369Sdim#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \ 55321369Sdim SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {} 56296417Sdim#else 57296417Sdim#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) 58296417Sdim#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) 59296417Sdim 60296417Sdim#endif // SANITIZER_INTERCEPTOR_HOOKS 61296417Sdim 62276789Sdim#if SANITIZER_WINDOWS && !defined(va_copy) 63251034Sed#define va_copy(dst, src) ((dst) = (src)) 64251034Sed#endif // _WIN32 65251034Sed 66276789Sdim#if SANITIZER_FREEBSD 67276789Sdim#define pthread_setname_np pthread_set_name_np 68280031Sdim#define inet_aton __inet_aton 69280031Sdim#define inet_pton __inet_pton 70288943Sdim#define iconv __bsd_iconv 71276789Sdim#endif 72276789Sdim 73327952Sdim#if SANITIZER_NETBSD 74327952Sdim#define clock_getres __clock_getres50 75327952Sdim#define clock_gettime __clock_gettime50 76327952Sdim#define clock_settime __clock_settime50 77327952Sdim#define ctime __ctime50 78327952Sdim#define ctime_r __ctime_r50 79341825Sdim#define devname __devname50 80344779Sdim#define fgetpos __fgetpos50 81344779Sdim#define fsetpos __fsetpos50 82360784Sdim#define fstatvfs __fstatvfs90 83360784Sdim#define fstatvfs1 __fstatvfs190 84344779Sdim#define fts_children __fts_children60 85344779Sdim#define fts_close __fts_close60 86344779Sdim#define fts_open __fts_open60 87344779Sdim#define fts_read __fts_read60 88344779Sdim#define fts_set __fts_set60 89327952Sdim#define getitimer __getitimer50 90360784Sdim#define getmntinfo __getmntinfo90 91327952Sdim#define getpwent __getpwent50 92327952Sdim#define getpwnam __getpwnam50 93327952Sdim#define getpwnam_r __getpwnam_r50 94327952Sdim#define getpwuid __getpwuid50 95327952Sdim#define getpwuid_r __getpwuid_r50 96327952Sdim#define getutent __getutent50 97327952Sdim#define getutxent __getutxent50 98327952Sdim#define getutxid __getutxid50 99327952Sdim#define getutxline __getutxline50 100360784Sdim#define getvfsstat __getvfsstat90 101344779Sdim#define pututxline __pututxline50 102327952Sdim#define glob __glob30 103327952Sdim#define gmtime __gmtime50 104327952Sdim#define gmtime_r __gmtime_r50 105341825Sdim#define localtime __locatime50 106327952Sdim#define localtime_r __localtime_r50 107327952Sdim#define mktime __mktime50 108341825Sdim#define lstat __lstat50 109327952Sdim#define opendir __opendir30 110327952Sdim#define readdir __readdir30 111327952Sdim#define readdir_r __readdir_r30 112327952Sdim#define scandir __scandir30 113327952Sdim#define setitimer __setitimer50 114327952Sdim#define setlocale __setlocale50 115327952Sdim#define shmctl __shmctl50 116327952Sdim#define sigemptyset __sigemptyset14 117327952Sdim#define sigfillset __sigfillset14 118327952Sdim#define sigpending __sigpending14 119327952Sdim#define sigprocmask __sigprocmask14 120327952Sdim#define sigtimedwait __sigtimedwait50 121327952Sdim#define stat __stat50 122360784Sdim#define statvfs __statvfs90 123360784Sdim#define statvfs1 __statvfs190 124327952Sdim#define time __time50 125327952Sdim#define times __times13 126344779Sdim#define unvis __unvis50 127327952Sdim#define wait3 __wait350 128327952Sdim#define wait4 __wait450 129341825Sdimextern const unsigned short *_ctype_tab_; 130341825Sdimextern const short *_toupper_tab_; 131341825Sdimextern const short *_tolower_tab_; 132327952Sdim#endif 133327952Sdim 134314564Sdim// Platform-specific options. 135314564Sdim#if SANITIZER_MAC 136314564Sdimnamespace __sanitizer { 137314564Sdimbool PlatformHasDifferentMemcpyAndMemmove(); 138314564Sdim} 139314564Sdim#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \ 140314564Sdim (__sanitizer::PlatformHasDifferentMemcpyAndMemmove()) 141314564Sdim#elif SANITIZER_WINDOWS64 142314564Sdim#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false 143314564Sdim#else 144314564Sdim#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true 145314564Sdim#endif // SANITIZER_MAC 146314564Sdim 147274201Sdim#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE 148276789Sdim#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {} 149274201Sdim#endif 150274201Sdim 151276789Sdim#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM 152276789Sdim#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {} 153276789Sdim#endif 154276789Sdim 155274201Sdim#ifndef COMMON_INTERCEPTOR_FD_ACCESS 156274201Sdim#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {} 157274201Sdim#endif 158274201Sdim 159321369Sdim#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK 160321369Sdim#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {} 161274201Sdim#endif 162274201Sdim 163321369Sdim#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK 164321369Sdim#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {} 165321369Sdim#endif 166321369Sdim 167274201Sdim#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK 168274201Sdim#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {} 169274201Sdim#endif 170274201Sdim 171274201Sdim#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR 172274201Sdim#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {} 173274201Sdim#endif 174274201Sdim 175309124Sdim#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID 176309124Sdim#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {} 177309124Sdim#endif 178309124Sdim 179276789Sdim#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG 180276789Sdim#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg)) 181276789Sdim#endif 182276789Sdim 183276789Sdim#ifndef COMMON_INTERCEPTOR_FILE_OPEN 184276789Sdim#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {} 185276789Sdim#endif 186276789Sdim 187276789Sdim#ifndef COMMON_INTERCEPTOR_FILE_CLOSE 188276789Sdim#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {} 189276789Sdim#endif 190276789Sdim 191276789Sdim#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED 192280031Sdim#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) {} 193276789Sdim#endif 194276789Sdim 195276789Sdim#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED 196276789Sdim#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {} 197276789Sdim#endif 198276789Sdim 199276789Sdim#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE 200276789Sdim#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \ 201276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__) 202276789Sdim#endif 203276789Sdim 204276789Sdim#ifndef COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED 205276789Sdim#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0) 206276789Sdim#endif 207276789Sdim 208321369Sdim#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \ 209288943Sdim COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \ 210321369Sdim common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) ) 211288943Sdim 212288943Sdim#ifndef COMMON_INTERCEPTOR_ON_DLOPEN 213321369Sdim#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \ 214321369Sdim CheckNoDeepBind(filename, flag); 215288943Sdim#endif 216288943Sdim 217288943Sdim#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE 218288943Sdim#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0; 219288943Sdim#endif 220288943Sdim 221296417Sdim#ifndef COMMON_INTERCEPTOR_ACQUIRE 222296417Sdim#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) {} 223296417Sdim#endif 224296417Sdim 225296417Sdim#ifndef COMMON_INTERCEPTOR_RELEASE 226296417Sdim#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {} 227296417Sdim#endif 228296417Sdim 229309124Sdim#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START 230309124Sdim#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {} 231309124Sdim#endif 232309124Sdim 233309124Sdim#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END 234309124Sdim#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {} 235309124Sdim#endif 236309124Sdim 237309124Sdim#ifdef SANITIZER_NLDBL_VERSION 238309124Sdim#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \ 239309124Sdim COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION) 240309124Sdim#else 241309124Sdim#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \ 242309124Sdim COMMON_INTERCEPT_FUNCTION(fn) 243309124Sdim#endif 244309124Sdim 245314564Sdim#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL 246314564Sdim#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \ 247314564Sdim { \ 248314564Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ 249314564Sdim return internal_memset(dst, v, size); \ 250314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \ 251314564Sdim if (common_flags()->intercept_intrin) \ 252314564Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ 253314564Sdim return REAL(memset)(dst, v, size); \ 254314564Sdim } 255314564Sdim#endif 256314564Sdim 257314564Sdim#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL 258314564Sdim#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \ 259314564Sdim { \ 260314564Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ 261314564Sdim return internal_memmove(dst, src, size); \ 262314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size); \ 263314564Sdim if (common_flags()->intercept_intrin) { \ 264314564Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ 265314564Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \ 266314564Sdim } \ 267314564Sdim return REAL(memmove)(dst, src, size); \ 268314564Sdim } 269314564Sdim#endif 270314564Sdim 271314564Sdim#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL 272314564Sdim#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \ 273314564Sdim { \ 274314564Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { \ 275314564Sdim return internal_memmove(dst, src, size); \ 276314564Sdim } \ 277314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size); \ 278314564Sdim if (common_flags()->intercept_intrin) { \ 279314564Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ 280314564Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \ 281314564Sdim } \ 282314564Sdim return REAL(memcpy)(dst, src, size); \ 283314564Sdim } 284314564Sdim#endif 285314564Sdim 286341825Sdim#ifndef COMMON_INTERCEPTOR_MMAP_IMPL 287341825Sdim#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \ 288341825Sdim off) \ 289341825Sdim { return REAL(mmap)(addr, sz, prot, flags, fd, off); } 290341825Sdim#endif 291341825Sdim 292321369Sdim#ifndef COMMON_INTERCEPTOR_COPY_STRING 293321369Sdim#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {} 294321369Sdim#endif 295321369Sdim 296321369Sdim#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL 297321369Sdim#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \ 298321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \ 299321369Sdim uptr copy_length = internal_strnlen(s, size); \ 300321369Sdim char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \ 301321369Sdim if (common_flags()->intercept_strndup) { \ 302321369Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \ 303321369Sdim } \ 304321369Sdim COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \ 305321369Sdim internal_memcpy(new_mem, s, copy_length); \ 306321369Sdim new_mem[copy_length] = '\0'; \ 307321369Sdim return new_mem; 308321369Sdim#endif 309321369Sdim 310360784Sdim#ifndef COMMON_INTERCEPTOR_STRERROR 311360784Sdim#define COMMON_INTERCEPTOR_STRERROR() {} 312360784Sdim#endif 313360784Sdim 314276789Sdimstruct FileMetadata { 315276789Sdim // For open_memstream(). 316276789Sdim char **addr; 317276789Sdim SIZE_T *size; 318276789Sdim}; 319276789Sdim 320276789Sdimstruct CommonInterceptorMetadata { 321276789Sdim enum { 322276789Sdim CIMT_INVALID = 0, 323276789Sdim CIMT_FILE 324276789Sdim } type; 325276789Sdim union { 326276789Sdim FileMetadata file; 327276789Sdim }; 328276789Sdim}; 329276789Sdim 330360784Sdim#if SI_POSIX 331276789Sdimtypedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap; 332276789Sdim 333276789Sdimstatic MetadataHashMap *interceptor_metadata_map; 334276789Sdim 335276789SdimUNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr, 336276789Sdim const FileMetadata &file) { 337276789Sdim MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr); 338276789Sdim CHECK(h.created()); 339276789Sdim h->type = CommonInterceptorMetadata::CIMT_FILE; 340276789Sdim h->file = file; 341276789Sdim} 342276789Sdim 343276789SdimUNUSED static const FileMetadata *GetInterceptorMetadata( 344276789Sdim __sanitizer_FILE *addr) { 345276789Sdim MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, 346276789Sdim /* remove */ false, 347276789Sdim /* create */ false); 348327952Sdim if (addr && h.exists()) { 349276789Sdim CHECK(!h.created()); 350276789Sdim CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE); 351276789Sdim return &h->file; 352276789Sdim } else { 353276789Sdim return 0; 354276789Sdim } 355276789Sdim} 356276789Sdim 357276789SdimUNUSED static void DeleteInterceptorMetadata(void *addr) { 358276789Sdim MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true); 359276789Sdim CHECK(h.exists()); 360276789Sdim} 361327952Sdim#endif // SI_POSIX 362276789Sdim 363309124Sdim#if SANITIZER_INTERCEPT_STRLEN 364309124SdimINTERCEPTOR(SIZE_T, strlen, const char *s) { 365309124Sdim // Sometimes strlen is called prior to InitializeCommonInterceptors, 366309124Sdim // in which case the REAL(strlen) typically used in 367309124Sdim // COMMON_INTERCEPTOR_ENTER will fail. We use internal_strlen here 368309124Sdim // to handle that. 369309124Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 370309124Sdim return internal_strlen(s); 371309124Sdim void *ctx; 372309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, strlen, s); 373309124Sdim SIZE_T result = REAL(strlen)(s); 374309124Sdim if (common_flags()->intercept_strlen) 375309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1); 376309124Sdim return result; 377309124Sdim} 378309124Sdim#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen) 379309124Sdim#else 380309124Sdim#define INIT_STRLEN 381309124Sdim#endif 382309124Sdim 383309124Sdim#if SANITIZER_INTERCEPT_STRNLEN 384309124SdimINTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) { 385309124Sdim void *ctx; 386309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen); 387309124Sdim SIZE_T length = REAL(strnlen)(s, maxlen); 388309124Sdim if (common_flags()->intercept_strlen) 389309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen)); 390309124Sdim return length; 391309124Sdim} 392309124Sdim#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen) 393309124Sdim#else 394309124Sdim#define INIT_STRNLEN 395309124Sdim#endif 396309124Sdim 397321369Sdim#if SANITIZER_INTERCEPT_STRNDUP 398321369SdimINTERCEPTOR(char*, strndup, const char *s, uptr size) { 399321369Sdim void *ctx; 400321369Sdim COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size); 401321369Sdim} 402321369Sdim#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup) 403321369Sdim#else 404321369Sdim#define INIT_STRNDUP 405321369Sdim#endif // SANITIZER_INTERCEPT_STRNDUP 406321369Sdim 407321369Sdim#if SANITIZER_INTERCEPT___STRNDUP 408321369SdimINTERCEPTOR(char*, __strndup, const char *s, uptr size) { 409321369Sdim void *ctx; 410321369Sdim COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size); 411321369Sdim} 412321369Sdim#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup) 413321369Sdim#else 414321369Sdim#define INIT___STRNDUP 415321369Sdim#endif // SANITIZER_INTERCEPT___STRNDUP 416321369Sdim 417276789Sdim#if SANITIZER_INTERCEPT_TEXTDOMAIN 418276789SdimINTERCEPTOR(char*, textdomain, const char *domainname) { 419276789Sdim void *ctx; 420276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname); 421321369Sdim if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0); 422288943Sdim char *domain = REAL(textdomain)(domainname); 423276789Sdim if (domain) { 424276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1); 425276789Sdim } 426276789Sdim return domain; 427276789Sdim} 428276789Sdim#define INIT_TEXTDOMAIN COMMON_INTERCEPT_FUNCTION(textdomain) 429276789Sdim#else 430276789Sdim#define INIT_TEXTDOMAIN 431276789Sdim#endif 432276789Sdim 433274201Sdim#if SANITIZER_INTERCEPT_STRCMP 434274201Sdimstatic inline int CharCmpX(unsigned char c1, unsigned char c2) { 435274201Sdim return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 436274201Sdim} 437274201Sdim 438296417SdimDECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc, 439296417Sdim const char *s1, const char *s2, int result) 440296417Sdim 441274201SdimINTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 442274201Sdim void *ctx; 443274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2); 444274201Sdim unsigned char c1, c2; 445274201Sdim uptr i; 446274201Sdim for (i = 0;; i++) { 447274201Sdim c1 = (unsigned char)s1[i]; 448274201Sdim c2 = (unsigned char)s2[i]; 449274201Sdim if (c1 != c2 || c1 == '\0') break; 450274201Sdim } 451288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); 452288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); 453296417Sdim int result = CharCmpX(c1, c2); 454296417Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1, 455296417Sdim s2, result); 456296417Sdim return result; 457274201Sdim} 458274201Sdim 459296417SdimDECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc, 460296417Sdim const char *s1, const char *s2, uptr n, 461296417Sdim int result) 462296417Sdim 463274201SdimINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 464276789Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 465276789Sdim return internal_strncmp(s1, s2, size); 466274201Sdim void *ctx; 467274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size); 468274201Sdim unsigned char c1 = 0, c2 = 0; 469274201Sdim uptr i; 470274201Sdim for (i = 0; i < size; i++) { 471274201Sdim c1 = (unsigned char)s1[i]; 472274201Sdim c2 = (unsigned char)s2[i]; 473274201Sdim if (c1 != c2 || c1 == '\0') break; 474274201Sdim } 475314564Sdim uptr i1 = i; 476314564Sdim uptr i2 = i; 477314564Sdim if (common_flags()->strict_string_checks) { 478314564Sdim for (; i1 < size && s1[i1]; i1++) {} 479314564Sdim for (; i2 < size && s2[i2]; i2++) {} 480314564Sdim } 481314564Sdim COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size)); 482314564Sdim COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size)); 483296417Sdim int result = CharCmpX(c1, c2); 484296417Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1, 485296417Sdim s2, size, result); 486296417Sdim return result; 487274201Sdim} 488274201Sdim 489274201Sdim#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp) 490274201Sdim#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp) 491274201Sdim#else 492274201Sdim#define INIT_STRCMP 493274201Sdim#define INIT_STRNCMP 494274201Sdim#endif 495274201Sdim 496251034Sed#if SANITIZER_INTERCEPT_STRCASECMP 497251034Sedstatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) { 498251034Sed int c1_low = ToLower(c1); 499251034Sed int c2_low = ToLower(c2); 500251034Sed return c1_low - c2_low; 501251034Sed} 502251034Sed 503309124SdimDECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc, 504309124Sdim const char *s1, const char *s2, int result) 505309124Sdim 506251034SedINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) { 507251034Sed void *ctx; 508251034Sed COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2); 509251034Sed unsigned char c1 = 0, c2 = 0; 510251034Sed uptr i; 511274201Sdim for (i = 0;; i++) { 512251034Sed c1 = (unsigned char)s1[i]; 513251034Sed c2 = (unsigned char)s2[i]; 514274201Sdim if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 515251034Sed } 516288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); 517288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); 518309124Sdim int result = CharCaseCmp(c1, c2); 519309124Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(), 520309124Sdim s1, s2, result); 521309124Sdim return result; 522251034Sed} 523251034Sed 524309124SdimDECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc, 525314564Sdim const char *s1, const char *s2, uptr size, 526309124Sdim int result) 527309124Sdim 528314564SdimINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) { 529251034Sed void *ctx; 530314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size); 531251034Sed unsigned char c1 = 0, c2 = 0; 532251034Sed uptr i; 533314564Sdim for (i = 0; i < size; i++) { 534251034Sed c1 = (unsigned char)s1[i]; 535251034Sed c2 = (unsigned char)s2[i]; 536274201Sdim if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 537251034Sed } 538314564Sdim uptr i1 = i; 539314564Sdim uptr i2 = i; 540314564Sdim if (common_flags()->strict_string_checks) { 541314564Sdim for (; i1 < size && s1[i1]; i1++) {} 542314564Sdim for (; i2 < size && s2[i2]; i2++) {} 543314564Sdim } 544314564Sdim COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size)); 545314564Sdim COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size)); 546309124Sdim int result = CharCaseCmp(c1, c2); 547309124Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(), 548314564Sdim s1, s2, size, result); 549309124Sdim return result; 550251034Sed} 551251034Sed 552274201Sdim#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp) 553274201Sdim#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp) 554251034Sed#else 555251034Sed#define INIT_STRCASECMP 556251034Sed#define INIT_STRNCASECMP 557251034Sed#endif 558251034Sed 559288943Sdim#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR 560288943Sdimstatic inline void StrstrCheck(void *ctx, char *r, const char *s1, 561288943Sdim const char *s2) { 562288943Sdim uptr len1 = REAL(strlen)(s1); 563288943Sdim uptr len2 = REAL(strlen)(s2); 564321369Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1); 565288943Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1); 566288943Sdim} 567288943Sdim#endif 568288943Sdim 569288943Sdim#if SANITIZER_INTERCEPT_STRSTR 570309124Sdim 571309124SdimDECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc, 572314564Sdim const char *s1, const char *s2, char *result) 573309124Sdim 574288943SdimINTERCEPTOR(char*, strstr, const char *s1, const char *s2) { 575288943Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 576288943Sdim return internal_strstr(s1, s2); 577288943Sdim void *ctx; 578288943Sdim COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2); 579288943Sdim char *r = REAL(strstr)(s1, s2); 580288943Sdim if (common_flags()->intercept_strstr) 581288943Sdim StrstrCheck(ctx, r, s1, s2); 582309124Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1, 583309124Sdim s2, r); 584288943Sdim return r; 585288943Sdim} 586288943Sdim 587288943Sdim#define INIT_STRSTR COMMON_INTERCEPT_FUNCTION(strstr); 588288943Sdim#else 589288943Sdim#define INIT_STRSTR 590288943Sdim#endif 591288943Sdim 592288943Sdim#if SANITIZER_INTERCEPT_STRCASESTR 593309124Sdim 594309124SdimDECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc, 595314564Sdim const char *s1, const char *s2, char *result) 596309124Sdim 597288943SdimINTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) { 598288943Sdim void *ctx; 599288943Sdim COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2); 600288943Sdim char *r = REAL(strcasestr)(s1, s2); 601288943Sdim if (common_flags()->intercept_strstr) 602288943Sdim StrstrCheck(ctx, r, s1, s2); 603309124Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(), 604309124Sdim s1, s2, r); 605288943Sdim return r; 606288943Sdim} 607288943Sdim 608288943Sdim#define INIT_STRCASESTR COMMON_INTERCEPT_FUNCTION(strcasestr); 609288943Sdim#else 610288943Sdim#define INIT_STRCASESTR 611288943Sdim#endif 612288943Sdim 613321369Sdim#if SANITIZER_INTERCEPT_STRTOK 614321369Sdim 615321369SdimINTERCEPTOR(char*, strtok, char *str, const char *delimiters) { 616321369Sdim void *ctx; 617321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters); 618321369Sdim if (!common_flags()->intercept_strtok) { 619321369Sdim return REAL(strtok)(str, delimiters); 620321369Sdim } 621321369Sdim if (common_flags()->strict_string_checks) { 622321369Sdim // If strict_string_checks is enabled, we check the whole first argument 623321369Sdim // string on the first call (strtok saves this string in a static buffer 624321369Sdim // for subsequent calls). We do not need to check strtok's result. 625321369Sdim // As the delimiters can change, we check them every call. 626321369Sdim if (str != nullptr) { 627321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1); 628321369Sdim } 629321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 630321369Sdim REAL(strlen)(delimiters) + 1); 631321369Sdim return REAL(strtok)(str, delimiters); 632321369Sdim } else { 633321369Sdim // However, when strict_string_checks is disabled we cannot check the 634321369Sdim // whole string on the first call. Instead, we check the result string 635321369Sdim // which is guaranteed to be a NULL-terminated substring of the first 636321369Sdim // argument. We also conservatively check one character of str and the 637321369Sdim // delimiters. 638321369Sdim if (str != nullptr) { 639321369Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1); 640321369Sdim } 641321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1); 642321369Sdim char *result = REAL(strtok)(str, delimiters); 643321369Sdim if (result != nullptr) { 644321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1); 645321369Sdim } else if (str != nullptr) { 646321369Sdim // No delimiter were found, it's safe to assume that the entire str was 647321369Sdim // scanned. 648321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1); 649321369Sdim } 650321369Sdim return result; 651321369Sdim } 652321369Sdim} 653321369Sdim 654321369Sdim#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok) 655321369Sdim#else 656321369Sdim#define INIT_STRTOK 657321369Sdim#endif 658321369Sdim 659309124Sdim#if SANITIZER_INTERCEPT_MEMMEM 660309124SdimDECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc, 661309124Sdim const void *s1, SIZE_T len1, const void *s2, 662314564Sdim SIZE_T len2, void *result) 663309124Sdim 664309124SdimINTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2, 665309124Sdim SIZE_T len2) { 666309124Sdim void *ctx; 667309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2); 668309124Sdim void *r = REAL(memmem)(s1, len1, s2, len2); 669309124Sdim if (common_flags()->intercept_memmem) { 670309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1); 671309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2); 672309124Sdim } 673309124Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(), 674309124Sdim s1, len1, s2, len2, r); 675309124Sdim return r; 676309124Sdim} 677309124Sdim 678309124Sdim#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem); 679309124Sdim#else 680309124Sdim#define INIT_MEMMEM 681309124Sdim#endif // SANITIZER_INTERCEPT_MEMMEM 682309124Sdim 683309124Sdim#if SANITIZER_INTERCEPT_STRCHR 684309124SdimINTERCEPTOR(char*, strchr, const char *s, int c) { 685309124Sdim void *ctx; 686309124Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 687309124Sdim return internal_strchr(s, c); 688309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c); 689309124Sdim char *result = REAL(strchr)(s, c); 690321369Sdim if (common_flags()->intercept_strchr) { 691321369Sdim // Keep strlen as macro argument, as macro may ignore it. 692321369Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s, 693321369Sdim (result ? result - s : REAL(strlen)(s)) + 1); 694321369Sdim } 695309124Sdim return result; 696309124Sdim} 697309124Sdim#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr) 698309124Sdim#else 699309124Sdim#define INIT_STRCHR 700309124Sdim#endif 701309124Sdim 702309124Sdim#if SANITIZER_INTERCEPT_STRCHRNUL 703309124SdimINTERCEPTOR(char*, strchrnul, const char *s, int c) { 704309124Sdim void *ctx; 705309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c); 706309124Sdim char *result = REAL(strchrnul)(s, c); 707309124Sdim uptr len = result - s + 1; 708309124Sdim if (common_flags()->intercept_strchr) 709309124Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s, len); 710309124Sdim return result; 711309124Sdim} 712309124Sdim#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul) 713309124Sdim#else 714309124Sdim#define INIT_STRCHRNUL 715309124Sdim#endif 716309124Sdim 717309124Sdim#if SANITIZER_INTERCEPT_STRRCHR 718309124SdimINTERCEPTOR(char*, strrchr, const char *s, int c) { 719309124Sdim void *ctx; 720309124Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 721309124Sdim return internal_strrchr(s, c); 722309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c); 723309124Sdim if (common_flags()->intercept_strchr) 724321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); 725309124Sdim return REAL(strrchr)(s, c); 726309124Sdim} 727309124Sdim#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr) 728309124Sdim#else 729309124Sdim#define INIT_STRRCHR 730309124Sdim#endif 731309124Sdim 732288943Sdim#if SANITIZER_INTERCEPT_STRSPN 733288943SdimINTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) { 734288943Sdim void *ctx; 735288943Sdim COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2); 736288943Sdim SIZE_T r = REAL(strspn)(s1, s2); 737288943Sdim if (common_flags()->intercept_strspn) { 738288943Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1); 739288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1); 740288943Sdim } 741288943Sdim return r; 742288943Sdim} 743288943Sdim 744288943SdimINTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) { 745288943Sdim void *ctx; 746288943Sdim COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2); 747288943Sdim SIZE_T r = REAL(strcspn)(s1, s2); 748288943Sdim if (common_flags()->intercept_strspn) { 749288943Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1); 750288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1); 751288943Sdim } 752288943Sdim return r; 753288943Sdim} 754288943Sdim 755288943Sdim#define INIT_STRSPN \ 756288943Sdim COMMON_INTERCEPT_FUNCTION(strspn); \ 757288943Sdim COMMON_INTERCEPT_FUNCTION(strcspn); 758288943Sdim#else 759288943Sdim#define INIT_STRSPN 760288943Sdim#endif 761288943Sdim 762288943Sdim#if SANITIZER_INTERCEPT_STRPBRK 763288943SdimINTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) { 764288943Sdim void *ctx; 765288943Sdim COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2); 766288943Sdim char *r = REAL(strpbrk)(s1, s2); 767288943Sdim if (common_flags()->intercept_strpbrk) { 768288943Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1); 769288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s1, 770288943Sdim r ? r - s1 + 1 : REAL(strlen)(s1) + 1); 771288943Sdim } 772288943Sdim return r; 773288943Sdim} 774288943Sdim 775288943Sdim#define INIT_STRPBRK COMMON_INTERCEPT_FUNCTION(strpbrk); 776288943Sdim#else 777288943Sdim#define INIT_STRPBRK 778288943Sdim#endif 779288943Sdim 780309124Sdim#if SANITIZER_INTERCEPT_MEMSET 781314564SdimINTERCEPTOR(void *, memset, void *dst, int v, uptr size) { 782309124Sdim void *ctx; 783314564Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size); 784309124Sdim} 785309124Sdim 786309124Sdim#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset) 787309124Sdim#else 788309124Sdim#define INIT_MEMSET 789309124Sdim#endif 790309124Sdim 791309124Sdim#if SANITIZER_INTERCEPT_MEMMOVE 792314564SdimINTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) { 793309124Sdim void *ctx; 794314564Sdim COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); 795309124Sdim} 796309124Sdim 797309124Sdim#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove) 798309124Sdim#else 799309124Sdim#define INIT_MEMMOVE 800309124Sdim#endif 801309124Sdim 802309124Sdim#if SANITIZER_INTERCEPT_MEMCPY 803314564SdimINTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) { 804314564Sdim // On OS X, calling internal_memcpy here will cause memory corruptions, 805314564Sdim // because memcpy and memmove are actually aliases of the same 806314564Sdim // implementation. We need to use internal_memmove here. 807314564Sdim // N.B.: If we switch this to internal_ we'll have to use internal_memmove 808314564Sdim // due to memcpy being an alias of memmove on OS X. 809309124Sdim void *ctx; 810314564Sdim if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 811314564Sdim COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size); 812314564Sdim } else { 813314564Sdim COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); 814309124Sdim } 815309124Sdim} 816309124Sdim 817314564Sdim#define INIT_MEMCPY \ 818314564Sdim do { \ 819314564Sdim if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \ 820314564Sdim COMMON_INTERCEPT_FUNCTION(memcpy); \ 821314564Sdim } else { \ 822314564Sdim ASSIGN_REAL(memcpy, memmove); \ 823314564Sdim } \ 824314564Sdim CHECK(REAL(memcpy)); \ 825314564Sdim } while (false) 826314564Sdim 827309124Sdim#else 828309124Sdim#define INIT_MEMCPY 829309124Sdim#endif 830309124Sdim 831296417Sdim#if SANITIZER_INTERCEPT_MEMCMP 832296417SdimDECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc, 833296417Sdim const void *s1, const void *s2, uptr n, 834296417Sdim int result) 835296417Sdim 836353358Sdim// Common code for `memcmp` and `bcmp`. 837353358Sdimint MemcmpInterceptorCommon(void *ctx, 838353358Sdim int (*real_fn)(const void *, const void *, uptr), 839353358Sdim const void *a1, const void *a2, uptr size) { 840296417Sdim if (common_flags()->intercept_memcmp) { 841296417Sdim if (common_flags()->strict_memcmp) { 842296417Sdim // Check the entire regions even if the first bytes of the buffers are 843296417Sdim // different. 844296417Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size); 845296417Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size); 846296417Sdim // Fallthrough to REAL(memcmp) below. 847296417Sdim } else { 848296417Sdim unsigned char c1 = 0, c2 = 0; 849296417Sdim const unsigned char *s1 = (const unsigned char*)a1; 850296417Sdim const unsigned char *s2 = (const unsigned char*)a2; 851296417Sdim uptr i; 852296417Sdim for (i = 0; i < size; i++) { 853296417Sdim c1 = s1[i]; 854296417Sdim c2 = s2[i]; 855296417Sdim if (c1 != c2) break; 856296417Sdim } 857296417Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size)); 858296417Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size)); 859296417Sdim int r = CharCmpX(c1, c2); 860296417Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), 861296417Sdim a1, a2, size, r); 862296417Sdim return r; 863296417Sdim } 864296417Sdim } 865353358Sdim int result = real_fn(a1, a2, size); 866296417Sdim CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1, 867296417Sdim a2, size, result); 868296417Sdim return result; 869296417Sdim} 870296417Sdim 871353358SdimINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 872353358Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 873353358Sdim return internal_memcmp(a1, a2, size); 874353358Sdim void *ctx; 875353358Sdim COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size); 876353358Sdim return MemcmpInterceptorCommon(ctx, REAL(memcmp), a1, a2, size); 877353358Sdim} 878353358Sdim 879296417Sdim#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp) 880296417Sdim#else 881296417Sdim#define INIT_MEMCMP 882296417Sdim#endif 883296417Sdim 884353358Sdim#if SANITIZER_INTERCEPT_BCMP 885353358SdimINTERCEPTOR(int, bcmp, const void *a1, const void *a2, uptr size) { 886353358Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 887353358Sdim return internal_memcmp(a1, a2, size); 888353358Sdim void *ctx; 889353358Sdim COMMON_INTERCEPTOR_ENTER(ctx, bcmp, a1, a2, size); 890353358Sdim return MemcmpInterceptorCommon(ctx, REAL(bcmp), a1, a2, size); 891353358Sdim} 892353358Sdim 893353358Sdim#define INIT_BCMP COMMON_INTERCEPT_FUNCTION(bcmp) 894353358Sdim#else 895353358Sdim#define INIT_BCMP 896353358Sdim#endif 897353358Sdim 898276789Sdim#if SANITIZER_INTERCEPT_MEMCHR 899276789SdimINTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) { 900296417Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 901296417Sdim return internal_memchr(s, c, n); 902276789Sdim void *ctx; 903276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n); 904314564Sdim#if SANITIZER_WINDOWS 905314564Sdim void *res; 906314564Sdim if (REAL(memchr)) { 907314564Sdim res = REAL(memchr)(s, c, n); 908314564Sdim } else { 909314564Sdim res = internal_memchr(s, c, n); 910314564Sdim } 911314564Sdim#else 912276789Sdim void *res = REAL(memchr)(s, c, n); 913314564Sdim#endif 914276789Sdim uptr len = res ? (char *)res - (const char *)s + 1 : n; 915276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len); 916276789Sdim return res; 917276789Sdim} 918276789Sdim 919276789Sdim#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr) 920276789Sdim#else 921276789Sdim#define INIT_MEMCHR 922276789Sdim#endif 923276789Sdim 924276789Sdim#if SANITIZER_INTERCEPT_MEMRCHR 925276789SdimINTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) { 926276789Sdim void *ctx; 927276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n); 928276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n); 929276789Sdim return REAL(memrchr)(s, c, n); 930276789Sdim} 931276789Sdim 932276789Sdim#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr) 933276789Sdim#else 934276789Sdim#define INIT_MEMRCHR 935276789Sdim#endif 936276789Sdim 937251034Sed#if SANITIZER_INTERCEPT_FREXP 938251034SedINTERCEPTOR(double, frexp, double x, int *exp) { 939251034Sed void *ctx; 940251034Sed COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp); 941276789Sdim // Assuming frexp() always writes to |exp|. 942276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); 943251034Sed double res = REAL(frexp)(x, exp); 944251034Sed return res; 945251034Sed} 946251034Sed 947274201Sdim#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp); 948251034Sed#else 949251034Sed#define INIT_FREXP 950274201Sdim#endif // SANITIZER_INTERCEPT_FREXP 951251034Sed 952251034Sed#if SANITIZER_INTERCEPT_FREXPF_FREXPL 953251034SedINTERCEPTOR(float, frexpf, float x, int *exp) { 954251034Sed void *ctx; 955251034Sed COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp); 956276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 957276789Sdim // its metadata. See 958296417Sdim // https://github.com/google/sanitizers/issues/321. 959251034Sed float res = REAL(frexpf)(x, exp); 960251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); 961251034Sed return res; 962251034Sed} 963251034Sed 964251034SedINTERCEPTOR(long double, frexpl, long double x, int *exp) { 965251034Sed void *ctx; 966251034Sed COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp); 967276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 968276789Sdim // its metadata. See 969296417Sdim // https://github.com/google/sanitizers/issues/321. 970251034Sed long double res = REAL(frexpl)(x, exp); 971251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); 972251034Sed return res; 973251034Sed} 974251034Sed 975274201Sdim#define INIT_FREXPF_FREXPL \ 976274201Sdim COMMON_INTERCEPT_FUNCTION(frexpf); \ 977309124Sdim COMMON_INTERCEPT_FUNCTION_LDBL(frexpl) 978251034Sed#else 979251034Sed#define INIT_FREXPF_FREXPL 980274201Sdim#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL 981251034Sed 982327952Sdim#if SI_POSIX 983274201Sdimstatic void write_iovec(void *ctx, struct __sanitizer_iovec *iovec, 984274201Sdim SIZE_T iovlen, SIZE_T maxlen) { 985274201Sdim for (SIZE_T i = 0; i < iovlen && maxlen; ++i) { 986274201Sdim SSIZE_T sz = Min(iovec[i].iov_len, maxlen); 987274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz); 988274201Sdim maxlen -= sz; 989274201Sdim } 990274201Sdim} 991274201Sdim 992274201Sdimstatic void read_iovec(void *ctx, struct __sanitizer_iovec *iovec, 993274201Sdim SIZE_T iovlen, SIZE_T maxlen) { 994274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen); 995274201Sdim for (SIZE_T i = 0; i < iovlen && maxlen; ++i) { 996274201Sdim SSIZE_T sz = Min(iovec[i].iov_len, maxlen); 997274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz); 998274201Sdim maxlen -= sz; 999274201Sdim } 1000274201Sdim} 1001274201Sdim#endif 1002274201Sdim 1003245614Sandrew#if SANITIZER_INTERCEPT_READ 1004245614SandrewINTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) { 1005251034Sed void *ctx; 1006245614Sandrew COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count); 1007274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1008276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1009276789Sdim // its metadata. See 1010296417Sdim // https://github.com/google/sanitizers/issues/321. 1011245614Sandrew SSIZE_T res = REAL(read)(fd, ptr, count); 1012274201Sdim if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); 1013274201Sdim if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 1014245614Sandrew return res; 1015245614Sandrew} 1016274201Sdim#define INIT_READ COMMON_INTERCEPT_FUNCTION(read) 1017245614Sandrew#else 1018251034Sed#define INIT_READ 1019245614Sandrew#endif 1020245614Sandrew 1021321369Sdim#if SANITIZER_INTERCEPT_FREAD 1022321369SdimINTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) { 1023321369Sdim // libc file streams can call user-supplied functions, see fopencookie. 1024321369Sdim void *ctx; 1025321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file); 1026321369Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1027321369Sdim // its metadata. See 1028321369Sdim // https://github.com/google/sanitizers/issues/321. 1029321369Sdim SIZE_T res = REAL(fread)(ptr, size, nmemb, file); 1030321369Sdim if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size); 1031321369Sdim return res; 1032321369Sdim} 1033321369Sdim#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread) 1034321369Sdim#else 1035321369Sdim#define INIT_FREAD 1036321369Sdim#endif 1037321369Sdim 1038245614Sandrew#if SANITIZER_INTERCEPT_PREAD 1039245614SandrewINTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) { 1040251034Sed void *ctx; 1041245614Sandrew COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset); 1042274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1043276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1044276789Sdim // its metadata. See 1045296417Sdim // https://github.com/google/sanitizers/issues/321. 1046245614Sandrew SSIZE_T res = REAL(pread)(fd, ptr, count, offset); 1047274201Sdim if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); 1048274201Sdim if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 1049245614Sandrew return res; 1050245614Sandrew} 1051274201Sdim#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread) 1052245614Sandrew#else 1053251034Sed#define INIT_PREAD 1054245614Sandrew#endif 1055245614Sandrew 1056245614Sandrew#if SANITIZER_INTERCEPT_PREAD64 1057245614SandrewINTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) { 1058251034Sed void *ctx; 1059245614Sandrew COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset); 1060274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1061276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1062276789Sdim // its metadata. See 1063296417Sdim // https://github.com/google/sanitizers/issues/321. 1064245614Sandrew SSIZE_T res = REAL(pread64)(fd, ptr, count, offset); 1065274201Sdim if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); 1066274201Sdim if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 1067245614Sandrew return res; 1068245614Sandrew} 1069274201Sdim#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64) 1070245614Sandrew#else 1071251034Sed#define INIT_PREAD64 1072245614Sandrew#endif 1073245614Sandrew 1074274201Sdim#if SANITIZER_INTERCEPT_READV 1075274201SdimINTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov, 1076274201Sdim int iovcnt) { 1077274201Sdim void *ctx; 1078274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt); 1079274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1080274201Sdim SSIZE_T res = REAL(readv)(fd, iov, iovcnt); 1081274201Sdim if (res > 0) write_iovec(ctx, iov, iovcnt, res); 1082274201Sdim if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 1083274201Sdim return res; 1084274201Sdim} 1085274201Sdim#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv) 1086274201Sdim#else 1087274201Sdim#define INIT_READV 1088274201Sdim#endif 1089274201Sdim 1090274201Sdim#if SANITIZER_INTERCEPT_PREADV 1091274201SdimINTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt, 1092274201Sdim OFF_T offset) { 1093274201Sdim void *ctx; 1094274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset); 1095274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1096274201Sdim SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset); 1097274201Sdim if (res > 0) write_iovec(ctx, iov, iovcnt, res); 1098274201Sdim if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 1099274201Sdim return res; 1100274201Sdim} 1101274201Sdim#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv) 1102274201Sdim#else 1103274201Sdim#define INIT_PREADV 1104274201Sdim#endif 1105274201Sdim 1106274201Sdim#if SANITIZER_INTERCEPT_PREADV64 1107274201SdimINTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt, 1108274201Sdim OFF64_T offset) { 1109274201Sdim void *ctx; 1110274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset); 1111274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1112274201Sdim SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset); 1113274201Sdim if (res > 0) write_iovec(ctx, iov, iovcnt, res); 1114274201Sdim if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 1115274201Sdim return res; 1116274201Sdim} 1117274201Sdim#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64) 1118274201Sdim#else 1119274201Sdim#define INIT_PREADV64 1120274201Sdim#endif 1121274201Sdim 1122245614Sandrew#if SANITIZER_INTERCEPT_WRITE 1123245614SandrewINTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) { 1124251034Sed void *ctx; 1125245614Sandrew COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count); 1126274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1127274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 1128245614Sandrew SSIZE_T res = REAL(write)(fd, ptr, count); 1129274201Sdim // FIXME: this check should be _before_ the call to REAL(write), not after 1130274201Sdim if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); 1131245614Sandrew return res; 1132245614Sandrew} 1133274201Sdim#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write) 1134245614Sandrew#else 1135251034Sed#define INIT_WRITE 1136245614Sandrew#endif 1137245614Sandrew 1138321369Sdim#if SANITIZER_INTERCEPT_FWRITE 1139321369SdimINTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) { 1140321369Sdim // libc file streams can call user-supplied functions, see fopencookie. 1141321369Sdim void *ctx; 1142321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file); 1143321369Sdim SIZE_T res = REAL(fwrite)(p, size, nmemb, file); 1144321369Sdim if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size); 1145321369Sdim return res; 1146321369Sdim} 1147321369Sdim#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite) 1148321369Sdim#else 1149321369Sdim#define INIT_FWRITE 1150321369Sdim#endif 1151321369Sdim 1152245614Sandrew#if SANITIZER_INTERCEPT_PWRITE 1153251034SedINTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) { 1154251034Sed void *ctx; 1155251034Sed COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset); 1156274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1157274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 1158251034Sed SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset); 1159274201Sdim if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); 1160245614Sandrew return res; 1161245614Sandrew} 1162274201Sdim#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite) 1163245614Sandrew#else 1164251034Sed#define INIT_PWRITE 1165245614Sandrew#endif 1166245614Sandrew 1167245614Sandrew#if SANITIZER_INTERCEPT_PWRITE64 1168251034SedINTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count, 1169251034Sed OFF64_T offset) { 1170251034Sed void *ctx; 1171251034Sed COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset); 1172274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1173274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 1174251034Sed SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset); 1175274201Sdim if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); 1176245614Sandrew return res; 1177245614Sandrew} 1178274201Sdim#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64) 1179245614Sandrew#else 1180251034Sed#define INIT_PWRITE64 1181245614Sandrew#endif 1182245614Sandrew 1183274201Sdim#if SANITIZER_INTERCEPT_WRITEV 1184274201SdimINTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov, 1185274201Sdim int iovcnt) { 1186274201Sdim void *ctx; 1187274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt); 1188274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1189274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 1190274201Sdim SSIZE_T res = REAL(writev)(fd, iov, iovcnt); 1191274201Sdim if (res > 0) read_iovec(ctx, iov, iovcnt, res); 1192274201Sdim return res; 1193274201Sdim} 1194274201Sdim#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev) 1195274201Sdim#else 1196274201Sdim#define INIT_WRITEV 1197274201Sdim#endif 1198274201Sdim 1199274201Sdim#if SANITIZER_INTERCEPT_PWRITEV 1200274201SdimINTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt, 1201274201Sdim OFF_T offset) { 1202274201Sdim void *ctx; 1203274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset); 1204274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1205274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 1206274201Sdim SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset); 1207274201Sdim if (res > 0) read_iovec(ctx, iov, iovcnt, res); 1208274201Sdim return res; 1209274201Sdim} 1210274201Sdim#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev) 1211274201Sdim#else 1212274201Sdim#define INIT_PWRITEV 1213274201Sdim#endif 1214274201Sdim 1215274201Sdim#if SANITIZER_INTERCEPT_PWRITEV64 1216274201SdimINTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt, 1217274201Sdim OFF64_T offset) { 1218274201Sdim void *ctx; 1219274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset); 1220274201Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 1221274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 1222274201Sdim SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset); 1223274201Sdim if (res > 0) read_iovec(ctx, iov, iovcnt, res); 1224274201Sdim return res; 1225274201Sdim} 1226274201Sdim#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64) 1227274201Sdim#else 1228274201Sdim#define INIT_PWRITEV64 1229274201Sdim#endif 1230274201Sdim 1231341825Sdim#if SANITIZER_INTERCEPT_FGETS 1232341825SdimINTERCEPTOR(char *, fgets, char *s, SIZE_T size, void *file) { 1233341825Sdim // libc file streams can call user-supplied functions, see fopencookie. 1234341825Sdim void *ctx; 1235341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, fgets, s, size, file); 1236341825Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1237341825Sdim // its metadata. See 1238341825Sdim // https://github.com/google/sanitizers/issues/321. 1239341825Sdim char *res = REAL(fgets)(s, size, file); 1240341825Sdim if (res) 1241341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1); 1242341825Sdim return res; 1243341825Sdim} 1244341825Sdim#define INIT_FGETS COMMON_INTERCEPT_FUNCTION(fgets) 1245341825Sdim#else 1246341825Sdim#define INIT_FGETS 1247341825Sdim#endif 1248341825Sdim 1249341825Sdim#if SANITIZER_INTERCEPT_FPUTS 1250341825SdimINTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) { 1251341825Sdim // libc file streams can call user-supplied functions, see fopencookie. 1252341825Sdim void *ctx; 1253341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file); 1254360784Sdim if (!SANITIZER_MAC || s) { // `fputs(NULL, file)` is supported on Darwin. 1255353358Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); 1256360784Sdim } 1257341825Sdim return REAL(fputs)(s, file); 1258341825Sdim} 1259341825Sdim#define INIT_FPUTS COMMON_INTERCEPT_FUNCTION(fputs) 1260341825Sdim#else 1261341825Sdim#define INIT_FPUTS 1262341825Sdim#endif 1263341825Sdim 1264341825Sdim#if SANITIZER_INTERCEPT_PUTS 1265341825SdimINTERCEPTOR(int, puts, char *s) { 1266341825Sdim // libc file streams can call user-supplied functions, see fopencookie. 1267341825Sdim void *ctx; 1268341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, puts, s); 1269360784Sdim if (!SANITIZER_MAC || s) { // `puts(NULL)` is supported on Darwin. 1270353358Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); 1271360784Sdim } 1272341825Sdim return REAL(puts)(s); 1273341825Sdim} 1274341825Sdim#define INIT_PUTS COMMON_INTERCEPT_FUNCTION(puts) 1275341825Sdim#else 1276341825Sdim#define INIT_PUTS 1277341825Sdim#endif 1278341825Sdim 1279245614Sandrew#if SANITIZER_INTERCEPT_PRCTL 1280360784SdimINTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3, 1281360784Sdim unsigned long arg4, unsigned long arg5) { 1282251034Sed void *ctx; 1283245614Sandrew COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5); 1284245614Sandrew static const int PR_SET_NAME = 15; 1285245614Sandrew int res = REAL(prctl(option, arg2, arg3, arg4, arg5)); 1286245614Sandrew if (option == PR_SET_NAME) { 1287245614Sandrew char buff[16]; 1288251034Sed internal_strncpy(buff, (char *)arg2, 15); 1289245614Sandrew buff[15] = 0; 1290245614Sandrew COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff); 1291245614Sandrew } 1292245614Sandrew return res; 1293245614Sandrew} 1294274201Sdim#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl) 1295245614Sandrew#else 1296251034Sed#define INIT_PRCTL 1297274201Sdim#endif // SANITIZER_INTERCEPT_PRCTL 1298245614Sandrew 1299251034Sed#if SANITIZER_INTERCEPT_TIME 1300251034SedINTERCEPTOR(unsigned long, time, unsigned long *t) { 1301251034Sed void *ctx; 1302251034Sed COMMON_INTERCEPTOR_ENTER(ctx, time, t); 1303276789Sdim unsigned long local_t; 1304276789Sdim unsigned long res = REAL(time)(&local_t); 1305251034Sed if (t && res != (unsigned long)-1) { 1306251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t)); 1307276789Sdim *t = local_t; 1308251034Sed } 1309251034Sed return res; 1310251034Sed} 1311274201Sdim#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time); 1312251034Sed#else 1313251034Sed#define INIT_TIME 1314274201Sdim#endif // SANITIZER_INTERCEPT_TIME 1315251034Sed 1316251034Sed#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS 1317274201Sdimstatic void unpoison_tm(void *ctx, __sanitizer_tm *tm) { 1318274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm)); 1319327952Sdim#if !SANITIZER_SOLARIS 1320274201Sdim if (tm->tm_zone) { 1321274201Sdim // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone 1322274201Sdim // can point to shared memory and tsan would report a data race. 1323276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone, 1324274201Sdim REAL(strlen(tm->tm_zone)) + 1); 1325274201Sdim } 1326327952Sdim#endif 1327274201Sdim} 1328274201SdimINTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) { 1329251034Sed void *ctx; 1330251034Sed COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep); 1331274201Sdim __sanitizer_tm *res = REAL(localtime)(timep); 1332251034Sed if (res) { 1333251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); 1334274201Sdim unpoison_tm(ctx, res); 1335251034Sed } 1336251034Sed return res; 1337251034Sed} 1338274201SdimINTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) { 1339251034Sed void *ctx; 1340251034Sed COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result); 1341274201Sdim __sanitizer_tm *res = REAL(localtime_r)(timep, result); 1342251034Sed if (res) { 1343251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); 1344274201Sdim unpoison_tm(ctx, res); 1345251034Sed } 1346251034Sed return res; 1347251034Sed} 1348274201SdimINTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) { 1349251034Sed void *ctx; 1350251034Sed COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep); 1351274201Sdim __sanitizer_tm *res = REAL(gmtime)(timep); 1352251034Sed if (res) { 1353251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); 1354274201Sdim unpoison_tm(ctx, res); 1355251034Sed } 1356251034Sed return res; 1357251034Sed} 1358274201SdimINTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) { 1359251034Sed void *ctx; 1360251034Sed COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result); 1361274201Sdim __sanitizer_tm *res = REAL(gmtime_r)(timep, result); 1362251034Sed if (res) { 1363251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); 1364274201Sdim unpoison_tm(ctx, res); 1365251034Sed } 1366251034Sed return res; 1367251034Sed} 1368251034SedINTERCEPTOR(char *, ctime, unsigned long *timep) { 1369251034Sed void *ctx; 1370251034Sed COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep); 1371276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1372276789Sdim // its metadata. See 1373296417Sdim // https://github.com/google/sanitizers/issues/321. 1374251034Sed char *res = REAL(ctime)(timep); 1375251034Sed if (res) { 1376251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); 1377251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 1378251034Sed } 1379251034Sed return res; 1380251034Sed} 1381251034SedINTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) { 1382251034Sed void *ctx; 1383251034Sed COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result); 1384276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1385276789Sdim // its metadata. See 1386296417Sdim // https://github.com/google/sanitizers/issues/321. 1387251034Sed char *res = REAL(ctime_r)(timep, result); 1388251034Sed if (res) { 1389251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); 1390251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 1391251034Sed } 1392251034Sed return res; 1393251034Sed} 1394274201SdimINTERCEPTOR(char *, asctime, __sanitizer_tm *tm) { 1395251034Sed void *ctx; 1396251034Sed COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm); 1397276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1398276789Sdim // its metadata. See 1399296417Sdim // https://github.com/google/sanitizers/issues/321. 1400251034Sed char *res = REAL(asctime)(tm); 1401251034Sed if (res) { 1402274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm)); 1403251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 1404251034Sed } 1405251034Sed return res; 1406251034Sed} 1407274201SdimINTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) { 1408251034Sed void *ctx; 1409251034Sed COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result); 1410276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1411276789Sdim // its metadata. See 1412296417Sdim // https://github.com/google/sanitizers/issues/321. 1413251034Sed char *res = REAL(asctime_r)(tm, result); 1414251034Sed if (res) { 1415274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm)); 1416251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 1417251034Sed } 1418251034Sed return res; 1419251034Sed} 1420276789SdimINTERCEPTOR(long, mktime, __sanitizer_tm *tm) { 1421276789Sdim void *ctx; 1422276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm); 1423276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec)); 1424276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min)); 1425276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour)); 1426276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday)); 1427276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon)); 1428276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year)); 1429276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst)); 1430276789Sdim long res = REAL(mktime)(tm); 1431276789Sdim if (res != -1) unpoison_tm(ctx, tm); 1432276789Sdim return res; 1433276789Sdim} 1434274201Sdim#define INIT_LOCALTIME_AND_FRIENDS \ 1435274201Sdim COMMON_INTERCEPT_FUNCTION(localtime); \ 1436274201Sdim COMMON_INTERCEPT_FUNCTION(localtime_r); \ 1437274201Sdim COMMON_INTERCEPT_FUNCTION(gmtime); \ 1438274201Sdim COMMON_INTERCEPT_FUNCTION(gmtime_r); \ 1439274201Sdim COMMON_INTERCEPT_FUNCTION(ctime); \ 1440274201Sdim COMMON_INTERCEPT_FUNCTION(ctime_r); \ 1441274201Sdim COMMON_INTERCEPT_FUNCTION(asctime); \ 1442276789Sdim COMMON_INTERCEPT_FUNCTION(asctime_r); \ 1443276789Sdim COMMON_INTERCEPT_FUNCTION(mktime); 1444251034Sed#else 1445251034Sed#define INIT_LOCALTIME_AND_FRIENDS 1446274201Sdim#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS 1447251034Sed 1448274201Sdim#if SANITIZER_INTERCEPT_STRPTIME 1449274201SdimINTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) { 1450274201Sdim void *ctx; 1451274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm); 1452274201Sdim if (format) 1453274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1); 1454276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1455276789Sdim // its metadata. See 1456296417Sdim // https://github.com/google/sanitizers/issues/321. 1457274201Sdim char *res = REAL(strptime)(s, format, tm); 1458288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0); 1459288943Sdim if (res && tm) { 1460274201Sdim // Do not call unpoison_tm here, because strptime does not, in fact, 1461274201Sdim // initialize the entire struct tm. For example, tm_zone pointer is left 1462274201Sdim // uninitialized. 1463288943Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm)); 1464274201Sdim } 1465274201Sdim return res; 1466274201Sdim} 1467274201Sdim#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime); 1468274201Sdim#else 1469274201Sdim#define INIT_STRPTIME 1470274201Sdim#endif 1471274201Sdim 1472276789Sdim#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF 1473276789Sdim#include "sanitizer_common_interceptors_format.inc" 1474276789Sdim 1475276789Sdim#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...) \ 1476276789Sdim { \ 1477276789Sdim void *ctx; \ 1478276789Sdim va_list ap; \ 1479276789Sdim va_start(ap, format); \ 1480276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap); \ 1481276789Sdim int res = WRAP(vname)(__VA_ARGS__, ap); \ 1482276789Sdim va_end(ap); \ 1483276789Sdim return res; \ 1484276789Sdim } 1485276789Sdim 1486276789Sdim#endif 1487276789Sdim 1488245614Sandrew#if SANITIZER_INTERCEPT_SCANF 1489245614Sandrew 1490251034Sed#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...) \ 1491251034Sed { \ 1492251034Sed void *ctx; \ 1493251034Sed COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \ 1494251034Sed va_list aq; \ 1495251034Sed va_copy(aq, ap); \ 1496251034Sed int res = REAL(vname)(__VA_ARGS__); \ 1497251034Sed if (res > 0) \ 1498251034Sed scanf_common(ctx, res, allowGnuMalloc, format, aq); \ 1499251034Sed va_end(aq); \ 1500251034Sed return res; \ 1501251034Sed } 1502251034Sed 1503251034SedINTERCEPTOR(int, vscanf, const char *format, va_list ap) 1504251034SedVSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap) 1505251034Sed 1506251034SedINTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap) 1507251034SedVSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap) 1508251034Sed 1509251034SedINTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap) 1510251034SedVSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap) 1511251034Sed 1512251034Sed#if SANITIZER_INTERCEPT_ISOC99_SCANF 1513251034SedINTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap) 1514251034SedVSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap) 1515251034Sed 1516251034SedINTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format, 1517251034Sed va_list ap) 1518251034SedVSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap) 1519251034Sed 1520251034SedINTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap) 1521251034SedVSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap) 1522251034Sed#endif // SANITIZER_INTERCEPT_ISOC99_SCANF 1523251034Sed 1524251034SedINTERCEPTOR(int, scanf, const char *format, ...) 1525276789SdimFORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format) 1526251034Sed 1527251034SedINTERCEPTOR(int, fscanf, void *stream, const char *format, ...) 1528276789SdimFORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format) 1529251034Sed 1530251034SedINTERCEPTOR(int, sscanf, const char *str, const char *format, ...) 1531276789SdimFORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format) 1532251034Sed 1533251034Sed#if SANITIZER_INTERCEPT_ISOC99_SCANF 1534251034SedINTERCEPTOR(int, __isoc99_scanf, const char *format, ...) 1535276789SdimFORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format) 1536251034Sed 1537251034SedINTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...) 1538276789SdimFORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format) 1539251034Sed 1540251034SedINTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...) 1541276789SdimFORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) 1542251034Sed#endif 1543251034Sed 1544274201Sdim#endif 1545251034Sed 1546274201Sdim#if SANITIZER_INTERCEPT_SCANF 1547274201Sdim#define INIT_SCANF \ 1548314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(scanf); \ 1549314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(sscanf); \ 1550314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(fscanf); \ 1551314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(vscanf); \ 1552314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \ 1553314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf); 1554251034Sed#else 1555251034Sed#define INIT_SCANF 1556251034Sed#endif 1557251034Sed 1558274201Sdim#if SANITIZER_INTERCEPT_ISOC99_SCANF 1559274201Sdim#define INIT_ISOC99_SCANF \ 1560274201Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_scanf); \ 1561274201Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf); \ 1562274201Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf); \ 1563274201Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf); \ 1564274201Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \ 1565274201Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf); 1566274201Sdim#else 1567274201Sdim#define INIT_ISOC99_SCANF 1568274201Sdim#endif 1569274201Sdim 1570276789Sdim#if SANITIZER_INTERCEPT_PRINTF 1571276789Sdim 1572276789Sdim#define VPRINTF_INTERCEPTOR_ENTER(vname, ...) \ 1573276789Sdim void *ctx; \ 1574276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \ 1575276789Sdim va_list aq; \ 1576276789Sdim va_copy(aq, ap); 1577276789Sdim 1578276789Sdim#define VPRINTF_INTERCEPTOR_RETURN() \ 1579276789Sdim va_end(aq); 1580276789Sdim 1581276789Sdim#define VPRINTF_INTERCEPTOR_IMPL(vname, ...) \ 1582276789Sdim { \ 1583276789Sdim VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__); \ 1584276789Sdim if (common_flags()->check_printf) \ 1585276789Sdim printf_common(ctx, format, aq); \ 1586276789Sdim int res = REAL(vname)(__VA_ARGS__); \ 1587276789Sdim VPRINTF_INTERCEPTOR_RETURN(); \ 1588276789Sdim return res; \ 1589276789Sdim } 1590276789Sdim 1591276789Sdim// FIXME: under ASan the REAL() call below may write to freed memory and 1592276789Sdim// corrupt its metadata. See 1593296417Sdim// https://github.com/google/sanitizers/issues/321. 1594276789Sdim#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...) \ 1595276789Sdim { \ 1596276789Sdim VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__) \ 1597276789Sdim if (common_flags()->check_printf) { \ 1598276789Sdim printf_common(ctx, format, aq); \ 1599276789Sdim } \ 1600276789Sdim int res = REAL(vname)(str, __VA_ARGS__); \ 1601276789Sdim if (res >= 0) { \ 1602276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1); \ 1603276789Sdim } \ 1604276789Sdim VPRINTF_INTERCEPTOR_RETURN(); \ 1605276789Sdim return res; \ 1606276789Sdim } 1607276789Sdim 1608276789Sdim// FIXME: under ASan the REAL() call below may write to freed memory and 1609276789Sdim// corrupt its metadata. See 1610296417Sdim// https://github.com/google/sanitizers/issues/321. 1611276789Sdim#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...) \ 1612276789Sdim { \ 1613276789Sdim VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__) \ 1614276789Sdim if (common_flags()->check_printf) { \ 1615276789Sdim printf_common(ctx, format, aq); \ 1616276789Sdim } \ 1617276789Sdim int res = REAL(vname)(str, size, __VA_ARGS__); \ 1618276789Sdim if (res >= 0) { \ 1619276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1))); \ 1620276789Sdim } \ 1621276789Sdim VPRINTF_INTERCEPTOR_RETURN(); \ 1622276789Sdim return res; \ 1623276789Sdim } 1624276789Sdim 1625276789Sdim// FIXME: under ASan the REAL() call below may write to freed memory and 1626276789Sdim// corrupt its metadata. See 1627296417Sdim// https://github.com/google/sanitizers/issues/321. 1628276789Sdim#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...) \ 1629276789Sdim { \ 1630276789Sdim VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__) \ 1631276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *)); \ 1632276789Sdim if (common_flags()->check_printf) { \ 1633276789Sdim printf_common(ctx, format, aq); \ 1634276789Sdim } \ 1635276789Sdim int res = REAL(vname)(strp, __VA_ARGS__); \ 1636276789Sdim if (res >= 0) { \ 1637276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1); \ 1638276789Sdim } \ 1639276789Sdim VPRINTF_INTERCEPTOR_RETURN(); \ 1640276789Sdim return res; \ 1641276789Sdim } 1642276789Sdim 1643276789SdimINTERCEPTOR(int, vprintf, const char *format, va_list ap) 1644276789SdimVPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap) 1645276789Sdim 1646276789SdimINTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format, 1647276789Sdim va_list ap) 1648276789SdimVPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap) 1649276789Sdim 1650276789SdimINTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format, 1651276789Sdim va_list ap) 1652276789SdimVSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap) 1653276789Sdim 1654327952Sdim#if SANITIZER_INTERCEPT___PRINTF_CHK 1655327952SdimINTERCEPTOR(int, __vsnprintf_chk, char *str, SIZE_T size, int flag, 1656327952Sdim SIZE_T size_to, const char *format, va_list ap) 1657327952SdimVSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap) 1658327952Sdim#endif 1659327952Sdim 1660280031Sdim#if SANITIZER_INTERCEPT_PRINTF_L 1661280031SdimINTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc, 1662280031Sdim const char *format, va_list ap) 1663280031SdimVSNPRINTF_INTERCEPTOR_IMPL(vsnprintf_l, str, size, loc, format, ap) 1664280031Sdim 1665280031SdimINTERCEPTOR(int, snprintf_l, char *str, SIZE_T size, void *loc, 1666280031Sdim const char *format, ...) 1667280031SdimFORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format) 1668280031Sdim#endif // SANITIZER_INTERCEPT_PRINTF_L 1669280031Sdim 1670276789SdimINTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap) 1671276789SdimVSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap) 1672276789Sdim 1673327952Sdim#if SANITIZER_INTERCEPT___PRINTF_CHK 1674327952SdimINTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to, 1675327952Sdim const char *format, va_list ap) 1676327952SdimVSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap) 1677327952Sdim#endif 1678327952Sdim 1679276789SdimINTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap) 1680276789SdimVASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap) 1681276789Sdim 1682276789Sdim#if SANITIZER_INTERCEPT_ISOC99_PRINTF 1683276789SdimINTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap) 1684276789SdimVPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap) 1685276789Sdim 1686276789SdimINTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream, 1687276789Sdim const char *format, va_list ap) 1688276789SdimVPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap) 1689276789Sdim 1690276789SdimINTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format, 1691276789Sdim va_list ap) 1692276789SdimVSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap) 1693276789Sdim 1694276789SdimINTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format, 1695276789Sdim va_list ap) 1696276789SdimVSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format, 1697276789Sdim ap) 1698276789Sdim 1699276789Sdim#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF 1700276789Sdim 1701276789SdimINTERCEPTOR(int, printf, const char *format, ...) 1702276789SdimFORMAT_INTERCEPTOR_IMPL(printf, vprintf, format) 1703276789Sdim 1704276789SdimINTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...) 1705276789SdimFORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format) 1706276789Sdim 1707327952Sdim#if SANITIZER_INTERCEPT___PRINTF_CHK 1708327952SdimINTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size, 1709327952Sdim const char *format, ...) 1710327952SdimFORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format) 1711327952Sdim#endif 1712327952Sdim 1713360784SdimINTERCEPTOR(int, sprintf, char *str, const char *format, ...) 1714360784SdimFORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) 1715276789Sdim 1716327952Sdim#if SANITIZER_INTERCEPT___PRINTF_CHK 1717327952SdimINTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to, 1718360784Sdim const char *format, ...) 1719360784SdimFORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) 1720327952Sdim#endif 1721327952Sdim 1722276789SdimINTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...) 1723276789SdimFORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format) 1724276789Sdim 1725327952Sdim#if SANITIZER_INTERCEPT___PRINTF_CHK 1726327952SdimINTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag, 1727360784Sdim SIZE_T size_to, const char *format, ...) 1728360784SdimFORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) 1729327952Sdim#endif 1730327952Sdim 1731276789SdimINTERCEPTOR(int, asprintf, char **strp, const char *format, ...) 1732276789SdimFORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format) 1733276789Sdim 1734276789Sdim#if SANITIZER_INTERCEPT_ISOC99_PRINTF 1735276789SdimINTERCEPTOR(int, __isoc99_printf, const char *format, ...) 1736276789SdimFORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format) 1737276789Sdim 1738276789SdimINTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format, 1739276789Sdim ...) 1740276789SdimFORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format) 1741276789Sdim 1742276789SdimINTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...) 1743276789SdimFORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format) 1744276789Sdim 1745276789SdimINTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size, 1746276789Sdim const char *format, ...) 1747276789SdimFORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size, 1748276789Sdim format) 1749276789Sdim 1750276789Sdim#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF 1751276789Sdim 1752276789Sdim#endif // SANITIZER_INTERCEPT_PRINTF 1753276789Sdim 1754276789Sdim#if SANITIZER_INTERCEPT_PRINTF 1755276789Sdim#define INIT_PRINTF \ 1756314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(printf); \ 1757314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \ 1758314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \ 1759314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \ 1760314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \ 1761314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \ 1762314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \ 1763314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \ 1764314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \ 1765314564Sdim COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf); 1766276789Sdim#else 1767276789Sdim#define INIT_PRINTF 1768276789Sdim#endif 1769276789Sdim 1770327952Sdim#if SANITIZER_INTERCEPT___PRINTF_CHK 1771327952Sdim#define INIT___PRINTF_CHK \ 1772327952Sdim COMMON_INTERCEPT_FUNCTION(__sprintf_chk); \ 1773327952Sdim COMMON_INTERCEPT_FUNCTION(__snprintf_chk); \ 1774327952Sdim COMMON_INTERCEPT_FUNCTION(__vsprintf_chk); \ 1775327952Sdim COMMON_INTERCEPT_FUNCTION(__vsnprintf_chk); \ 1776327952Sdim COMMON_INTERCEPT_FUNCTION(__fprintf_chk); 1777327952Sdim#else 1778327952Sdim#define INIT___PRINTF_CHK 1779327952Sdim#endif 1780327952Sdim 1781280031Sdim#if SANITIZER_INTERCEPT_PRINTF_L 1782280031Sdim#define INIT_PRINTF_L \ 1783280031Sdim COMMON_INTERCEPT_FUNCTION(snprintf_l); \ 1784280031Sdim COMMON_INTERCEPT_FUNCTION(vsnprintf_l); 1785280031Sdim#else 1786280031Sdim#define INIT_PRINTF_L 1787280031Sdim#endif 1788280031Sdim 1789276789Sdim#if SANITIZER_INTERCEPT_ISOC99_PRINTF 1790276789Sdim#define INIT_ISOC99_PRINTF \ 1791276789Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_printf); \ 1792276789Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf); \ 1793276789Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf); \ 1794276789Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf); \ 1795276789Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf); \ 1796276789Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf); \ 1797276789Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \ 1798276789Sdim COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf); 1799276789Sdim#else 1800276789Sdim#define INIT_ISOC99_PRINTF 1801276789Sdim#endif 1802276789Sdim 1803274201Sdim#if SANITIZER_INTERCEPT_IOCTL 1804274201Sdim#include "sanitizer_common_interceptors_ioctl.inc" 1805341825Sdim#include "sanitizer_interceptors_ioctl_netbsd.inc" 1806280031SdimINTERCEPTOR(int, ioctl, int d, unsigned long request, ...) { 1807288943Sdim // We need a frame pointer, because we call into ioctl_common_[pre|post] which 1808288943Sdim // can trigger a report and we need to be able to unwind through this 1809288943Sdim // function. On Mac in debug mode we might not have a frame pointer, because 1810288943Sdim // ioctl_common_[pre|post] doesn't get inlined here. 1811288943Sdim ENABLE_FRAME_POINTER; 1812288943Sdim 1813274201Sdim void *ctx; 1814280031Sdim va_list ap; 1815280031Sdim va_start(ap, request); 1816280031Sdim void *arg = va_arg(ap, void *); 1817280031Sdim va_end(ap); 1818274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg); 1819274201Sdim 1820274201Sdim CHECK(ioctl_initialized); 1821274201Sdim 1822274201Sdim // Note: TSan does not use common flags, and they are zero-initialized. 1823274201Sdim // This effectively disables ioctl handling in TSan. 1824274201Sdim if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg); 1825274201Sdim 1826280031Sdim // Although request is unsigned long, the rest of the interceptor uses it 1827280031Sdim // as just "unsigned" to save space, because we know that all values fit in 1828280031Sdim // "unsigned" - they are compile-time constants. 1829280031Sdim 1830274201Sdim const ioctl_desc *desc = ioctl_lookup(request); 1831276789Sdim ioctl_desc decoded_desc; 1832276789Sdim if (!desc) { 1833276789Sdim VPrintf(2, "Decoding unknown ioctl 0x%x\n", request); 1834276789Sdim if (!ioctl_decode(request, &decoded_desc)) 1835276789Sdim Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request); 1836276789Sdim else 1837276789Sdim desc = &decoded_desc; 1838276789Sdim } 1839274201Sdim 1840274201Sdim if (desc) ioctl_common_pre(ctx, desc, d, request, arg); 1841274201Sdim int res = REAL(ioctl)(d, request, arg); 1842274201Sdim // FIXME: some ioctls have different return values for success and failure. 1843274201Sdim if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg); 1844274201Sdim return res; 1845274201Sdim} 1846274201Sdim#define INIT_IOCTL \ 1847274201Sdim ioctl_init(); \ 1848274201Sdim COMMON_INTERCEPT_FUNCTION(ioctl); 1849274201Sdim#else 1850274201Sdim#define INIT_IOCTL 1851274201Sdim#endif 1852274201Sdim 1853353358Sdim#if SANITIZER_POSIX 1854353358SdimUNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) { 1855276789Sdim if (pwd) { 1856276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd)); 1857276789Sdim if (pwd->pw_name) 1858353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_name, 1859353358Sdim REAL(strlen)(pwd->pw_name) + 1); 1860276789Sdim if (pwd->pw_passwd) 1861353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_passwd, 1862353358Sdim REAL(strlen)(pwd->pw_passwd) + 1); 1863276789Sdim#if !SANITIZER_ANDROID 1864276789Sdim if (pwd->pw_gecos) 1865353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos, 1866353358Sdim REAL(strlen)(pwd->pw_gecos) + 1); 1867276789Sdim#endif 1868353358Sdim#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD 1869276789Sdim if (pwd->pw_class) 1870353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class, 1871353358Sdim REAL(strlen)(pwd->pw_class) + 1); 1872276789Sdim#endif 1873276789Sdim if (pwd->pw_dir) 1874353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_dir, 1875353358Sdim REAL(strlen)(pwd->pw_dir) + 1); 1876276789Sdim if (pwd->pw_shell) 1877353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_shell, 1878353358Sdim REAL(strlen)(pwd->pw_shell) + 1); 1879276789Sdim } 1880276789Sdim} 1881276789Sdim 1882353358SdimUNUSED static void unpoison_group(void *ctx, __sanitizer_group *grp) { 1883276789Sdim if (grp) { 1884276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp)); 1885276789Sdim if (grp->gr_name) 1886353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_name, 1887353358Sdim REAL(strlen)(grp->gr_name) + 1); 1888276789Sdim if (grp->gr_passwd) 1889353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_passwd, 1890353358Sdim REAL(strlen)(grp->gr_passwd) + 1); 1891276789Sdim char **p = grp->gr_mem; 1892276789Sdim for (; *p; ++p) { 1893353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1); 1894276789Sdim } 1895353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_mem, 1896353358Sdim (p - grp->gr_mem + 1) * sizeof(*p)); 1897276789Sdim } 1898276789Sdim} 1899353358Sdim#endif // SANITIZER_POSIX 1900276789Sdim 1901251034Sed#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS 1902276789SdimINTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) { 1903251034Sed void *ctx; 1904251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name); 1905327952Sdim if (name) 1906327952Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 1907276789Sdim __sanitizer_passwd *res = REAL(getpwnam)(name); 1908353358Sdim unpoison_passwd(ctx, res); 1909245614Sandrew return res; 1910245614Sandrew} 1911276789SdimINTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) { 1912251034Sed void *ctx; 1913251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid); 1914276789Sdim __sanitizer_passwd *res = REAL(getpwuid)(uid); 1915353358Sdim unpoison_passwd(ctx, res); 1916251034Sed return res; 1917251034Sed} 1918276789SdimINTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) { 1919251034Sed void *ctx; 1920251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name); 1921251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 1922276789Sdim __sanitizer_group *res = REAL(getgrnam)(name); 1923353358Sdim unpoison_group(ctx, res); 1924251034Sed return res; 1925251034Sed} 1926276789SdimINTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) { 1927251034Sed void *ctx; 1928251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid); 1929276789Sdim __sanitizer_group *res = REAL(getgrgid)(gid); 1930353358Sdim unpoison_group(ctx, res); 1931251034Sed return res; 1932251034Sed} 1933274201Sdim#define INIT_GETPWNAM_AND_FRIENDS \ 1934274201Sdim COMMON_INTERCEPT_FUNCTION(getpwnam); \ 1935274201Sdim COMMON_INTERCEPT_FUNCTION(getpwuid); \ 1936274201Sdim COMMON_INTERCEPT_FUNCTION(getgrnam); \ 1937274201Sdim COMMON_INTERCEPT_FUNCTION(getgrgid); 1938251034Sed#else 1939251034Sed#define INIT_GETPWNAM_AND_FRIENDS 1940251034Sed#endif 1941245614Sandrew 1942251034Sed#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS 1943276789SdimINTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd, 1944276789Sdim char *buf, SIZE_T buflen, __sanitizer_passwd **result) { 1945251034Sed void *ctx; 1946251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result); 1947251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 1948276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1949276789Sdim // its metadata. See 1950296417Sdim // https://github.com/google/sanitizers/issues/321. 1951251034Sed int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result); 1952353358Sdim if (!res && result) 1953353358Sdim unpoison_passwd(ctx, *result); 1954276789Sdim if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 1955245614Sandrew return res; 1956245614Sandrew} 1957276789SdimINTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf, 1958276789Sdim SIZE_T buflen, __sanitizer_passwd **result) { 1959251034Sed void *ctx; 1960251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result); 1961276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1962276789Sdim // its metadata. See 1963296417Sdim // https://github.com/google/sanitizers/issues/321. 1964251034Sed int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result); 1965353358Sdim if (!res && result) 1966353358Sdim unpoison_passwd(ctx, *result); 1967276789Sdim if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 1968251034Sed return res; 1969251034Sed} 1970276789SdimINTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp, 1971276789Sdim char *buf, SIZE_T buflen, __sanitizer_group **result) { 1972251034Sed void *ctx; 1973251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result); 1974251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 1975276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1976276789Sdim // its metadata. See 1977296417Sdim // https://github.com/google/sanitizers/issues/321. 1978251034Sed int res = REAL(getgrnam_r)(name, grp, buf, buflen, result); 1979353358Sdim if (!res && result) 1980353358Sdim unpoison_group(ctx, *result); 1981276789Sdim if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 1982251034Sed return res; 1983251034Sed} 1984276789SdimINTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf, 1985276789Sdim SIZE_T buflen, __sanitizer_group **result) { 1986251034Sed void *ctx; 1987251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result); 1988276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 1989276789Sdim // its metadata. See 1990296417Sdim // https://github.com/google/sanitizers/issues/321. 1991251034Sed int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result); 1992353358Sdim if (!res && result) 1993353358Sdim unpoison_group(ctx, *result); 1994276789Sdim if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 1995251034Sed return res; 1996251034Sed} 1997274201Sdim#define INIT_GETPWNAM_R_AND_FRIENDS \ 1998274201Sdim COMMON_INTERCEPT_FUNCTION(getpwnam_r); \ 1999274201Sdim COMMON_INTERCEPT_FUNCTION(getpwuid_r); \ 2000274201Sdim COMMON_INTERCEPT_FUNCTION(getgrnam_r); \ 2001274201Sdim COMMON_INTERCEPT_FUNCTION(getgrgid_r); 2002251034Sed#else 2003251034Sed#define INIT_GETPWNAM_R_AND_FRIENDS 2004251034Sed#endif 2005245614Sandrew 2006276789Sdim#if SANITIZER_INTERCEPT_GETPWENT 2007276789SdimINTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) { 2008276789Sdim void *ctx; 2009276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy); 2010276789Sdim __sanitizer_passwd *res = REAL(getpwent)(dummy); 2011353358Sdim unpoison_passwd(ctx, res); 2012276789Sdim return res; 2013276789Sdim} 2014276789SdimINTERCEPTOR(__sanitizer_group *, getgrent, int dummy) { 2015276789Sdim void *ctx; 2016276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy); 2017276789Sdim __sanitizer_group *res = REAL(getgrent)(dummy); 2018353358Sdim unpoison_group(ctx, res); 2019276789Sdim return res; 2020276789Sdim} 2021276789Sdim#define INIT_GETPWENT \ 2022276789Sdim COMMON_INTERCEPT_FUNCTION(getpwent); \ 2023276789Sdim COMMON_INTERCEPT_FUNCTION(getgrent); 2024276789Sdim#else 2025276789Sdim#define INIT_GETPWENT 2026276789Sdim#endif 2027276789Sdim 2028276789Sdim#if SANITIZER_INTERCEPT_FGETPWENT 2029276789SdimINTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) { 2030276789Sdim void *ctx; 2031276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp); 2032276789Sdim __sanitizer_passwd *res = REAL(fgetpwent)(fp); 2033353358Sdim unpoison_passwd(ctx, res); 2034276789Sdim return res; 2035276789Sdim} 2036276789SdimINTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) { 2037276789Sdim void *ctx; 2038276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp); 2039276789Sdim __sanitizer_group *res = REAL(fgetgrent)(fp); 2040353358Sdim unpoison_group(ctx, res); 2041276789Sdim return res; 2042276789Sdim} 2043276789Sdim#define INIT_FGETPWENT \ 2044276789Sdim COMMON_INTERCEPT_FUNCTION(fgetpwent); \ 2045276789Sdim COMMON_INTERCEPT_FUNCTION(fgetgrent); 2046276789Sdim#else 2047276789Sdim#define INIT_FGETPWENT 2048276789Sdim#endif 2049276789Sdim 2050276789Sdim#if SANITIZER_INTERCEPT_GETPWENT_R 2051276789SdimINTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf, 2052276789Sdim SIZE_T buflen, __sanitizer_passwd **pwbufp) { 2053276789Sdim void *ctx; 2054276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp); 2055276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2056276789Sdim // its metadata. See 2057296417Sdim // https://github.com/google/sanitizers/issues/321. 2058276789Sdim int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp); 2059353358Sdim if (!res && pwbufp) 2060353358Sdim unpoison_passwd(ctx, *pwbufp); 2061276789Sdim if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp)); 2062276789Sdim return res; 2063276789Sdim} 2064344779SdimINTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen, 2065344779Sdim __sanitizer_group **pwbufp) { 2066276789Sdim void *ctx; 2067344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp); 2068276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2069276789Sdim // its metadata. See 2070296417Sdim // https://github.com/google/sanitizers/issues/321. 2071344779Sdim int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp); 2072353358Sdim if (!res && pwbufp) 2073353358Sdim unpoison_group(ctx, *pwbufp); 2074276789Sdim if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp)); 2075276789Sdim return res; 2076276789Sdim} 2077344779Sdim#define INIT_GETPWENT_R \ 2078344779Sdim COMMON_INTERCEPT_FUNCTION(getpwent_r); \ 2079344779Sdim COMMON_INTERCEPT_FUNCTION(getgrent_r); 2080344779Sdim#else 2081344779Sdim#define INIT_GETPWENT_R 2082344779Sdim#endif 2083344779Sdim 2084344779Sdim#if SANITIZER_INTERCEPT_FGETPWENT_R 2085344779SdimINTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf, 2086344779Sdim SIZE_T buflen, __sanitizer_passwd **pwbufp) { 2087276789Sdim void *ctx; 2088344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp); 2089276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2090276789Sdim // its metadata. See 2091296417Sdim // https://github.com/google/sanitizers/issues/321. 2092344779Sdim int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp); 2093353358Sdim if (!res && pwbufp) 2094353358Sdim unpoison_passwd(ctx, *pwbufp); 2095276789Sdim if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp)); 2096276789Sdim return res; 2097276789Sdim} 2098344779Sdim#define INIT_FGETPWENT_R \ 2099344779Sdim COMMON_INTERCEPT_FUNCTION(fgetpwent_r); 2100344779Sdim#else 2101344779Sdim#define INIT_FGETPWENT_R 2102344779Sdim#endif 2103344779Sdim 2104344779Sdim#if SANITIZER_INTERCEPT_FGETGRENT_R 2105276789SdimINTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf, 2106276789Sdim SIZE_T buflen, __sanitizer_group **pwbufp) { 2107276789Sdim void *ctx; 2108276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp); 2109276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2110276789Sdim // its metadata. See 2111296417Sdim // https://github.com/google/sanitizers/issues/321. 2112276789Sdim int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp); 2113353358Sdim if (!res && pwbufp) 2114353358Sdim unpoison_group(ctx, *pwbufp); 2115276789Sdim if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp)); 2116276789Sdim return res; 2117276789Sdim} 2118344779Sdim#define INIT_FGETGRENT_R \ 2119276789Sdim COMMON_INTERCEPT_FUNCTION(fgetgrent_r); 2120276789Sdim#else 2121344779Sdim#define INIT_FGETGRENT_R 2122276789Sdim#endif 2123276789Sdim 2124276789Sdim#if SANITIZER_INTERCEPT_SETPWENT 2125276789Sdim// The only thing these interceptors do is disable any nested interceptors. 2126276789Sdim// These functions may open nss modules and call uninstrumented functions from 2127276789Sdim// them, and we don't want things like strlen() to trigger. 2128276789SdimINTERCEPTOR(void, setpwent, int dummy) { 2129276789Sdim void *ctx; 2130276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy); 2131276789Sdim REAL(setpwent)(dummy); 2132276789Sdim} 2133276789SdimINTERCEPTOR(void, endpwent, int dummy) { 2134276789Sdim void *ctx; 2135276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy); 2136276789Sdim REAL(endpwent)(dummy); 2137276789Sdim} 2138276789SdimINTERCEPTOR(void, setgrent, int dummy) { 2139276789Sdim void *ctx; 2140276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy); 2141276789Sdim REAL(setgrent)(dummy); 2142276789Sdim} 2143276789SdimINTERCEPTOR(void, endgrent, int dummy) { 2144276789Sdim void *ctx; 2145276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy); 2146276789Sdim REAL(endgrent)(dummy); 2147276789Sdim} 2148276789Sdim#define INIT_SETPWENT \ 2149276789Sdim COMMON_INTERCEPT_FUNCTION(setpwent); \ 2150276789Sdim COMMON_INTERCEPT_FUNCTION(endpwent); \ 2151276789Sdim COMMON_INTERCEPT_FUNCTION(setgrent); \ 2152276789Sdim COMMON_INTERCEPT_FUNCTION(endgrent); 2153276789Sdim#else 2154276789Sdim#define INIT_SETPWENT 2155276789Sdim#endif 2156276789Sdim 2157251034Sed#if SANITIZER_INTERCEPT_CLOCK_GETTIME 2158251034SedINTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) { 2159251034Sed void *ctx; 2160251034Sed COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp); 2161276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2162276789Sdim // its metadata. See 2163296417Sdim // https://github.com/google/sanitizers/issues/321. 2164251034Sed int res = REAL(clock_getres)(clk_id, tp); 2165251034Sed if (!res && tp) { 2166251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz); 2167251034Sed } 2168245614Sandrew return res; 2169245614Sandrew} 2170251034SedINTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) { 2171251034Sed void *ctx; 2172251034Sed COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp); 2173276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2174276789Sdim // its metadata. See 2175296417Sdim // https://github.com/google/sanitizers/issues/321. 2176251034Sed int res = REAL(clock_gettime)(clk_id, tp); 2177251034Sed if (!res) { 2178251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz); 2179251034Sed } 2180251034Sed return res; 2181251034Sed} 2182327952Sdimnamespace __sanitizer { 2183327952Sdimextern "C" { 2184327952Sdimint real_clock_gettime(u32 clk_id, void *tp) { 2185344779Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 2186344779Sdim return internal_clock_gettime(clk_id, tp); 2187327952Sdim return REAL(clock_gettime)(clk_id, tp); 2188327952Sdim} 2189327952Sdim} // extern "C" 2190327952Sdim} // namespace __sanitizer 2191251034SedINTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) { 2192251034Sed void *ctx; 2193251034Sed COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp); 2194251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz); 2195251034Sed return REAL(clock_settime)(clk_id, tp); 2196251034Sed} 2197274201Sdim#define INIT_CLOCK_GETTIME \ 2198274201Sdim COMMON_INTERCEPT_FUNCTION(clock_getres); \ 2199274201Sdim COMMON_INTERCEPT_FUNCTION(clock_gettime); \ 2200274201Sdim COMMON_INTERCEPT_FUNCTION(clock_settime); 2201251034Sed#else 2202251034Sed#define INIT_CLOCK_GETTIME 2203251034Sed#endif 2204245614Sandrew 2205251034Sed#if SANITIZER_INTERCEPT_GETITIMER 2206251034SedINTERCEPTOR(int, getitimer, int which, void *curr_value) { 2207251034Sed void *ctx; 2208251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value); 2209276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2210276789Sdim // its metadata. See 2211296417Sdim // https://github.com/google/sanitizers/issues/321. 2212251034Sed int res = REAL(getitimer)(which, curr_value); 2213274201Sdim if (!res && curr_value) { 2214251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz); 2215251034Sed } 2216245614Sandrew return res; 2217245614Sandrew} 2218251034SedINTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) { 2219251034Sed void *ctx; 2220251034Sed COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value); 2221341825Sdim if (new_value) { 2222341825Sdim // itimerval can contain padding that may be legitimately uninitialized 2223341825Sdim const struct __sanitizer_itimerval *nv = 2224341825Sdim (const struct __sanitizer_itimerval *)new_value; 2225341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_sec, 2226341825Sdim sizeof(__sanitizer_time_t)); 2227341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_usec, 2228341825Sdim sizeof(__sanitizer_suseconds_t)); 2229341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_sec, 2230341825Sdim sizeof(__sanitizer_time_t)); 2231341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_usec, 2232341825Sdim sizeof(__sanitizer_suseconds_t)); 2233341825Sdim } 2234276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2235276789Sdim // its metadata. See 2236296417Sdim // https://github.com/google/sanitizers/issues/321. 2237251034Sed int res = REAL(setitimer)(which, new_value, old_value); 2238251034Sed if (!res && old_value) { 2239251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz); 2240251034Sed } 2241251034Sed return res; 2242251034Sed} 2243274201Sdim#define INIT_GETITIMER \ 2244274201Sdim COMMON_INTERCEPT_FUNCTION(getitimer); \ 2245274201Sdim COMMON_INTERCEPT_FUNCTION(setitimer); 2246251034Sed#else 2247251034Sed#define INIT_GETITIMER 2248251034Sed#endif 2249245614Sandrew 2250251034Sed#if SANITIZER_INTERCEPT_GLOB 2251274201Sdimstatic void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) { 2252251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob)); 2253251034Sed // +1 for NULL pointer at the end. 2254274201Sdim if (pglob->gl_pathv) 2255274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE( 2256274201Sdim ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv)); 2257251034Sed for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) { 2258251034Sed char *p = pglob->gl_pathv[i]; 2259251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1); 2260251034Sed } 2261251034Sed} 2262251034Sed 2263327952Sdim#if SANITIZER_SOLARIS 2264327952SdimINTERCEPTOR(int, glob, const char *pattern, int flags, 2265327952Sdim int (*errfunc)(const char *epath, int eerrno), 2266327952Sdim __sanitizer_glob_t *pglob) { 2267327952Sdim void *ctx; 2268327952Sdim COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob); 2269327952Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0); 2270327952Sdim int res = REAL(glob)(pattern, flags, errfunc, pglob); 2271327952Sdim if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob); 2272327952Sdim return res; 2273327952Sdim} 2274327952Sdim#else 2275274201Sdimstatic THREADLOCAL __sanitizer_glob_t *pglob_copy; 2276274201Sdim 2277274201Sdimstatic void wrapped_gl_closedir(void *dir) { 2278276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 2279274201Sdim pglob_copy->gl_closedir(dir); 2280274201Sdim} 2281274201Sdim 2282274201Sdimstatic void *wrapped_gl_readdir(void *dir) { 2283276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 2284274201Sdim return pglob_copy->gl_readdir(dir); 2285274201Sdim} 2286274201Sdim 2287274201Sdimstatic void *wrapped_gl_opendir(const char *s) { 2288276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 2289276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1); 2290274201Sdim return pglob_copy->gl_opendir(s); 2291274201Sdim} 2292274201Sdim 2293274201Sdimstatic int wrapped_gl_lstat(const char *s, void *st) { 2294276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(2); 2295276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1); 2296274201Sdim return pglob_copy->gl_lstat(s, st); 2297274201Sdim} 2298274201Sdim 2299274201Sdimstatic int wrapped_gl_stat(const char *s, void *st) { 2300276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(2); 2301276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1); 2302274201Sdim return pglob_copy->gl_stat(s, st); 2303274201Sdim} 2304274201Sdim 2305296417Sdimstatic const __sanitizer_glob_t kGlobCopy = { 2306296417Sdim 0, 0, 0, 2307296417Sdim 0, wrapped_gl_closedir, wrapped_gl_readdir, 2308296417Sdim wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat}; 2309296417Sdim 2310251034SedINTERCEPTOR(int, glob, const char *pattern, int flags, 2311251034Sed int (*errfunc)(const char *epath, int eerrno), 2312274201Sdim __sanitizer_glob_t *pglob) { 2313251034Sed void *ctx; 2314251034Sed COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob); 2315288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0); 2316296417Sdim __sanitizer_glob_t glob_copy; 2317296417Sdim internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy)); 2318274201Sdim if (flags & glob_altdirfunc) { 2319274201Sdim Swap(pglob->gl_closedir, glob_copy.gl_closedir); 2320274201Sdim Swap(pglob->gl_readdir, glob_copy.gl_readdir); 2321274201Sdim Swap(pglob->gl_opendir, glob_copy.gl_opendir); 2322274201Sdim Swap(pglob->gl_lstat, glob_copy.gl_lstat); 2323274201Sdim Swap(pglob->gl_stat, glob_copy.gl_stat); 2324274201Sdim pglob_copy = &glob_copy; 2325274201Sdim } 2326251034Sed int res = REAL(glob)(pattern, flags, errfunc, pglob); 2327274201Sdim if (flags & glob_altdirfunc) { 2328274201Sdim Swap(pglob->gl_closedir, glob_copy.gl_closedir); 2329274201Sdim Swap(pglob->gl_readdir, glob_copy.gl_readdir); 2330274201Sdim Swap(pglob->gl_opendir, glob_copy.gl_opendir); 2331274201Sdim Swap(pglob->gl_lstat, glob_copy.gl_lstat); 2332274201Sdim Swap(pglob->gl_stat, glob_copy.gl_stat); 2333274201Sdim } 2334274201Sdim pglob_copy = 0; 2335274201Sdim if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob); 2336245614Sandrew return res; 2337245614Sandrew} 2338327952Sdim#endif // SANITIZER_SOLARIS 2339327952Sdim#define INIT_GLOB \ 2340327952Sdim COMMON_INTERCEPT_FUNCTION(glob); 2341327952Sdim#else // SANITIZER_INTERCEPT_GLOB 2342327952Sdim#define INIT_GLOB 2343327952Sdim#endif // SANITIZER_INTERCEPT_GLOB 2344245614Sandrew 2345327952Sdim#if SANITIZER_INTERCEPT_GLOB64 2346251034SedINTERCEPTOR(int, glob64, const char *pattern, int flags, 2347251034Sed int (*errfunc)(const char *epath, int eerrno), 2348274201Sdim __sanitizer_glob_t *pglob) { 2349251034Sed void *ctx; 2350251034Sed COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob); 2351288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0); 2352296417Sdim __sanitizer_glob_t glob_copy; 2353296417Sdim internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy)); 2354274201Sdim if (flags & glob_altdirfunc) { 2355274201Sdim Swap(pglob->gl_closedir, glob_copy.gl_closedir); 2356274201Sdim Swap(pglob->gl_readdir, glob_copy.gl_readdir); 2357274201Sdim Swap(pglob->gl_opendir, glob_copy.gl_opendir); 2358274201Sdim Swap(pglob->gl_lstat, glob_copy.gl_lstat); 2359274201Sdim Swap(pglob->gl_stat, glob_copy.gl_stat); 2360274201Sdim pglob_copy = &glob_copy; 2361274201Sdim } 2362251034Sed int res = REAL(glob64)(pattern, flags, errfunc, pglob); 2363274201Sdim if (flags & glob_altdirfunc) { 2364274201Sdim Swap(pglob->gl_closedir, glob_copy.gl_closedir); 2365274201Sdim Swap(pglob->gl_readdir, glob_copy.gl_readdir); 2366274201Sdim Swap(pglob->gl_opendir, glob_copy.gl_opendir); 2367274201Sdim Swap(pglob->gl_lstat, glob_copy.gl_lstat); 2368274201Sdim Swap(pglob->gl_stat, glob_copy.gl_stat); 2369274201Sdim } 2370274201Sdim pglob_copy = 0; 2371274201Sdim if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob); 2372245614Sandrew return res; 2373245614Sandrew} 2374327952Sdim#define INIT_GLOB64 \ 2375274201Sdim COMMON_INTERCEPT_FUNCTION(glob64); 2376327952Sdim#else // SANITIZER_INTERCEPT_GLOB64 2377327952Sdim#define INIT_GLOB64 2378327952Sdim#endif // SANITIZER_INTERCEPT_GLOB64 2379245614Sandrew 2380251034Sed#if SANITIZER_INTERCEPT_WAIT 2381251034Sed// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version 2382251034Sed// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for 2383251034Sed// details. 2384251034SedINTERCEPTOR_WITH_SUFFIX(int, wait, int *status) { 2385251034Sed void *ctx; 2386251034Sed COMMON_INTERCEPTOR_ENTER(ctx, wait, status); 2387276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2388276789Sdim // its metadata. See 2389296417Sdim // https://github.com/google/sanitizers/issues/321. 2390251034Sed int res = REAL(wait)(status); 2391251034Sed if (res != -1 && status) 2392251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); 2393251034Sed return res; 2394251034Sed} 2395276789Sdim// On FreeBSD id_t is always 64-bit wide. 2396276789Sdim#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) 2397276789SdimINTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, long long id, void *infop, 2398276789Sdim int options) { 2399276789Sdim#else 2400251034SedINTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop, 2401274201Sdim int options) { 2402276789Sdim#endif 2403251034Sed void *ctx; 2404251034Sed COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options); 2405276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2406276789Sdim // its metadata. See 2407296417Sdim // https://github.com/google/sanitizers/issues/321. 2408251034Sed int res = REAL(waitid)(idtype, id, infop, options); 2409251034Sed if (res != -1 && infop) 2410251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz); 2411251034Sed return res; 2412251034Sed} 2413251034SedINTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) { 2414251034Sed void *ctx; 2415251034Sed COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options); 2416276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2417276789Sdim // its metadata. See 2418296417Sdim // https://github.com/google/sanitizers/issues/321. 2419251034Sed int res = REAL(waitpid)(pid, status, options); 2420251034Sed if (res != -1 && status) 2421251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); 2422251034Sed return res; 2423251034Sed} 2424251034SedINTERCEPTOR(int, wait3, int *status, int options, void *rusage) { 2425251034Sed void *ctx; 2426251034Sed COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage); 2427276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2428276789Sdim // its metadata. See 2429296417Sdim // https://github.com/google/sanitizers/issues/321. 2430251034Sed int res = REAL(wait3)(status, options, rusage); 2431251034Sed if (res != -1) { 2432274201Sdim if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); 2433274201Sdim if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); 2434251034Sed } 2435251034Sed return res; 2436251034Sed} 2437276789Sdim#if SANITIZER_ANDROID 2438276789SdimINTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) { 2439276789Sdim void *ctx; 2440276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage); 2441276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2442276789Sdim // its metadata. See 2443296417Sdim // https://github.com/google/sanitizers/issues/321. 2444276789Sdim int res = REAL(__wait4)(pid, status, options, rusage); 2445276789Sdim if (res != -1) { 2446276789Sdim if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); 2447276789Sdim if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); 2448276789Sdim } 2449276789Sdim return res; 2450276789Sdim} 2451276789Sdim#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4); 2452276789Sdim#else 2453251034SedINTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) { 2454251034Sed void *ctx; 2455251034Sed COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage); 2456276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2457276789Sdim // its metadata. See 2458296417Sdim // https://github.com/google/sanitizers/issues/321. 2459251034Sed int res = REAL(wait4)(pid, status, options, rusage); 2460251034Sed if (res != -1) { 2461274201Sdim if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); 2462274201Sdim if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); 2463251034Sed } 2464251034Sed return res; 2465251034Sed} 2466276789Sdim#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4); 2467276789Sdim#endif // SANITIZER_ANDROID 2468274201Sdim#define INIT_WAIT \ 2469274201Sdim COMMON_INTERCEPT_FUNCTION(wait); \ 2470274201Sdim COMMON_INTERCEPT_FUNCTION(waitid); \ 2471274201Sdim COMMON_INTERCEPT_FUNCTION(waitpid); \ 2472276789Sdim COMMON_INTERCEPT_FUNCTION(wait3); 2473245614Sandrew#else 2474251034Sed#define INIT_WAIT 2475276789Sdim#define INIT_WAIT4 2476245614Sandrew#endif 2477245614Sandrew 2478251034Sed#if SANITIZER_INTERCEPT_INET 2479251034SedINTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) { 2480251034Sed void *ctx; 2481251034Sed COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size); 2482251034Sed uptr sz = __sanitizer_in_addr_sz(af); 2483251034Sed if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz); 2484251034Sed // FIXME: figure out read size based on the address family. 2485276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2486276789Sdim // its metadata. See 2487296417Sdim // https://github.com/google/sanitizers/issues/321. 2488251034Sed char *res = REAL(inet_ntop)(af, src, dst, size); 2489274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 2490251034Sed return res; 2491251034Sed} 2492251034SedINTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) { 2493251034Sed void *ctx; 2494251034Sed COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst); 2495288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0); 2496251034Sed // FIXME: figure out read size based on the address family. 2497276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2498276789Sdim // its metadata. See 2499296417Sdim // https://github.com/google/sanitizers/issues/321. 2500251034Sed int res = REAL(inet_pton)(af, src, dst); 2501251034Sed if (res == 1) { 2502251034Sed uptr sz = __sanitizer_in_addr_sz(af); 2503251034Sed if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz); 2504251034Sed } 2505251034Sed return res; 2506251034Sed} 2507274201Sdim#define INIT_INET \ 2508274201Sdim COMMON_INTERCEPT_FUNCTION(inet_ntop); \ 2509274201Sdim COMMON_INTERCEPT_FUNCTION(inet_pton); 2510251034Sed#else 2511251034Sed#define INIT_INET 2512251034Sed#endif 2513251034Sed 2514274201Sdim#if SANITIZER_INTERCEPT_INET 2515274201SdimINTERCEPTOR(int, inet_aton, const char *cp, void *dst) { 2516274201Sdim void *ctx; 2517274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst); 2518274201Sdim if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1); 2519276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2520276789Sdim // its metadata. See 2521296417Sdim // https://github.com/google/sanitizers/issues/321. 2522274201Sdim int res = REAL(inet_aton)(cp, dst); 2523274201Sdim if (res != 0) { 2524274201Sdim uptr sz = __sanitizer_in_addr_sz(af_inet); 2525274201Sdim if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz); 2526274201Sdim } 2527274201Sdim return res; 2528274201Sdim} 2529274201Sdim#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton); 2530274201Sdim#else 2531274201Sdim#define INIT_INET_ATON 2532274201Sdim#endif 2533274201Sdim 2534251034Sed#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM 2535251034SedINTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) { 2536251034Sed void *ctx; 2537251034Sed COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param); 2538276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2539276789Sdim // its metadata. See 2540296417Sdim // https://github.com/google/sanitizers/issues/321. 2541251034Sed int res = REAL(pthread_getschedparam)(thread, policy, param); 2542251034Sed if (res == 0) { 2543251034Sed if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy)); 2544251034Sed if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param)); 2545251034Sed } 2546251034Sed return res; 2547251034Sed} 2548274201Sdim#define INIT_PTHREAD_GETSCHEDPARAM \ 2549274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_getschedparam); 2550251034Sed#else 2551251034Sed#define INIT_PTHREAD_GETSCHEDPARAM 2552251034Sed#endif 2553251034Sed 2554251034Sed#if SANITIZER_INTERCEPT_GETADDRINFO 2555251034SedINTERCEPTOR(int, getaddrinfo, char *node, char *service, 2556251034Sed struct __sanitizer_addrinfo *hints, 2557251034Sed struct __sanitizer_addrinfo **out) { 2558251034Sed void *ctx; 2559251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out); 2560251034Sed if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1); 2561251034Sed if (service) 2562251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1); 2563251034Sed if (hints) 2564251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo)); 2565276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2566276789Sdim // its metadata. See 2567296417Sdim // https://github.com/google/sanitizers/issues/321. 2568251034Sed int res = REAL(getaddrinfo)(node, service, hints, out); 2569274201Sdim if (res == 0 && out) { 2570274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out)); 2571251034Sed struct __sanitizer_addrinfo *p = *out; 2572251034Sed while (p) { 2573274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); 2574251034Sed if (p->ai_addr) 2575274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen); 2576251034Sed if (p->ai_canonname) 2577251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname, 2578251034Sed REAL(strlen)(p->ai_canonname) + 1); 2579251034Sed p = p->ai_next; 2580251034Sed } 2581251034Sed } 2582251034Sed return res; 2583251034Sed} 2584274201Sdim#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo); 2585251034Sed#else 2586251034Sed#define INIT_GETADDRINFO 2587251034Sed#endif 2588251034Sed 2589274201Sdim#if SANITIZER_INTERCEPT_GETNAMEINFO 2590274201SdimINTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host, 2591274201Sdim unsigned hostlen, char *serv, unsigned servlen, int flags) { 2592274201Sdim void *ctx; 2593274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen, 2594274201Sdim serv, servlen, flags); 2595274201Sdim // FIXME: consider adding READ_RANGE(sockaddr, salen) 2596274201Sdim // There is padding in in_addr that may make this too noisy 2597276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2598276789Sdim // its metadata. See 2599296417Sdim // https://github.com/google/sanitizers/issues/321. 2600274201Sdim int res = 2601274201Sdim REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags); 2602274201Sdim if (res == 0) { 2603274201Sdim if (host && hostlen) 2604274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1); 2605274201Sdim if (serv && servlen) 2606274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1); 2607274201Sdim } 2608274201Sdim return res; 2609274201Sdim} 2610274201Sdim#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo); 2611274201Sdim#else 2612274201Sdim#define INIT_GETNAMEINFO 2613274201Sdim#endif 2614274201Sdim 2615251034Sed#if SANITIZER_INTERCEPT_GETSOCKNAME 2616251034SedINTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) { 2617251034Sed void *ctx; 2618251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen); 2619251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen)); 2620251034Sed int addrlen_in = *addrlen; 2621276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2622276789Sdim // its metadata. See 2623296417Sdim // https://github.com/google/sanitizers/issues/321. 2624251034Sed int res = REAL(getsockname)(sock_fd, addr, addrlen); 2625251034Sed if (res == 0) { 2626251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen)); 2627251034Sed } 2628251034Sed return res; 2629251034Sed} 2630274201Sdim#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname); 2631251034Sed#else 2632251034Sed#define INIT_GETSOCKNAME 2633251034Sed#endif 2634251034Sed 2635251034Sed#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R 2636251034Sedstatic void write_hostent(void *ctx, struct __sanitizer_hostent *h) { 2637251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent)); 2638251034Sed if (h->h_name) 2639251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1); 2640251034Sed char **p = h->h_aliases; 2641251034Sed while (*p) { 2642251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1); 2643251034Sed ++p; 2644251034Sed } 2645251034Sed COMMON_INTERCEPTOR_WRITE_RANGE( 2646251034Sed ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases)); 2647251034Sed p = h->h_addr_list; 2648251034Sed while (*p) { 2649251034Sed COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length); 2650251034Sed ++p; 2651251034Sed } 2652251034Sed COMMON_INTERCEPTOR_WRITE_RANGE( 2653251034Sed ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list)); 2654251034Sed} 2655251034Sed#endif 2656251034Sed 2657251034Sed#if SANITIZER_INTERCEPT_GETHOSTBYNAME 2658251034SedINTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) { 2659251034Sed void *ctx; 2660251034Sed COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name); 2661251034Sed struct __sanitizer_hostent *res = REAL(gethostbyname)(name); 2662251034Sed if (res) write_hostent(ctx, res); 2663251034Sed return res; 2664251034Sed} 2665251034Sed 2666251034SedINTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len, 2667251034Sed int type) { 2668251034Sed void *ctx; 2669251034Sed COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type); 2670251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len); 2671251034Sed struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type); 2672251034Sed if (res) write_hostent(ctx, res); 2673251034Sed return res; 2674251034Sed} 2675251034Sed 2676274201SdimINTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) { 2677251034Sed void *ctx; 2678274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake); 2679274201Sdim struct __sanitizer_hostent *res = REAL(gethostent)(fake); 2680251034Sed if (res) write_hostent(ctx, res); 2681251034Sed return res; 2682251034Sed} 2683327952Sdim#define INIT_GETHOSTBYNAME \ 2684327952Sdim COMMON_INTERCEPT_FUNCTION(gethostent); \ 2685327952Sdim COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \ 2686327952Sdim COMMON_INTERCEPT_FUNCTION(gethostbyname); 2687327952Sdim#else 2688327952Sdim#define INIT_GETHOSTBYNAME 2689327952Sdim#endif // SANITIZER_INTERCEPT_GETHOSTBYNAME 2690251034Sed 2691327952Sdim#if SANITIZER_INTERCEPT_GETHOSTBYNAME2 2692251034SedINTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) { 2693251034Sed void *ctx; 2694251034Sed COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af); 2695251034Sed struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af); 2696251034Sed if (res) write_hostent(ctx, res); 2697251034Sed return res; 2698251034Sed} 2699327952Sdim#define INIT_GETHOSTBYNAME2 COMMON_INTERCEPT_FUNCTION(gethostbyname2); 2700251034Sed#else 2701327952Sdim#define INIT_GETHOSTBYNAME2 2702327952Sdim#endif // SANITIZER_INTERCEPT_GETHOSTBYNAME2 2703251034Sed 2704251034Sed#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R 2705276789SdimINTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret, 2706276789Sdim char *buf, SIZE_T buflen, __sanitizer_hostent **result, 2707276789Sdim int *h_errnop) { 2708276789Sdim void *ctx; 2709276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result, 2710276789Sdim h_errnop); 2711276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2712276789Sdim // its metadata. See 2713296417Sdim // https://github.com/google/sanitizers/issues/321. 2714276789Sdim int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop); 2715276789Sdim if (result) { 2716276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 2717276789Sdim if (res == 0 && *result) write_hostent(ctx, *result); 2718276789Sdim } 2719276789Sdim if (h_errnop) 2720276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop)); 2721276789Sdim return res; 2722276789Sdim} 2723276789Sdim#define INIT_GETHOSTBYNAME_R COMMON_INTERCEPT_FUNCTION(gethostbyname_r); 2724276789Sdim#else 2725276789Sdim#define INIT_GETHOSTBYNAME_R 2726276789Sdim#endif 2727276789Sdim 2728276789Sdim#if SANITIZER_INTERCEPT_GETHOSTENT_R 2729251034SedINTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf, 2730251034Sed SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) { 2731251034Sed void *ctx; 2732251034Sed COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result, 2733251034Sed h_errnop); 2734276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2735276789Sdim // its metadata. See 2736296417Sdim // https://github.com/google/sanitizers/issues/321. 2737251034Sed int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop); 2738276789Sdim if (result) { 2739276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 2740276789Sdim if (res == 0 && *result) write_hostent(ctx, *result); 2741251034Sed } 2742276789Sdim if (h_errnop) 2743276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop)); 2744251034Sed return res; 2745251034Sed} 2746276789Sdim#define INIT_GETHOSTENT_R \ 2747276789Sdim COMMON_INTERCEPT_FUNCTION(gethostent_r); 2748276789Sdim#else 2749276789Sdim#define INIT_GETHOSTENT_R 2750276789Sdim#endif 2751251034Sed 2752276789Sdim#if SANITIZER_INTERCEPT_GETHOSTBYADDR_R 2753251034SedINTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type, 2754251034Sed struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen, 2755251034Sed __sanitizer_hostent **result, int *h_errnop) { 2756251034Sed void *ctx; 2757251034Sed COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf, 2758251034Sed buflen, result, h_errnop); 2759251034Sed COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len); 2760276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2761276789Sdim // its metadata. See 2762296417Sdim // https://github.com/google/sanitizers/issues/321. 2763251034Sed int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result, 2764251034Sed h_errnop); 2765276789Sdim if (result) { 2766276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 2767276789Sdim if (res == 0 && *result) write_hostent(ctx, *result); 2768251034Sed } 2769276789Sdim if (h_errnop) 2770276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop)); 2771251034Sed return res; 2772251034Sed} 2773276789Sdim#define INIT_GETHOSTBYADDR_R \ 2774276789Sdim COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r); 2775276789Sdim#else 2776276789Sdim#define INIT_GETHOSTBYADDR_R 2777276789Sdim#endif 2778251034Sed 2779276789Sdim#if SANITIZER_INTERCEPT_GETHOSTBYNAME2_R 2780251034SedINTERCEPTOR(int, gethostbyname2_r, char *name, int af, 2781251034Sed struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen, 2782251034Sed __sanitizer_hostent **result, int *h_errnop) { 2783251034Sed void *ctx; 2784251034Sed COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen, 2785251034Sed result, h_errnop); 2786276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2787276789Sdim // its metadata. See 2788296417Sdim // https://github.com/google/sanitizers/issues/321. 2789251034Sed int res = 2790251034Sed REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop); 2791276789Sdim if (result) { 2792276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 2793276789Sdim if (res == 0 && *result) write_hostent(ctx, *result); 2794251034Sed } 2795276789Sdim if (h_errnop) 2796276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop)); 2797251034Sed return res; 2798251034Sed} 2799276789Sdim#define INIT_GETHOSTBYNAME2_R \ 2800274201Sdim COMMON_INTERCEPT_FUNCTION(gethostbyname2_r); 2801251034Sed#else 2802276789Sdim#define INIT_GETHOSTBYNAME2_R 2803251034Sed#endif 2804251034Sed 2805251034Sed#if SANITIZER_INTERCEPT_GETSOCKOPT 2806251034SedINTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval, 2807251034Sed int *optlen) { 2808251034Sed void *ctx; 2809251034Sed COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval, 2810251034Sed optlen); 2811251034Sed if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen)); 2812276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2813276789Sdim // its metadata. See 2814296417Sdim // https://github.com/google/sanitizers/issues/321. 2815251034Sed int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen); 2816251034Sed if (res == 0) 2817251034Sed if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen); 2818251034Sed return res; 2819251034Sed} 2820274201Sdim#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt); 2821251034Sed#else 2822251034Sed#define INIT_GETSOCKOPT 2823251034Sed#endif 2824251034Sed 2825274201Sdim#if SANITIZER_INTERCEPT_ACCEPT 2826274201SdimINTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) { 2827274201Sdim void *ctx; 2828274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen); 2829276789Sdim unsigned addrlen0 = 0; 2830274201Sdim if (addrlen) { 2831274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen)); 2832274201Sdim addrlen0 = *addrlen; 2833274201Sdim } 2834274201Sdim int fd2 = REAL(accept)(fd, addr, addrlen); 2835274201Sdim if (fd2 >= 0) { 2836274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); 2837274201Sdim if (addr && addrlen) 2838274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0)); 2839274201Sdim } 2840274201Sdim return fd2; 2841274201Sdim} 2842274201Sdim#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept); 2843274201Sdim#else 2844274201Sdim#define INIT_ACCEPT 2845274201Sdim#endif 2846274201Sdim 2847274201Sdim#if SANITIZER_INTERCEPT_ACCEPT4 2848274201SdimINTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) { 2849274201Sdim void *ctx; 2850274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f); 2851276789Sdim unsigned addrlen0 = 0; 2852274201Sdim if (addrlen) { 2853274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen)); 2854274201Sdim addrlen0 = *addrlen; 2855274201Sdim } 2856276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2857276789Sdim // its metadata. See 2858296417Sdim // https://github.com/google/sanitizers/issues/321. 2859274201Sdim int fd2 = REAL(accept4)(fd, addr, addrlen, f); 2860274201Sdim if (fd2 >= 0) { 2861274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); 2862274201Sdim if (addr && addrlen) 2863274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0)); 2864274201Sdim } 2865274201Sdim return fd2; 2866274201Sdim} 2867274201Sdim#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4); 2868274201Sdim#else 2869274201Sdim#define INIT_ACCEPT4 2870274201Sdim#endif 2871274201Sdim 2872341825Sdim#if SANITIZER_INTERCEPT_PACCEPT 2873341825SdimINTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen, 2874341825Sdim __sanitizer_sigset_t *set, int f) { 2875341825Sdim void *ctx; 2876341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, paccept, fd, addr, addrlen, set, f); 2877341825Sdim unsigned addrlen0 = 0; 2878341825Sdim if (addrlen) { 2879341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen)); 2880341825Sdim addrlen0 = *addrlen; 2881341825Sdim } 2882341825Sdim if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set)); 2883341825Sdim int fd2 = REAL(paccept)(fd, addr, addrlen, set, f); 2884341825Sdim if (fd2 >= 0) { 2885341825Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); 2886341825Sdim if (addr && addrlen) 2887341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0)); 2888341825Sdim } 2889341825Sdim return fd2; 2890341825Sdim} 2891341825Sdim#define INIT_PACCEPT COMMON_INTERCEPT_FUNCTION(paccept); 2892341825Sdim#else 2893341825Sdim#define INIT_PACCEPT 2894341825Sdim#endif 2895341825Sdim 2896274201Sdim#if SANITIZER_INTERCEPT_MODF 2897274201SdimINTERCEPTOR(double, modf, double x, double *iptr) { 2898274201Sdim void *ctx; 2899274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr); 2900276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2901276789Sdim // its metadata. See 2902296417Sdim // https://github.com/google/sanitizers/issues/321. 2903274201Sdim double res = REAL(modf)(x, iptr); 2904274201Sdim if (iptr) { 2905274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr)); 2906274201Sdim } 2907274201Sdim return res; 2908274201Sdim} 2909274201SdimINTERCEPTOR(float, modff, float x, float *iptr) { 2910274201Sdim void *ctx; 2911274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr); 2912276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2913276789Sdim // its metadata. See 2914296417Sdim // https://github.com/google/sanitizers/issues/321. 2915274201Sdim float res = REAL(modff)(x, iptr); 2916274201Sdim if (iptr) { 2917274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr)); 2918274201Sdim } 2919274201Sdim return res; 2920274201Sdim} 2921274201SdimINTERCEPTOR(long double, modfl, long double x, long double *iptr) { 2922274201Sdim void *ctx; 2923274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr); 2924276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2925276789Sdim // its metadata. See 2926296417Sdim // https://github.com/google/sanitizers/issues/321. 2927274201Sdim long double res = REAL(modfl)(x, iptr); 2928274201Sdim if (iptr) { 2929274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr)); 2930274201Sdim } 2931274201Sdim return res; 2932274201Sdim} 2933274201Sdim#define INIT_MODF \ 2934274201Sdim COMMON_INTERCEPT_FUNCTION(modf); \ 2935274201Sdim COMMON_INTERCEPT_FUNCTION(modff); \ 2936309124Sdim COMMON_INTERCEPT_FUNCTION_LDBL(modfl); 2937274201Sdim#else 2938274201Sdim#define INIT_MODF 2939274201Sdim#endif 2940274201Sdim 2941341825Sdim#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG 2942274201Sdimstatic void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg, 2943274201Sdim SSIZE_T maxlen) { 2944274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg)); 2945274201Sdim if (msg->msg_name && msg->msg_namelen) 2946274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen); 2947274201Sdim if (msg->msg_iov && msg->msg_iovlen) 2948274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov, 2949274201Sdim sizeof(*msg->msg_iov) * msg->msg_iovlen); 2950274201Sdim write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen); 2951274201Sdim if (msg->msg_control && msg->msg_controllen) 2952274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen); 2953274201Sdim} 2954341825Sdim#endif 2955274201Sdim 2956341825Sdim#if SANITIZER_INTERCEPT_RECVMSG 2957274201SdimINTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg, 2958274201Sdim int flags) { 2959274201Sdim void *ctx; 2960274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags); 2961276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 2962276789Sdim // its metadata. See 2963296417Sdim // https://github.com/google/sanitizers/issues/321. 2964274201Sdim SSIZE_T res = REAL(recvmsg)(fd, msg, flags); 2965274201Sdim if (res >= 0) { 2966274201Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 2967276789Sdim if (msg) { 2968276789Sdim write_msghdr(ctx, msg, res); 2969276789Sdim COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg); 2970276789Sdim } 2971274201Sdim } 2972274201Sdim return res; 2973274201Sdim} 2974274201Sdim#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg); 2975274201Sdim#else 2976274201Sdim#define INIT_RECVMSG 2977274201Sdim#endif 2978274201Sdim 2979341825Sdim#if SANITIZER_INTERCEPT_RECVMMSG 2980341825SdimINTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec, 2981341825Sdim unsigned int vlen, int flags, void *timeout) { 2982341825Sdim void *ctx; 2983341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout); 2984341825Sdim if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz); 2985341825Sdim int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout); 2986341825Sdim if (res >= 0) { 2987341825Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 2988341825Sdim for (int i = 0; i < res; ++i) { 2989341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len, 2990341825Sdim sizeof(msgvec[i].msg_len)); 2991341825Sdim write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len); 2992341825Sdim COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr); 2993341825Sdim } 2994341825Sdim } 2995341825Sdim return res; 2996341825Sdim} 2997341825Sdim#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg); 2998341825Sdim#else 2999341825Sdim#define INIT_RECVMMSG 3000341825Sdim#endif 3001341825Sdim 3002341825Sdim#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG 3003309124Sdimstatic void read_msghdr_control(void *ctx, void *control, uptr controllen) { 3004309124Sdim const unsigned kCmsgDataOffset = 3005309124Sdim RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr)); 3006309124Sdim 3007309124Sdim char *p = (char *)control; 3008309124Sdim char *const control_end = p + controllen; 3009309124Sdim while (true) { 3010309124Sdim if (p + sizeof(__sanitizer_cmsghdr) > control_end) break; 3011309124Sdim __sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p; 3012309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len)); 3013309124Sdim 3014309124Sdim if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break; 3015309124Sdim 3016309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level, 3017309124Sdim sizeof(cmsg->cmsg_level)); 3018309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type, 3019309124Sdim sizeof(cmsg->cmsg_type)); 3020309124Sdim 3021309124Sdim if (cmsg->cmsg_len > kCmsgDataOffset) { 3022309124Sdim char *data = p + kCmsgDataOffset; 3023309124Sdim unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset; 3024309124Sdim if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len); 3025309124Sdim } 3026309124Sdim 3027309124Sdim p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr)); 3028309124Sdim } 3029309124Sdim} 3030309124Sdim 3031309124Sdimstatic void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg, 3032309124Sdim SSIZE_T maxlen) { 3033309124Sdim#define R(f) \ 3034309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f)) 3035309124Sdim R(name); 3036309124Sdim R(namelen); 3037309124Sdim R(iov); 3038309124Sdim R(iovlen); 3039309124Sdim R(control); 3040309124Sdim R(controllen); 3041309124Sdim R(flags); 3042309124Sdim#undef R 3043309124Sdim if (msg->msg_name && msg->msg_namelen) 3044309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen); 3045309124Sdim if (msg->msg_iov && msg->msg_iovlen) 3046309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov, 3047309124Sdim sizeof(*msg->msg_iov) * msg->msg_iovlen); 3048309124Sdim read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen); 3049309124Sdim if (msg->msg_control && msg->msg_controllen) 3050309124Sdim read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen); 3051309124Sdim} 3052341825Sdim#endif 3053309124Sdim 3054341825Sdim#if SANITIZER_INTERCEPT_SENDMSG 3055309124SdimINTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg, 3056309124Sdim int flags) { 3057309124Sdim void *ctx; 3058309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags); 3059309124Sdim if (fd >= 0) { 3060309124Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 3061309124Sdim COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 3062309124Sdim } 3063309124Sdim SSIZE_T res = REAL(sendmsg)(fd, msg, flags); 3064309124Sdim if (common_flags()->intercept_send && res >= 0 && msg) 3065309124Sdim read_msghdr(ctx, msg, res); 3066309124Sdim return res; 3067309124Sdim} 3068309124Sdim#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg); 3069309124Sdim#else 3070309124Sdim#define INIT_SENDMSG 3071309124Sdim#endif 3072309124Sdim 3073341825Sdim#if SANITIZER_INTERCEPT_SENDMMSG 3074341825SdimINTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec, 3075341825Sdim unsigned vlen, int flags) { 3076341825Sdim void *ctx; 3077341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags); 3078341825Sdim if (fd >= 0) { 3079341825Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 3080341825Sdim COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 3081341825Sdim } 3082341825Sdim int res = REAL(sendmmsg)(fd, msgvec, vlen, flags); 3083360784Sdim if (res >= 0 && msgvec) { 3084341825Sdim for (int i = 0; i < res; ++i) { 3085341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len, 3086341825Sdim sizeof(msgvec[i].msg_len)); 3087341825Sdim if (common_flags()->intercept_send) 3088341825Sdim read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len); 3089341825Sdim } 3090360784Sdim } 3091341825Sdim return res; 3092341825Sdim} 3093341825Sdim#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg); 3094341825Sdim#else 3095341825Sdim#define INIT_SENDMMSG 3096341825Sdim#endif 3097341825Sdim 3098274201Sdim#if SANITIZER_INTERCEPT_GETPEERNAME 3099274201SdimINTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) { 3100274201Sdim void *ctx; 3101274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen); 3102274201Sdim unsigned addr_sz; 3103274201Sdim if (addrlen) addr_sz = *addrlen; 3104276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3105276789Sdim // its metadata. See 3106296417Sdim // https://github.com/google/sanitizers/issues/321. 3107274201Sdim int res = REAL(getpeername)(sockfd, addr, addrlen); 3108274201Sdim if (!res && addr && addrlen) 3109274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen)); 3110274201Sdim return res; 3111274201Sdim} 3112274201Sdim#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername); 3113274201Sdim#else 3114274201Sdim#define INIT_GETPEERNAME 3115274201Sdim#endif 3116274201Sdim 3117274201Sdim#if SANITIZER_INTERCEPT_SYSINFO 3118274201SdimINTERCEPTOR(int, sysinfo, void *info) { 3119274201Sdim void *ctx; 3120276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3121276789Sdim // its metadata. See 3122296417Sdim // https://github.com/google/sanitizers/issues/321. 3123274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info); 3124274201Sdim int res = REAL(sysinfo)(info); 3125274201Sdim if (!res && info) 3126274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz); 3127274201Sdim return res; 3128274201Sdim} 3129274201Sdim#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo); 3130274201Sdim#else 3131274201Sdim#define INIT_SYSINFO 3132274201Sdim#endif 3133274201Sdim 3134274201Sdim#if SANITIZER_INTERCEPT_READDIR 3135280031SdimINTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) { 3136280031Sdim void *ctx; 3137280031Sdim COMMON_INTERCEPTOR_ENTER(ctx, opendir, path); 3138280031Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 3139280031Sdim __sanitizer_dirent *res = REAL(opendir)(path); 3140296417Sdim if (res) 3141280031Sdim COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path); 3142280031Sdim return res; 3143280031Sdim} 3144280031Sdim 3145274201SdimINTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) { 3146274201Sdim void *ctx; 3147274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp); 3148276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3149276789Sdim // its metadata. See 3150296417Sdim // https://github.com/google/sanitizers/issues/321. 3151274201Sdim __sanitizer_dirent *res = REAL(readdir)(dirp); 3152274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen); 3153274201Sdim return res; 3154274201Sdim} 3155274201Sdim 3156274201SdimINTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry, 3157274201Sdim __sanitizer_dirent **result) { 3158274201Sdim void *ctx; 3159274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result); 3160276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3161276789Sdim // its metadata. See 3162296417Sdim // https://github.com/google/sanitizers/issues/321. 3163274201Sdim int res = REAL(readdir_r)(dirp, entry, result); 3164274201Sdim if (!res) { 3165274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 3166274201Sdim if (*result) 3167274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen); 3168274201Sdim } 3169274201Sdim return res; 3170274201Sdim} 3171274201Sdim 3172274201Sdim#define INIT_READDIR \ 3173280031Sdim COMMON_INTERCEPT_FUNCTION(opendir); \ 3174274201Sdim COMMON_INTERCEPT_FUNCTION(readdir); \ 3175274201Sdim COMMON_INTERCEPT_FUNCTION(readdir_r); 3176274201Sdim#else 3177274201Sdim#define INIT_READDIR 3178274201Sdim#endif 3179274201Sdim 3180274201Sdim#if SANITIZER_INTERCEPT_READDIR64 3181274201SdimINTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) { 3182274201Sdim void *ctx; 3183274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp); 3184276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3185276789Sdim // its metadata. See 3186296417Sdim // https://github.com/google/sanitizers/issues/321. 3187274201Sdim __sanitizer_dirent64 *res = REAL(readdir64)(dirp); 3188274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen); 3189274201Sdim return res; 3190274201Sdim} 3191274201Sdim 3192274201SdimINTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry, 3193274201Sdim __sanitizer_dirent64 **result) { 3194274201Sdim void *ctx; 3195274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result); 3196276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3197276789Sdim // its metadata. See 3198296417Sdim // https://github.com/google/sanitizers/issues/321. 3199274201Sdim int res = REAL(readdir64_r)(dirp, entry, result); 3200274201Sdim if (!res) { 3201274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 3202274201Sdim if (*result) 3203274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen); 3204274201Sdim } 3205274201Sdim return res; 3206274201Sdim} 3207274201Sdim#define INIT_READDIR64 \ 3208274201Sdim COMMON_INTERCEPT_FUNCTION(readdir64); \ 3209274201Sdim COMMON_INTERCEPT_FUNCTION(readdir64_r); 3210274201Sdim#else 3211274201Sdim#define INIT_READDIR64 3212274201Sdim#endif 3213274201Sdim 3214274201Sdim#if SANITIZER_INTERCEPT_PTRACE 3215274201SdimINTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { 3216274201Sdim void *ctx; 3217274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data); 3218296417Sdim __sanitizer_iovec local_iovec; 3219274201Sdim 3220274201Sdim if (data) { 3221360784Sdim if (request == ptrace_setregs) { 3222274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz); 3223360784Sdim } else if (request == ptrace_setfpregs) { 3224274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz); 3225360784Sdim } else if (request == ptrace_setfpxregs) { 3226274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz); 3227360784Sdim } else if (request == ptrace_setvfpregs) { 3228296417Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz); 3229360784Sdim } else if (request == ptrace_setsiginfo) { 3230274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz); 3231360784Sdim 3232296417Sdim // Some kernel might zero the iovec::iov_base in case of invalid 3233296417Sdim // write access. In this case copy the invalid address for further 3234296417Sdim // inspection. 3235360784Sdim } else if (request == ptrace_setregset || request == ptrace_getregset) { 3236296417Sdim __sanitizer_iovec *iovec = (__sanitizer_iovec*)data; 3237296417Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec)); 3238296417Sdim local_iovec = *iovec; 3239296417Sdim if (request == ptrace_setregset) 3240296417Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len); 3241274201Sdim } 3242274201Sdim } 3243274201Sdim 3244276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3245276789Sdim // its metadata. See 3246296417Sdim // https://github.com/google/sanitizers/issues/321. 3247274201Sdim uptr res = REAL(ptrace)(request, pid, addr, data); 3248274201Sdim 3249274201Sdim if (!res && data) { 3250276789Sdim // Note that PEEK* requests assign different meaning to the return value. 3251274201Sdim // This function does not handle them (nor does it need to). 3252360784Sdim if (request == ptrace_getregs) { 3253274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz); 3254360784Sdim } else if (request == ptrace_getfpregs) { 3255274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz); 3256360784Sdim } else if (request == ptrace_getfpxregs) { 3257274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz); 3258360784Sdim } else if (request == ptrace_getvfpregs) { 3259296417Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz); 3260360784Sdim } else if (request == ptrace_getsiginfo) { 3261274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz); 3262360784Sdim } else if (request == ptrace_geteventmsg) { 3263276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long)); 3264360784Sdim } else if (request == ptrace_getregset) { 3265296417Sdim __sanitizer_iovec *iovec = (__sanitizer_iovec*)data; 3266296417Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec)); 3267296417Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base, 3268296417Sdim local_iovec.iov_len); 3269274201Sdim } 3270274201Sdim } 3271274201Sdim return res; 3272274201Sdim} 3273274201Sdim 3274274201Sdim#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace); 3275274201Sdim#else 3276274201Sdim#define INIT_PTRACE 3277274201Sdim#endif 3278274201Sdim 3279274201Sdim#if SANITIZER_INTERCEPT_SETLOCALE 3280341825Sdimstatic void unpoison_ctype_arrays(void *ctx) { 3281341825Sdim#if SANITIZER_NETBSD 3282341825Sdim // These arrays contain 256 regular elements in unsigned char range + 1 EOF 3283341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _ctype_tab_, 257 * sizeof(short)); 3284341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _toupper_tab_, 257 * sizeof(short)); 3285341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _tolower_tab_, 257 * sizeof(short)); 3286341825Sdim#endif 3287341825Sdim} 3288341825Sdim 3289274201SdimINTERCEPTOR(char *, setlocale, int category, char *locale) { 3290274201Sdim void *ctx; 3291274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale); 3292274201Sdim if (locale) 3293274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1); 3294274201Sdim char *res = REAL(setlocale)(category, locale); 3295341825Sdim if (res) { 3296341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 3297341825Sdim unpoison_ctype_arrays(ctx); 3298341825Sdim } 3299274201Sdim return res; 3300274201Sdim} 3301274201Sdim 3302274201Sdim#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale); 3303274201Sdim#else 3304274201Sdim#define INIT_SETLOCALE 3305274201Sdim#endif 3306274201Sdim 3307274201Sdim#if SANITIZER_INTERCEPT_GETCWD 3308274201SdimINTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) { 3309274201Sdim void *ctx; 3310274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size); 3311276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3312276789Sdim // its metadata. See 3313296417Sdim // https://github.com/google/sanitizers/issues/321. 3314274201Sdim char *res = REAL(getcwd)(buf, size); 3315274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 3316274201Sdim return res; 3317274201Sdim} 3318274201Sdim#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd); 3319274201Sdim#else 3320274201Sdim#define INIT_GETCWD 3321274201Sdim#endif 3322274201Sdim 3323274201Sdim#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME 3324274201SdimINTERCEPTOR(char *, get_current_dir_name, int fake) { 3325274201Sdim void *ctx; 3326274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake); 3327276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3328276789Sdim // its metadata. See 3329296417Sdim // https://github.com/google/sanitizers/issues/321. 3330274201Sdim char *res = REAL(get_current_dir_name)(fake); 3331274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 3332274201Sdim return res; 3333274201Sdim} 3334274201Sdim 3335274201Sdim#define INIT_GET_CURRENT_DIR_NAME \ 3336274201Sdim COMMON_INTERCEPT_FUNCTION(get_current_dir_name); 3337274201Sdim#else 3338274201Sdim#define INIT_GET_CURRENT_DIR_NAME 3339274201Sdim#endif 3340274201Sdim 3341288943SdimUNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 3342288943Sdim CHECK(endptr); 3343288943Sdim if (nptr == *endptr) { 3344288943Sdim // No digits were found at strtol call, we need to find out the last 3345288943Sdim // symbol accessed by strtoll on our own. 3346288943Sdim // We get this symbol by skipping leading blanks and optional +/- sign. 3347288943Sdim while (IsSpace(*nptr)) nptr++; 3348288943Sdim if (*nptr == '+' || *nptr == '-') nptr++; 3349288943Sdim *endptr = const_cast<char *>(nptr); 3350288943Sdim } 3351288943Sdim CHECK(*endptr >= nptr); 3352288943Sdim} 3353288943Sdim 3354288943SdimUNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr, 3355288943Sdim char **endptr, char *real_endptr, int base) { 3356296417Sdim if (endptr) { 3357288943Sdim *endptr = real_endptr; 3358288943Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr)); 3359288943Sdim } 3360288943Sdim // If base has unsupported value, strtol can exit with EINVAL 3361288943Sdim // without reading any characters. So do additional checks only 3362288943Sdim // if base is valid. 3363288943Sdim bool is_valid_base = (base == 0) || (2 <= base && base <= 36); 3364288943Sdim if (is_valid_base) { 3365288943Sdim FixRealStrtolEndptr(nptr, &real_endptr); 3366288943Sdim } 3367288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ? 3368288943Sdim (real_endptr - nptr) + 1 : 0); 3369288943Sdim} 3370288943Sdim 3371288943Sdim 3372274201Sdim#if SANITIZER_INTERCEPT_STRTOIMAX 3373274201SdimINTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) { 3374274201Sdim void *ctx; 3375274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base); 3376276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3377276789Sdim // its metadata. See 3378296417Sdim // https://github.com/google/sanitizers/issues/321. 3379288943Sdim char *real_endptr; 3380288943Sdim INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base); 3381288943Sdim StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 3382274201Sdim return res; 3383274201Sdim} 3384274201Sdim 3385344779SdimINTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) { 3386274201Sdim void *ctx; 3387274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base); 3388276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3389276789Sdim // its metadata. See 3390296417Sdim // https://github.com/google/sanitizers/issues/321. 3391288943Sdim char *real_endptr; 3392344779Sdim UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base); 3393288943Sdim StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 3394274201Sdim return res; 3395274201Sdim} 3396274201Sdim 3397274201Sdim#define INIT_STRTOIMAX \ 3398274201Sdim COMMON_INTERCEPT_FUNCTION(strtoimax); \ 3399274201Sdim COMMON_INTERCEPT_FUNCTION(strtoumax); 3400274201Sdim#else 3401274201Sdim#define INIT_STRTOIMAX 3402274201Sdim#endif 3403274201Sdim 3404274201Sdim#if SANITIZER_INTERCEPT_MBSTOWCS 3405274201SdimINTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) { 3406274201Sdim void *ctx; 3407274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len); 3408276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3409276789Sdim // its metadata. See 3410296417Sdim // https://github.com/google/sanitizers/issues/321. 3411274201Sdim SIZE_T res = REAL(mbstowcs)(dest, src, len); 3412274201Sdim if (res != (SIZE_T) - 1 && dest) { 3413274201Sdim SIZE_T write_cnt = res + (res < len); 3414274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t)); 3415274201Sdim } 3416274201Sdim return res; 3417274201Sdim} 3418274201Sdim 3419274201SdimINTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len, 3420274201Sdim void *ps) { 3421274201Sdim void *ctx; 3422274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps); 3423274201Sdim if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src)); 3424274201Sdim if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); 3425276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3426276789Sdim // its metadata. See 3427296417Sdim // https://github.com/google/sanitizers/issues/321. 3428274201Sdim SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps); 3429274201Sdim if (res != (SIZE_T)(-1) && dest && src) { 3430274201Sdim // This function, and several others, may or may not write the terminating 3431274201Sdim // \0 character. They write it iff they clear *src. 3432274201Sdim SIZE_T write_cnt = res + !*src; 3433274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t)); 3434274201Sdim } 3435274201Sdim return res; 3436274201Sdim} 3437274201Sdim 3438274201Sdim#define INIT_MBSTOWCS \ 3439274201Sdim COMMON_INTERCEPT_FUNCTION(mbstowcs); \ 3440274201Sdim COMMON_INTERCEPT_FUNCTION(mbsrtowcs); 3441274201Sdim#else 3442274201Sdim#define INIT_MBSTOWCS 3443274201Sdim#endif 3444274201Sdim 3445274201Sdim#if SANITIZER_INTERCEPT_MBSNRTOWCS 3446274201SdimINTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms, 3447274201Sdim SIZE_T len, void *ps) { 3448274201Sdim void *ctx; 3449274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps); 3450274201Sdim if (src) { 3451274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src)); 3452274201Sdim if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms); 3453274201Sdim } 3454274201Sdim if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); 3455276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3456276789Sdim // its metadata. See 3457296417Sdim // https://github.com/google/sanitizers/issues/321. 3458274201Sdim SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps); 3459274201Sdim if (res != (SIZE_T)(-1) && dest && src) { 3460274201Sdim SIZE_T write_cnt = res + !*src; 3461274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t)); 3462274201Sdim } 3463274201Sdim return res; 3464274201Sdim} 3465274201Sdim 3466274201Sdim#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs); 3467274201Sdim#else 3468274201Sdim#define INIT_MBSNRTOWCS 3469274201Sdim#endif 3470274201Sdim 3471274201Sdim#if SANITIZER_INTERCEPT_WCSTOMBS 3472274201SdimINTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) { 3473274201Sdim void *ctx; 3474274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len); 3475276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3476276789Sdim // its metadata. See 3477296417Sdim // https://github.com/google/sanitizers/issues/321. 3478274201Sdim SIZE_T res = REAL(wcstombs)(dest, src, len); 3479274201Sdim if (res != (SIZE_T) - 1 && dest) { 3480274201Sdim SIZE_T write_cnt = res + (res < len); 3481274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt); 3482274201Sdim } 3483274201Sdim return res; 3484274201Sdim} 3485274201Sdim 3486274201SdimINTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len, 3487274201Sdim void *ps) { 3488274201Sdim void *ctx; 3489274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps); 3490274201Sdim if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src)); 3491274201Sdim if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); 3492276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3493276789Sdim // its metadata. See 3494296417Sdim // https://github.com/google/sanitizers/issues/321. 3495274201Sdim SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps); 3496274201Sdim if (res != (SIZE_T) - 1 && dest && src) { 3497274201Sdim SIZE_T write_cnt = res + !*src; 3498274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt); 3499274201Sdim } 3500274201Sdim return res; 3501274201Sdim} 3502274201Sdim 3503274201Sdim#define INIT_WCSTOMBS \ 3504274201Sdim COMMON_INTERCEPT_FUNCTION(wcstombs); \ 3505274201Sdim COMMON_INTERCEPT_FUNCTION(wcsrtombs); 3506274201Sdim#else 3507274201Sdim#define INIT_WCSTOMBS 3508274201Sdim#endif 3509274201Sdim 3510274201Sdim#if SANITIZER_INTERCEPT_WCSNRTOMBS 3511274201SdimINTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms, 3512274201Sdim SIZE_T len, void *ps) { 3513274201Sdim void *ctx; 3514274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps); 3515274201Sdim if (src) { 3516274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src)); 3517274201Sdim if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms); 3518274201Sdim } 3519274201Sdim if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); 3520276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3521276789Sdim // its metadata. See 3522296417Sdim // https://github.com/google/sanitizers/issues/321. 3523274201Sdim SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps); 3524296417Sdim if (res != ((SIZE_T)-1) && dest && src) { 3525274201Sdim SIZE_T write_cnt = res + !*src; 3526274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt); 3527274201Sdim } 3528274201Sdim return res; 3529274201Sdim} 3530274201Sdim 3531274201Sdim#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs); 3532274201Sdim#else 3533274201Sdim#define INIT_WCSNRTOMBS 3534274201Sdim#endif 3535274201Sdim 3536296417Sdim 3537296417Sdim#if SANITIZER_INTERCEPT_WCRTOMB 3538296417SdimINTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) { 3539296417Sdim void *ctx; 3540296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps); 3541296417Sdim if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); 3542353358Sdim 3543353358Sdim if (!dest) 3544353358Sdim return REAL(wcrtomb)(dest, src, ps); 3545353358Sdim 3546353358Sdim char local_dest[32]; 3547353358Sdim SIZE_T res = REAL(wcrtomb)(local_dest, src, ps); 3548353358Sdim if (res != ((SIZE_T)-1)) { 3549353358Sdim CHECK_LE(res, sizeof(local_dest)); 3550353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res); 3551353358Sdim REAL(memcpy)(dest, local_dest, res); 3552296417Sdim } 3553296417Sdim return res; 3554296417Sdim} 3555296417Sdim 3556296417Sdim#define INIT_WCRTOMB COMMON_INTERCEPT_FUNCTION(wcrtomb); 3557296417Sdim#else 3558296417Sdim#define INIT_WCRTOMB 3559296417Sdim#endif 3560296417Sdim 3561353358Sdim#if SANITIZER_INTERCEPT_WCTOMB 3562353358SdimINTERCEPTOR(int, wctomb, char *dest, wchar_t src) { 3563353358Sdim void *ctx; 3564353358Sdim COMMON_INTERCEPTOR_ENTER(ctx, wctomb, dest, src); 3565353358Sdim if (!dest) 3566353358Sdim return REAL(wctomb)(dest, src); 3567353358Sdim 3568353358Sdim char local_dest[32]; 3569353358Sdim int res = REAL(wctomb)(local_dest, src); 3570353358Sdim if (res != -1) { 3571353358Sdim CHECK_LE(res, sizeof(local_dest)); 3572353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res); 3573353358Sdim REAL(memcpy)(dest, local_dest, res); 3574353358Sdim } 3575353358Sdim return res; 3576353358Sdim} 3577353358Sdim 3578353358Sdim#define INIT_WCTOMB COMMON_INTERCEPT_FUNCTION(wctomb); 3579353358Sdim#else 3580353358Sdim#define INIT_WCTOMB 3581353358Sdim#endif 3582353358Sdim 3583274201Sdim#if SANITIZER_INTERCEPT_TCGETATTR 3584274201SdimINTERCEPTOR(int, tcgetattr, int fd, void *termios_p) { 3585274201Sdim void *ctx; 3586274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p); 3587276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3588276789Sdim // its metadata. See 3589296417Sdim // https://github.com/google/sanitizers/issues/321. 3590274201Sdim int res = REAL(tcgetattr)(fd, termios_p); 3591274201Sdim if (!res && termios_p) 3592274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz); 3593274201Sdim return res; 3594274201Sdim} 3595274201Sdim 3596274201Sdim#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr); 3597274201Sdim#else 3598274201Sdim#define INIT_TCGETATTR 3599274201Sdim#endif 3600274201Sdim 3601274201Sdim#if SANITIZER_INTERCEPT_REALPATH 3602274201SdimINTERCEPTOR(char *, realpath, const char *path, char *resolved_path) { 3603274201Sdim void *ctx; 3604274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path); 3605274201Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 3606274201Sdim 3607274201Sdim // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest 3608274201Sdim // version of a versioned symbol. For realpath(), this gives us something 3609274201Sdim // (called __old_realpath) that does not handle NULL in the second argument. 3610274201Sdim // Handle it as part of the interceptor. 3611296417Sdim char *allocated_path = nullptr; 3612274201Sdim if (!resolved_path) 3613274201Sdim allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1); 3614274201Sdim 3615274201Sdim char *res = REAL(realpath)(path, resolved_path); 3616274201Sdim if (allocated_path && !res) WRAP(free)(allocated_path); 3617274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 3618274201Sdim return res; 3619274201Sdim} 3620274201Sdim#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath); 3621274201Sdim#else 3622274201Sdim#define INIT_REALPATH 3623274201Sdim#endif 3624274201Sdim 3625274201Sdim#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME 3626274201SdimINTERCEPTOR(char *, canonicalize_file_name, const char *path) { 3627274201Sdim void *ctx; 3628274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path); 3629274201Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 3630274201Sdim char *res = REAL(canonicalize_file_name)(path); 3631274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 3632274201Sdim return res; 3633274201Sdim} 3634274201Sdim#define INIT_CANONICALIZE_FILE_NAME \ 3635274201Sdim COMMON_INTERCEPT_FUNCTION(canonicalize_file_name); 3636274201Sdim#else 3637274201Sdim#define INIT_CANONICALIZE_FILE_NAME 3638274201Sdim#endif 3639274201Sdim 3640274201Sdim#if SANITIZER_INTERCEPT_CONFSTR 3641274201SdimINTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) { 3642274201Sdim void *ctx; 3643274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len); 3644276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3645276789Sdim // its metadata. See 3646296417Sdim // https://github.com/google/sanitizers/issues/321. 3647274201Sdim SIZE_T res = REAL(confstr)(name, buf, len); 3648274201Sdim if (buf && res) 3649274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len); 3650274201Sdim return res; 3651274201Sdim} 3652274201Sdim#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr); 3653274201Sdim#else 3654274201Sdim#define INIT_CONFSTR 3655274201Sdim#endif 3656274201Sdim 3657274201Sdim#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY 3658274201SdimINTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) { 3659274201Sdim void *ctx; 3660274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask); 3661276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3662276789Sdim // its metadata. See 3663296417Sdim // https://github.com/google/sanitizers/issues/321. 3664274201Sdim int res = REAL(sched_getaffinity)(pid, cpusetsize, mask); 3665274201Sdim if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize); 3666274201Sdim return res; 3667274201Sdim} 3668274201Sdim#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity); 3669274201Sdim#else 3670274201Sdim#define INIT_SCHED_GETAFFINITY 3671274201Sdim#endif 3672274201Sdim 3673280031Sdim#if SANITIZER_INTERCEPT_SCHED_GETPARAM 3674280031SdimINTERCEPTOR(int, sched_getparam, int pid, void *param) { 3675280031Sdim void *ctx; 3676280031Sdim COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param); 3677280031Sdim int res = REAL(sched_getparam)(pid, param); 3678280031Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz); 3679280031Sdim return res; 3680280031Sdim} 3681280031Sdim#define INIT_SCHED_GETPARAM COMMON_INTERCEPT_FUNCTION(sched_getparam); 3682280031Sdim#else 3683280031Sdim#define INIT_SCHED_GETPARAM 3684280031Sdim#endif 3685280031Sdim 3686274201Sdim#if SANITIZER_INTERCEPT_STRERROR 3687274201SdimINTERCEPTOR(char *, strerror, int errnum) { 3688274201Sdim void *ctx; 3689274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum); 3690360784Sdim COMMON_INTERCEPTOR_STRERROR(); 3691274201Sdim char *res = REAL(strerror)(errnum); 3692276789Sdim if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); 3693274201Sdim return res; 3694274201Sdim} 3695274201Sdim#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror); 3696274201Sdim#else 3697274201Sdim#define INIT_STRERROR 3698274201Sdim#endif 3699274201Sdim 3700274201Sdim#if SANITIZER_INTERCEPT_STRERROR_R 3701321369Sdim// There are 2 versions of strerror_r: 3702321369Sdim// * POSIX version returns 0 on success, negative error code on failure, 3703321369Sdim// writes message to buf. 3704321369Sdim// * GNU version returns message pointer, which points to either buf or some 3705321369Sdim// static storage. 3706321369Sdim#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \ 3707341825Sdim SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD || \ 3708341825Sdim SANITIZER_FREEBSD || SANITIZER_OPENBSD 3709321369Sdim// POSIX version. Spec is not clear on whether buf is NULL-terminated. 3710321369Sdim// At least on OSX, buf contents are valid even when the call fails. 3711321369SdimINTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) { 3712321369Sdim void *ctx; 3713321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen); 3714321369Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3715321369Sdim // its metadata. See 3716321369Sdim // https://github.com/google/sanitizers/issues/321. 3717321369Sdim int res = REAL(strerror_r)(errnum, buf, buflen); 3718321369Sdim 3719321369Sdim SIZE_T sz = internal_strnlen(buf, buflen); 3720321369Sdim if (sz < buflen) ++sz; 3721321369Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz); 3722321369Sdim return res; 3723321369Sdim} 3724321369Sdim#else 3725321369Sdim// GNU version. 3726274201SdimINTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) { 3727274201Sdim void *ctx; 3728274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen); 3729276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3730276789Sdim // its metadata. See 3731296417Sdim // https://github.com/google/sanitizers/issues/321. 3732274201Sdim char *res = REAL(strerror_r)(errnum, buf, buflen); 3733321369Sdim if (res == buf) 3734274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 3735321369Sdim else 3736321369Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); 3737274201Sdim return res; 3738274201Sdim} 3739321369Sdim#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE || 3740321369Sdim //SANITIZER_MAC 3741274201Sdim#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r); 3742274201Sdim#else 3743274201Sdim#define INIT_STRERROR_R 3744274201Sdim#endif 3745274201Sdim 3746276789Sdim#if SANITIZER_INTERCEPT_XPG_STRERROR_R 3747276789SdimINTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) { 3748276789Sdim void *ctx; 3749276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen); 3750276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3751276789Sdim // its metadata. See 3752296417Sdim // https://github.com/google/sanitizers/issues/321. 3753276789Sdim int res = REAL(__xpg_strerror_r)(errnum, buf, buflen); 3754276789Sdim // This version always returns a null-terminated string. 3755276789Sdim if (buf && buflen) 3756276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1); 3757276789Sdim return res; 3758276789Sdim} 3759276789Sdim#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r); 3760276789Sdim#else 3761276789Sdim#define INIT_XPG_STRERROR_R 3762276789Sdim#endif 3763276789Sdim 3764274201Sdim#if SANITIZER_INTERCEPT_SCANDIR 3765274201Sdimtypedef int (*scandir_filter_f)(const struct __sanitizer_dirent *); 3766274201Sdimtypedef int (*scandir_compar_f)(const struct __sanitizer_dirent **, 3767274201Sdim const struct __sanitizer_dirent **); 3768274201Sdim 3769274201Sdimstatic THREADLOCAL scandir_filter_f scandir_filter; 3770274201Sdimstatic THREADLOCAL scandir_compar_f scandir_compar; 3771274201Sdim 3772274201Sdimstatic int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) { 3773276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 3774276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen); 3775274201Sdim return scandir_filter(dir); 3776274201Sdim} 3777274201Sdim 3778274201Sdimstatic int wrapped_scandir_compar(const struct __sanitizer_dirent **a, 3779274201Sdim const struct __sanitizer_dirent **b) { 3780276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(2); 3781276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a)); 3782276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen); 3783276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b)); 3784276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen); 3785274201Sdim return scandir_compar(a, b); 3786274201Sdim} 3787274201Sdim 3788274201SdimINTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist, 3789274201Sdim scandir_filter_f filter, scandir_compar_f compar) { 3790274201Sdim void *ctx; 3791274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar); 3792274201Sdim if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1); 3793274201Sdim scandir_filter = filter; 3794274201Sdim scandir_compar = compar; 3795276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3796276789Sdim // its metadata. See 3797296417Sdim // https://github.com/google/sanitizers/issues/321. 3798296417Sdim int res = REAL(scandir)(dirp, namelist, 3799296417Sdim filter ? wrapped_scandir_filter : nullptr, 3800296417Sdim compar ? wrapped_scandir_compar : nullptr); 3801296417Sdim scandir_filter = nullptr; 3802296417Sdim scandir_compar = nullptr; 3803274201Sdim if (namelist && res > 0) { 3804274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist)); 3805274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res); 3806274201Sdim for (int i = 0; i < res; ++i) 3807274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i], 3808274201Sdim (*namelist)[i]->d_reclen); 3809274201Sdim } 3810274201Sdim return res; 3811274201Sdim} 3812274201Sdim#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir); 3813274201Sdim#else 3814274201Sdim#define INIT_SCANDIR 3815274201Sdim#endif 3816274201Sdim 3817274201Sdim#if SANITIZER_INTERCEPT_SCANDIR64 3818274201Sdimtypedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *); 3819274201Sdimtypedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **, 3820274201Sdim const struct __sanitizer_dirent64 **); 3821274201Sdim 3822274201Sdimstatic THREADLOCAL scandir64_filter_f scandir64_filter; 3823274201Sdimstatic THREADLOCAL scandir64_compar_f scandir64_compar; 3824274201Sdim 3825274201Sdimstatic int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) { 3826276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 3827276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen); 3828274201Sdim return scandir64_filter(dir); 3829274201Sdim} 3830274201Sdim 3831274201Sdimstatic int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a, 3832274201Sdim const struct __sanitizer_dirent64 **b) { 3833276789Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(2); 3834276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a)); 3835276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen); 3836276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b)); 3837276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen); 3838274201Sdim return scandir64_compar(a, b); 3839274201Sdim} 3840274201Sdim 3841274201SdimINTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist, 3842274201Sdim scandir64_filter_f filter, scandir64_compar_f compar) { 3843274201Sdim void *ctx; 3844274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar); 3845274201Sdim if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1); 3846274201Sdim scandir64_filter = filter; 3847274201Sdim scandir64_compar = compar; 3848276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3849276789Sdim // its metadata. See 3850296417Sdim // https://github.com/google/sanitizers/issues/321. 3851274201Sdim int res = 3852296417Sdim REAL(scandir64)(dirp, namelist, 3853296417Sdim filter ? wrapped_scandir64_filter : nullptr, 3854296417Sdim compar ? wrapped_scandir64_compar : nullptr); 3855296417Sdim scandir64_filter = nullptr; 3856296417Sdim scandir64_compar = nullptr; 3857274201Sdim if (namelist && res > 0) { 3858274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist)); 3859274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res); 3860274201Sdim for (int i = 0; i < res; ++i) 3861274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i], 3862274201Sdim (*namelist)[i]->d_reclen); 3863274201Sdim } 3864274201Sdim return res; 3865274201Sdim} 3866274201Sdim#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64); 3867274201Sdim#else 3868274201Sdim#define INIT_SCANDIR64 3869274201Sdim#endif 3870274201Sdim 3871274201Sdim#if SANITIZER_INTERCEPT_GETGROUPS 3872274201SdimINTERCEPTOR(int, getgroups, int size, u32 *lst) { 3873274201Sdim void *ctx; 3874274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst); 3875276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3876276789Sdim // its metadata. See 3877296417Sdim // https://github.com/google/sanitizers/issues/321. 3878274201Sdim int res = REAL(getgroups)(size, lst); 3879321369Sdim if (res >= 0 && lst && size > 0) 3880321369Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst)); 3881274201Sdim return res; 3882274201Sdim} 3883274201Sdim#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups); 3884274201Sdim#else 3885274201Sdim#define INIT_GETGROUPS 3886274201Sdim#endif 3887274201Sdim 3888274201Sdim#if SANITIZER_INTERCEPT_POLL 3889274201Sdimstatic void read_pollfd(void *ctx, __sanitizer_pollfd *fds, 3890274201Sdim __sanitizer_nfds_t nfds) { 3891274201Sdim for (unsigned i = 0; i < nfds; ++i) { 3892274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd)); 3893274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events)); 3894274201Sdim } 3895274201Sdim} 3896274201Sdim 3897274201Sdimstatic void write_pollfd(void *ctx, __sanitizer_pollfd *fds, 3898274201Sdim __sanitizer_nfds_t nfds) { 3899274201Sdim for (unsigned i = 0; i < nfds; ++i) 3900274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents, 3901274201Sdim sizeof(fds[i].revents)); 3902274201Sdim} 3903274201Sdim 3904274201SdimINTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds, 3905274201Sdim int timeout) { 3906274201Sdim void *ctx; 3907274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout); 3908274201Sdim if (fds && nfds) read_pollfd(ctx, fds, nfds); 3909274201Sdim int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout); 3910274201Sdim if (fds && nfds) write_pollfd(ctx, fds, nfds); 3911274201Sdim return res; 3912274201Sdim} 3913274201Sdim#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll); 3914274201Sdim#else 3915274201Sdim#define INIT_POLL 3916274201Sdim#endif 3917274201Sdim 3918274201Sdim#if SANITIZER_INTERCEPT_PPOLL 3919274201SdimINTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds, 3920274201Sdim void *timeout_ts, __sanitizer_sigset_t *sigmask) { 3921274201Sdim void *ctx; 3922274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask); 3923274201Sdim if (fds && nfds) read_pollfd(ctx, fds, nfds); 3924274201Sdim if (timeout_ts) 3925274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz); 3926327952Sdim if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask)); 3927274201Sdim int res = 3928274201Sdim COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask); 3929274201Sdim if (fds && nfds) write_pollfd(ctx, fds, nfds); 3930274201Sdim return res; 3931274201Sdim} 3932274201Sdim#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll); 3933274201Sdim#else 3934274201Sdim#define INIT_PPOLL 3935274201Sdim#endif 3936274201Sdim 3937274201Sdim#if SANITIZER_INTERCEPT_WORDEXP 3938274201SdimINTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) { 3939274201Sdim void *ctx; 3940274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags); 3941274201Sdim if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); 3942276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3943276789Sdim // its metadata. See 3944296417Sdim // https://github.com/google/sanitizers/issues/321. 3945274201Sdim int res = REAL(wordexp)(s, p, flags); 3946274201Sdim if (!res && p) { 3947274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); 3948274201Sdim if (p->we_wordc) 3949274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv, 3950274201Sdim sizeof(*p->we_wordv) * p->we_wordc); 3951274201Sdim for (uptr i = 0; i < p->we_wordc; ++i) { 3952274201Sdim char *w = p->we_wordv[i]; 3953274201Sdim if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1); 3954274201Sdim } 3955274201Sdim } 3956274201Sdim return res; 3957274201Sdim} 3958274201Sdim#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp); 3959274201Sdim#else 3960274201Sdim#define INIT_WORDEXP 3961274201Sdim#endif 3962274201Sdim 3963274201Sdim#if SANITIZER_INTERCEPT_SIGWAIT 3964274201SdimINTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) { 3965274201Sdim void *ctx; 3966274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig); 3967327952Sdim if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set)); 3968276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3969276789Sdim // its metadata. See 3970296417Sdim // https://github.com/google/sanitizers/issues/321. 3971274201Sdim int res = REAL(sigwait)(set, sig); 3972274201Sdim if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig)); 3973274201Sdim return res; 3974274201Sdim} 3975274201Sdim#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait); 3976274201Sdim#else 3977274201Sdim#define INIT_SIGWAIT 3978274201Sdim#endif 3979274201Sdim 3980274201Sdim#if SANITIZER_INTERCEPT_SIGWAITINFO 3981274201SdimINTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) { 3982274201Sdim void *ctx; 3983274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info); 3984327952Sdim if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set)); 3985276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 3986276789Sdim // its metadata. See 3987296417Sdim // https://github.com/google/sanitizers/issues/321. 3988274201Sdim int res = REAL(sigwaitinfo)(set, info); 3989274201Sdim if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz); 3990274201Sdim return res; 3991274201Sdim} 3992274201Sdim#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo); 3993274201Sdim#else 3994274201Sdim#define INIT_SIGWAITINFO 3995274201Sdim#endif 3996274201Sdim 3997274201Sdim#if SANITIZER_INTERCEPT_SIGTIMEDWAIT 3998274201SdimINTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info, 3999274201Sdim void *timeout) { 4000274201Sdim void *ctx; 4001274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout); 4002274201Sdim if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz); 4003327952Sdim if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set)); 4004276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4005276789Sdim // its metadata. See 4006296417Sdim // https://github.com/google/sanitizers/issues/321. 4007274201Sdim int res = REAL(sigtimedwait)(set, info, timeout); 4008274201Sdim if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz); 4009274201Sdim return res; 4010274201Sdim} 4011274201Sdim#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait); 4012274201Sdim#else 4013274201Sdim#define INIT_SIGTIMEDWAIT 4014274201Sdim#endif 4015274201Sdim 4016274201Sdim#if SANITIZER_INTERCEPT_SIGSETOPS 4017274201SdimINTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) { 4018274201Sdim void *ctx; 4019274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set); 4020276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4021276789Sdim // its metadata. See 4022296417Sdim // https://github.com/google/sanitizers/issues/321. 4023274201Sdim int res = REAL(sigemptyset)(set); 4024274201Sdim if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set)); 4025274201Sdim return res; 4026274201Sdim} 4027274201Sdim 4028274201SdimINTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) { 4029274201Sdim void *ctx; 4030274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set); 4031276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4032276789Sdim // its metadata. See 4033296417Sdim // https://github.com/google/sanitizers/issues/321. 4034274201Sdim int res = REAL(sigfillset)(set); 4035274201Sdim if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set)); 4036274201Sdim return res; 4037274201Sdim} 4038274201Sdim#define INIT_SIGSETOPS \ 4039274201Sdim COMMON_INTERCEPT_FUNCTION(sigemptyset); \ 4040274201Sdim COMMON_INTERCEPT_FUNCTION(sigfillset); 4041274201Sdim#else 4042274201Sdim#define INIT_SIGSETOPS 4043274201Sdim#endif 4044274201Sdim 4045274201Sdim#if SANITIZER_INTERCEPT_SIGPENDING 4046274201SdimINTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) { 4047274201Sdim void *ctx; 4048274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set); 4049276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4050276789Sdim // its metadata. See 4051296417Sdim // https://github.com/google/sanitizers/issues/321. 4052274201Sdim int res = REAL(sigpending)(set); 4053274201Sdim if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set)); 4054274201Sdim return res; 4055274201Sdim} 4056274201Sdim#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending); 4057274201Sdim#else 4058274201Sdim#define INIT_SIGPENDING 4059274201Sdim#endif 4060274201Sdim 4061274201Sdim#if SANITIZER_INTERCEPT_SIGPROCMASK 4062274201SdimINTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set, 4063274201Sdim __sanitizer_sigset_t *oldset) { 4064274201Sdim void *ctx; 4065274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset); 4066327952Sdim if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set)); 4067276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4068276789Sdim // its metadata. See 4069296417Sdim // https://github.com/google/sanitizers/issues/321. 4070274201Sdim int res = REAL(sigprocmask)(how, set, oldset); 4071274201Sdim if (!res && oldset) 4072274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset)); 4073274201Sdim return res; 4074274201Sdim} 4075274201Sdim#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask); 4076274201Sdim#else 4077274201Sdim#define INIT_SIGPROCMASK 4078274201Sdim#endif 4079274201Sdim 4080353358Sdim#if SANITIZER_INTERCEPT_PTHREAD_SIGMASK 4081353358SdimINTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set, 4082353358Sdim __sanitizer_sigset_t *oldset) { 4083353358Sdim void *ctx; 4084353358Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset); 4085353358Sdim if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set)); 4086353358Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4087353358Sdim // its metadata. See 4088353358Sdim // https://github.com/google/sanitizers/issues/321. 4089353358Sdim int res = REAL(pthread_sigmask)(how, set, oldset); 4090353358Sdim if (!res && oldset) 4091353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset)); 4092353358Sdim return res; 4093353358Sdim} 4094353358Sdim#define INIT_PTHREAD_SIGMASK COMMON_INTERCEPT_FUNCTION(pthread_sigmask); 4095353358Sdim#else 4096353358Sdim#define INIT_PTHREAD_SIGMASK 4097353358Sdim#endif 4098353358Sdim 4099274201Sdim#if SANITIZER_INTERCEPT_BACKTRACE 4100274201SdimINTERCEPTOR(int, backtrace, void **buffer, int size) { 4101274201Sdim void *ctx; 4102274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size); 4103276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4104276789Sdim // its metadata. See 4105296417Sdim // https://github.com/google/sanitizers/issues/321. 4106274201Sdim int res = REAL(backtrace)(buffer, size); 4107274201Sdim if (res && buffer) 4108274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer)); 4109274201Sdim return res; 4110274201Sdim} 4111274201Sdim 4112274201SdimINTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) { 4113274201Sdim void *ctx; 4114274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size); 4115274201Sdim if (buffer && size) 4116274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer)); 4117276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4118276789Sdim // its metadata. See 4119296417Sdim // https://github.com/google/sanitizers/issues/321. 4120274201Sdim char **res = REAL(backtrace_symbols)(buffer, size); 4121274201Sdim if (res && size) { 4122274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res)); 4123274201Sdim for (int i = 0; i < size; ++i) 4124274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1); 4125274201Sdim } 4126274201Sdim return res; 4127274201Sdim} 4128274201Sdim#define INIT_BACKTRACE \ 4129274201Sdim COMMON_INTERCEPT_FUNCTION(backtrace); \ 4130274201Sdim COMMON_INTERCEPT_FUNCTION(backtrace_symbols); 4131274201Sdim#else 4132274201Sdim#define INIT_BACKTRACE 4133274201Sdim#endif 4134274201Sdim 4135274201Sdim#if SANITIZER_INTERCEPT__EXIT 4136274201SdimINTERCEPTOR(void, _exit, int status) { 4137274201Sdim void *ctx; 4138274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, _exit, status); 4139309124Sdim COMMON_INTERCEPTOR_USER_CALLBACK_START(); 4140274201Sdim int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx); 4141309124Sdim COMMON_INTERCEPTOR_USER_CALLBACK_END(); 4142274201Sdim if (status == 0) status = status1; 4143274201Sdim REAL(_exit)(status); 4144274201Sdim} 4145274201Sdim#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit); 4146274201Sdim#else 4147274201Sdim#define INIT__EXIT 4148274201Sdim#endif 4149274201Sdim 4150341825Sdim#if SANITIZER_INTERCEPT_PTHREAD_MUTEX 4151274201SdimINTERCEPTOR(int, pthread_mutex_lock, void *m) { 4152274201Sdim void *ctx; 4153274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m); 4154321369Sdim COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m); 4155274201Sdim int res = REAL(pthread_mutex_lock)(m); 4156274201Sdim if (res == errno_EOWNERDEAD) 4157274201Sdim COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m); 4158274201Sdim if (res == 0 || res == errno_EOWNERDEAD) 4159321369Sdim COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m); 4160309124Sdim if (res == errno_EINVAL) 4161309124Sdim COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); 4162274201Sdim return res; 4163274201Sdim} 4164274201Sdim 4165274201SdimINTERCEPTOR(int, pthread_mutex_unlock, void *m) { 4166274201Sdim void *ctx; 4167274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m); 4168274201Sdim COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m); 4169309124Sdim int res = REAL(pthread_mutex_unlock)(m); 4170309124Sdim if (res == errno_EINVAL) 4171309124Sdim COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); 4172309124Sdim return res; 4173274201Sdim} 4174274201Sdim 4175274201Sdim#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock) 4176274201Sdim#define INIT_PTHREAD_MUTEX_UNLOCK \ 4177274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock) 4178274201Sdim#else 4179274201Sdim#define INIT_PTHREAD_MUTEX_LOCK 4180274201Sdim#define INIT_PTHREAD_MUTEX_UNLOCK 4181274201Sdim#endif 4182274201Sdim 4183341825Sdim#if SANITIZER_INTERCEPT___PTHREAD_MUTEX 4184341825SdimINTERCEPTOR(int, __pthread_mutex_lock, void *m) { 4185360784Sdim void *ctx; 4186360784Sdim COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_lock, m); 4187360784Sdim COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m); 4188360784Sdim int res = REAL(__pthread_mutex_lock)(m); 4189360784Sdim if (res == errno_EOWNERDEAD) 4190360784Sdim COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m); 4191360784Sdim if (res == 0 || res == errno_EOWNERDEAD) 4192360784Sdim COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m); 4193360784Sdim if (res == errno_EINVAL) 4194360784Sdim COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); 4195360784Sdim return res; 4196341825Sdim} 4197341825Sdim 4198341825SdimINTERCEPTOR(int, __pthread_mutex_unlock, void *m) { 4199360784Sdim void *ctx; 4200360784Sdim COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_unlock, m); 4201360784Sdim COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m); 4202360784Sdim int res = REAL(__pthread_mutex_unlock)(m); 4203360784Sdim if (res == errno_EINVAL) 4204360784Sdim COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); 4205360784Sdim return res; 4206341825Sdim} 4207341825Sdim 4208341825Sdim#define INIT___PTHREAD_MUTEX_LOCK \ 4209341825Sdim COMMON_INTERCEPT_FUNCTION(__pthread_mutex_lock) 4210341825Sdim#define INIT___PTHREAD_MUTEX_UNLOCK \ 4211341825Sdim COMMON_INTERCEPT_FUNCTION(__pthread_mutex_unlock) 4212341825Sdim#else 4213341825Sdim#define INIT___PTHREAD_MUTEX_LOCK 4214341825Sdim#define INIT___PTHREAD_MUTEX_UNLOCK 4215327952Sdim#endif 4216327952Sdim 4217341825Sdim#if SANITIZER_INTERCEPT___LIBC_MUTEX 4218341825SdimINTERCEPTOR(int, __libc_mutex_lock, void *m) 4219341825SdimALIAS(WRAPPER_NAME(pthread_mutex_lock)); 4220341825Sdim 4221341825SdimINTERCEPTOR(int, __libc_mutex_unlock, void *m) 4222341825SdimALIAS(WRAPPER_NAME(pthread_mutex_unlock)); 4223341825Sdim 4224341825SdimINTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate) 4225341825SdimALIAS(WRAPPER_NAME(pthread_setcancelstate)); 4226341825Sdim 4227341825Sdim#define INIT___LIBC_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock) 4228341825Sdim#define INIT___LIBC_MUTEX_UNLOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_unlock) 4229341825Sdim#define INIT___LIBC_THR_SETCANCELSTATE \ 4230341825Sdim COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate) 4231341825Sdim#else 4232341825Sdim#define INIT___LIBC_MUTEX_LOCK 4233341825Sdim#define INIT___LIBC_MUTEX_UNLOCK 4234341825Sdim#define INIT___LIBC_THR_SETCANCELSTATE 4235341825Sdim#endif 4236341825Sdim 4237274201Sdim#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R 4238274201Sdimstatic void write_mntent(void *ctx, __sanitizer_mntent *mnt) { 4239274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt)); 4240274201Sdim if (mnt->mnt_fsname) 4241274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname, 4242274201Sdim REAL(strlen)(mnt->mnt_fsname) + 1); 4243274201Sdim if (mnt->mnt_dir) 4244274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir, 4245274201Sdim REAL(strlen)(mnt->mnt_dir) + 1); 4246274201Sdim if (mnt->mnt_type) 4247274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type, 4248274201Sdim REAL(strlen)(mnt->mnt_type) + 1); 4249274201Sdim if (mnt->mnt_opts) 4250274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts, 4251274201Sdim REAL(strlen)(mnt->mnt_opts) + 1); 4252274201Sdim} 4253274201Sdim#endif 4254274201Sdim 4255274201Sdim#if SANITIZER_INTERCEPT_GETMNTENT 4256274201SdimINTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) { 4257274201Sdim void *ctx; 4258274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp); 4259274201Sdim __sanitizer_mntent *res = REAL(getmntent)(fp); 4260274201Sdim if (res) write_mntent(ctx, res); 4261274201Sdim return res; 4262274201Sdim} 4263274201Sdim#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent); 4264274201Sdim#else 4265274201Sdim#define INIT_GETMNTENT 4266274201Sdim#endif 4267274201Sdim 4268274201Sdim#if SANITIZER_INTERCEPT_GETMNTENT_R 4269274201SdimINTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp, 4270274201Sdim __sanitizer_mntent *mntbuf, char *buf, int buflen) { 4271274201Sdim void *ctx; 4272274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen); 4273274201Sdim __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen); 4274274201Sdim if (res) write_mntent(ctx, res); 4275274201Sdim return res; 4276274201Sdim} 4277274201Sdim#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r); 4278274201Sdim#else 4279274201Sdim#define INIT_GETMNTENT_R 4280274201Sdim#endif 4281274201Sdim 4282274201Sdim#if SANITIZER_INTERCEPT_STATFS 4283274201SdimINTERCEPTOR(int, statfs, char *path, void *buf) { 4284274201Sdim void *ctx; 4285274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf); 4286274201Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 4287276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4288276789Sdim // its metadata. See 4289296417Sdim // https://github.com/google/sanitizers/issues/321. 4290274201Sdim int res = REAL(statfs)(path, buf); 4291274201Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz); 4292274201Sdim return res; 4293274201Sdim} 4294274201SdimINTERCEPTOR(int, fstatfs, int fd, void *buf) { 4295274201Sdim void *ctx; 4296274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf); 4297276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4298276789Sdim // its metadata. See 4299296417Sdim // https://github.com/google/sanitizers/issues/321. 4300274201Sdim int res = REAL(fstatfs)(fd, buf); 4301274201Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz); 4302274201Sdim return res; 4303274201Sdim} 4304274201Sdim#define INIT_STATFS \ 4305274201Sdim COMMON_INTERCEPT_FUNCTION(statfs); \ 4306274201Sdim COMMON_INTERCEPT_FUNCTION(fstatfs); 4307274201Sdim#else 4308274201Sdim#define INIT_STATFS 4309274201Sdim#endif 4310274201Sdim 4311274201Sdim#if SANITIZER_INTERCEPT_STATFS64 4312274201SdimINTERCEPTOR(int, statfs64, char *path, void *buf) { 4313274201Sdim void *ctx; 4314274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf); 4315274201Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 4316276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4317276789Sdim // its metadata. See 4318296417Sdim // https://github.com/google/sanitizers/issues/321. 4319274201Sdim int res = REAL(statfs64)(path, buf); 4320274201Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz); 4321274201Sdim return res; 4322274201Sdim} 4323274201SdimINTERCEPTOR(int, fstatfs64, int fd, void *buf) { 4324274201Sdim void *ctx; 4325274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf); 4326276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4327276789Sdim // its metadata. See 4328296417Sdim // https://github.com/google/sanitizers/issues/321. 4329274201Sdim int res = REAL(fstatfs64)(fd, buf); 4330274201Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz); 4331274201Sdim return res; 4332274201Sdim} 4333274201Sdim#define INIT_STATFS64 \ 4334274201Sdim COMMON_INTERCEPT_FUNCTION(statfs64); \ 4335274201Sdim COMMON_INTERCEPT_FUNCTION(fstatfs64); 4336274201Sdim#else 4337274201Sdim#define INIT_STATFS64 4338274201Sdim#endif 4339274201Sdim 4340274201Sdim#if SANITIZER_INTERCEPT_STATVFS 4341274201SdimINTERCEPTOR(int, statvfs, char *path, void *buf) { 4342274201Sdim void *ctx; 4343274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf); 4344274201Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 4345276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4346276789Sdim // its metadata. See 4347296417Sdim // https://github.com/google/sanitizers/issues/321. 4348274201Sdim int res = REAL(statvfs)(path, buf); 4349274201Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); 4350274201Sdim return res; 4351274201Sdim} 4352274201SdimINTERCEPTOR(int, fstatvfs, int fd, void *buf) { 4353274201Sdim void *ctx; 4354274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf); 4355344779Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 4356276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4357276789Sdim // its metadata. See 4358296417Sdim // https://github.com/google/sanitizers/issues/321. 4359274201Sdim int res = REAL(fstatvfs)(fd, buf); 4360344779Sdim if (!res) { 4361344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); 4362344779Sdim if (fd >= 0) 4363344779Sdim COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 4364344779Sdim } 4365274201Sdim return res; 4366274201Sdim} 4367274201Sdim#define INIT_STATVFS \ 4368274201Sdim COMMON_INTERCEPT_FUNCTION(statvfs); \ 4369274201Sdim COMMON_INTERCEPT_FUNCTION(fstatvfs); 4370274201Sdim#else 4371274201Sdim#define INIT_STATVFS 4372274201Sdim#endif 4373274201Sdim 4374274201Sdim#if SANITIZER_INTERCEPT_STATVFS64 4375274201SdimINTERCEPTOR(int, statvfs64, char *path, void *buf) { 4376274201Sdim void *ctx; 4377274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf); 4378274201Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 4379276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4380276789Sdim // its metadata. See 4381296417Sdim // https://github.com/google/sanitizers/issues/321. 4382274201Sdim int res = REAL(statvfs64)(path, buf); 4383274201Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz); 4384274201Sdim return res; 4385274201Sdim} 4386274201SdimINTERCEPTOR(int, fstatvfs64, int fd, void *buf) { 4387274201Sdim void *ctx; 4388274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf); 4389276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4390276789Sdim // its metadata. See 4391296417Sdim // https://github.com/google/sanitizers/issues/321. 4392274201Sdim int res = REAL(fstatvfs64)(fd, buf); 4393274201Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz); 4394274201Sdim return res; 4395274201Sdim} 4396274201Sdim#define INIT_STATVFS64 \ 4397274201Sdim COMMON_INTERCEPT_FUNCTION(statvfs64); \ 4398274201Sdim COMMON_INTERCEPT_FUNCTION(fstatvfs64); 4399274201Sdim#else 4400274201Sdim#define INIT_STATVFS64 4401274201Sdim#endif 4402274201Sdim 4403274201Sdim#if SANITIZER_INTERCEPT_INITGROUPS 4404274201SdimINTERCEPTOR(int, initgroups, char *user, u32 group) { 4405274201Sdim void *ctx; 4406274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group); 4407274201Sdim if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1); 4408274201Sdim int res = REAL(initgroups)(user, group); 4409274201Sdim return res; 4410274201Sdim} 4411274201Sdim#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups); 4412274201Sdim#else 4413274201Sdim#define INIT_INITGROUPS 4414274201Sdim#endif 4415274201Sdim 4416276789Sdim#if SANITIZER_INTERCEPT_ETHER_NTOA_ATON 4417274201SdimINTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) { 4418274201Sdim void *ctx; 4419274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr); 4420274201Sdim if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr)); 4421274201Sdim char *res = REAL(ether_ntoa)(addr); 4422276789Sdim if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); 4423274201Sdim return res; 4424274201Sdim} 4425274201SdimINTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) { 4426274201Sdim void *ctx; 4427274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf); 4428274201Sdim if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1); 4429274201Sdim __sanitizer_ether_addr *res = REAL(ether_aton)(buf); 4430276789Sdim if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res)); 4431274201Sdim return res; 4432274201Sdim} 4433276789Sdim#define INIT_ETHER_NTOA_ATON \ 4434276789Sdim COMMON_INTERCEPT_FUNCTION(ether_ntoa); \ 4435276789Sdim COMMON_INTERCEPT_FUNCTION(ether_aton); 4436276789Sdim#else 4437276789Sdim#define INIT_ETHER_NTOA_ATON 4438276789Sdim#endif 4439276789Sdim 4440276789Sdim#if SANITIZER_INTERCEPT_ETHER_HOST 4441274201SdimINTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) { 4442274201Sdim void *ctx; 4443274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr); 4444274201Sdim if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr)); 4445276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4446276789Sdim // its metadata. See 4447296417Sdim // https://github.com/google/sanitizers/issues/321. 4448274201Sdim int res = REAL(ether_ntohost)(hostname, addr); 4449274201Sdim if (!res && hostname) 4450274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1); 4451274201Sdim return res; 4452274201Sdim} 4453274201SdimINTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) { 4454274201Sdim void *ctx; 4455274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr); 4456274201Sdim if (hostname) 4457274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1); 4458276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4459276789Sdim // its metadata. See 4460296417Sdim // https://github.com/google/sanitizers/issues/321. 4461274201Sdim int res = REAL(ether_hostton)(hostname, addr); 4462274201Sdim if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr)); 4463274201Sdim return res; 4464274201Sdim} 4465274201SdimINTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr, 4466274201Sdim char *hostname) { 4467274201Sdim void *ctx; 4468274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname); 4469274201Sdim if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1); 4470276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4471276789Sdim // its metadata. See 4472296417Sdim // https://github.com/google/sanitizers/issues/321. 4473274201Sdim int res = REAL(ether_line)(line, addr, hostname); 4474274201Sdim if (!res) { 4475274201Sdim if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr)); 4476274201Sdim if (hostname) 4477274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1); 4478274201Sdim } 4479274201Sdim return res; 4480274201Sdim} 4481276789Sdim#define INIT_ETHER_HOST \ 4482274201Sdim COMMON_INTERCEPT_FUNCTION(ether_ntohost); \ 4483274201Sdim COMMON_INTERCEPT_FUNCTION(ether_hostton); \ 4484274201Sdim COMMON_INTERCEPT_FUNCTION(ether_line); 4485274201Sdim#else 4486276789Sdim#define INIT_ETHER_HOST 4487274201Sdim#endif 4488274201Sdim 4489274201Sdim#if SANITIZER_INTERCEPT_ETHER_R 4490274201SdimINTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) { 4491274201Sdim void *ctx; 4492274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf); 4493274201Sdim if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr)); 4494276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4495276789Sdim // its metadata. See 4496296417Sdim // https://github.com/google/sanitizers/issues/321. 4497274201Sdim char *res = REAL(ether_ntoa_r)(addr, buf); 4498274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 4499274201Sdim return res; 4500274201Sdim} 4501274201SdimINTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf, 4502274201Sdim __sanitizer_ether_addr *addr) { 4503274201Sdim void *ctx; 4504274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr); 4505274201Sdim if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1); 4506276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4507276789Sdim // its metadata. See 4508296417Sdim // https://github.com/google/sanitizers/issues/321. 4509274201Sdim __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr); 4510274201Sdim if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res)); 4511274201Sdim return res; 4512274201Sdim} 4513274201Sdim#define INIT_ETHER_R \ 4514274201Sdim COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \ 4515274201Sdim COMMON_INTERCEPT_FUNCTION(ether_aton_r); 4516274201Sdim#else 4517274201Sdim#define INIT_ETHER_R 4518274201Sdim#endif 4519274201Sdim 4520274201Sdim#if SANITIZER_INTERCEPT_SHMCTL 4521274201SdimINTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) { 4522274201Sdim void *ctx; 4523274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf); 4524276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4525276789Sdim // its metadata. See 4526296417Sdim // https://github.com/google/sanitizers/issues/321. 4527274201Sdim int res = REAL(shmctl)(shmid, cmd, buf); 4528274201Sdim if (res >= 0) { 4529274201Sdim unsigned sz = 0; 4530274201Sdim if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat) 4531274201Sdim sz = sizeof(__sanitizer_shmid_ds); 4532274201Sdim else if (cmd == shmctl_ipc_info) 4533274201Sdim sz = struct_shminfo_sz; 4534274201Sdim else if (cmd == shmctl_shm_info) 4535274201Sdim sz = struct_shm_info_sz; 4536274201Sdim if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz); 4537274201Sdim } 4538274201Sdim return res; 4539274201Sdim} 4540274201Sdim#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl); 4541274201Sdim#else 4542274201Sdim#define INIT_SHMCTL 4543274201Sdim#endif 4544274201Sdim 4545274201Sdim#if SANITIZER_INTERCEPT_RANDOM_R 4546274201SdimINTERCEPTOR(int, random_r, void *buf, u32 *result) { 4547274201Sdim void *ctx; 4548274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result); 4549276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4550276789Sdim // its metadata. See 4551296417Sdim // https://github.com/google/sanitizers/issues/321. 4552274201Sdim int res = REAL(random_r)(buf, result); 4553274201Sdim if (!res && result) 4554274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 4555274201Sdim return res; 4556274201Sdim} 4557274201Sdim#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r); 4558274201Sdim#else 4559274201Sdim#define INIT_RANDOM_R 4560274201Sdim#endif 4561274201Sdim 4562276789Sdim// FIXME: under ASan the REAL() call below may write to freed memory and corrupt 4563276789Sdim// its metadata. See 4564296417Sdim// https://github.com/google/sanitizers/issues/321. 4565276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET || \ 4566341825Sdim SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED || \ 4567276789Sdim SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \ 4568276789Sdim SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET || \ 4569276789Sdim SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GET || \ 4570276789Sdim SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GET || \ 4571276789Sdim SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GET 4572276789Sdim#define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz) \ 4573276789Sdim INTERCEPTOR(int, fn, void *attr, void *r) { \ 4574276789Sdim void *ctx; \ 4575276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r); \ 4576276789Sdim int res = REAL(fn)(attr, r); \ 4577276789Sdim if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \ 4578276789Sdim return res; \ 4579274201Sdim } 4580276789Sdim#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz) \ 4581276789Sdim INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_attr_get##what, sz) 4582276789Sdim#define INTERCEPTOR_PTHREAD_MUTEXATTR_GET(what, sz) \ 4583276789Sdim INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_mutexattr_get##what, sz) 4584276789Sdim#define INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(what, sz) \ 4585276789Sdim INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_rwlockattr_get##what, sz) 4586276789Sdim#define INTERCEPTOR_PTHREAD_CONDATTR_GET(what, sz) \ 4587276789Sdim INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_condattr_get##what, sz) 4588276789Sdim#define INTERCEPTOR_PTHREAD_BARRIERATTR_GET(what, sz) \ 4589276789Sdim INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_barrierattr_get##what, sz) 4590274201Sdim#endif 4591274201Sdim 4592274201Sdim#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET 4593274201SdimINTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int)) 4594274201SdimINTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T)) 4595274201SdimINTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int)) 4596274201SdimINTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T)) 4597274201SdimINTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) { 4598274201Sdim void *ctx; 4599274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size); 4600276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4601276789Sdim // its metadata. See 4602296417Sdim // https://github.com/google/sanitizers/issues/321. 4603274201Sdim int res = REAL(pthread_attr_getstack)(attr, addr, size); 4604274201Sdim if (!res) { 4605274201Sdim if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr)); 4606274201Sdim if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size)); 4607274201Sdim } 4608274201Sdim return res; 4609274201Sdim} 4610274201Sdim 4611276789Sdim// We may need to call the real pthread_attr_getstack from the run-time 4612276789Sdim// in sanitizer_common, but we don't want to include the interception headers 4613276789Sdim// there. So, just define this function here. 4614276789Sdimnamespace __sanitizer { 4615276789Sdimextern "C" { 4616276789Sdimint real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) { 4617276789Sdim return REAL(pthread_attr_getstack)(attr, addr, size); 4618276789Sdim} 4619276789Sdim} // extern "C" 4620276789Sdim} // namespace __sanitizer 4621276789Sdim 4622274201Sdim#define INIT_PTHREAD_ATTR_GET \ 4623274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \ 4624274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize); \ 4625274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope); \ 4626274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize); \ 4627274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack); 4628274201Sdim#else 4629274201Sdim#define INIT_PTHREAD_ATTR_GET 4630274201Sdim#endif 4631274201Sdim 4632341825Sdim#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED 4633341825SdimINTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz) 4634341825SdimINTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int)) 4635341825Sdim 4636341825Sdim#define INIT_PTHREAD_ATTR_GET_SCHED \ 4637341825Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam); \ 4638341825Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy); 4639341825Sdim#else 4640341825Sdim#define INIT_PTHREAD_ATTR_GET_SCHED 4641341825Sdim#endif 4642341825Sdim 4643274201Sdim#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED 4644274201SdimINTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int)) 4645274201Sdim 4646274201Sdim#define INIT_PTHREAD_ATTR_GETINHERITSCHED \ 4647274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched); 4648274201Sdim#else 4649274201Sdim#define INIT_PTHREAD_ATTR_GETINHERITSCHED 4650274201Sdim#endif 4651274201Sdim 4652274201Sdim#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP 4653274201SdimINTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize, 4654274201Sdim void *cpuset) { 4655274201Sdim void *ctx; 4656274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize, 4657274201Sdim cpuset); 4658276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4659276789Sdim // its metadata. See 4660296417Sdim // https://github.com/google/sanitizers/issues/321. 4661274201Sdim int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset); 4662274201Sdim if (!res && cpusetsize && cpuset) 4663274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize); 4664274201Sdim return res; 4665274201Sdim} 4666274201Sdim 4667274201Sdim#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \ 4668274201Sdim COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np); 4669274201Sdim#else 4670274201Sdim#define INIT_PTHREAD_ATTR_GETAFFINITY_NP 4671274201Sdim#endif 4672274201Sdim 4673276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED 4674276789SdimINTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int)) 4675276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \ 4676276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared); 4677276789Sdim#else 4678276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETPSHARED 4679276789Sdim#endif 4680276789Sdim 4681276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE 4682276789SdimINTERCEPTOR_PTHREAD_MUTEXATTR_GET(type, sizeof(int)) 4683276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETTYPE \ 4684276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype); 4685276789Sdim#else 4686276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETTYPE 4687276789Sdim#endif 4688276789Sdim 4689276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL 4690276789SdimINTERCEPTOR_PTHREAD_MUTEXATTR_GET(protocol, sizeof(int)) 4691276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL \ 4692276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol); 4693276789Sdim#else 4694276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL 4695276789Sdim#endif 4696276789Sdim 4697276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING 4698276789SdimINTERCEPTOR_PTHREAD_MUTEXATTR_GET(prioceiling, sizeof(int)) 4699276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING \ 4700276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling); 4701276789Sdim#else 4702276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING 4703276789Sdim#endif 4704276789Sdim 4705276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST 4706276789SdimINTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust, sizeof(int)) 4707276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETROBUST \ 4708276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust); 4709276789Sdim#else 4710276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETROBUST 4711276789Sdim#endif 4712276789Sdim 4713276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP 4714276789SdimINTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust_np, sizeof(int)) 4715276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP \ 4716276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np); 4717276789Sdim#else 4718276789Sdim#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP 4719276789Sdim#endif 4720276789Sdim 4721276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED 4722276789SdimINTERCEPTOR_PTHREAD_RWLOCKATTR_GET(pshared, sizeof(int)) 4723276789Sdim#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED \ 4724276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared); 4725276789Sdim#else 4726276789Sdim#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED 4727276789Sdim#endif 4728276789Sdim 4729276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP 4730276789SdimINTERCEPTOR_PTHREAD_RWLOCKATTR_GET(kind_np, sizeof(int)) 4731276789Sdim#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP \ 4732276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np); 4733276789Sdim#else 4734276789Sdim#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP 4735276789Sdim#endif 4736276789Sdim 4737276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED 4738276789SdimINTERCEPTOR_PTHREAD_CONDATTR_GET(pshared, sizeof(int)) 4739276789Sdim#define INIT_PTHREAD_CONDATTR_GETPSHARED \ 4740276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared); 4741276789Sdim#else 4742276789Sdim#define INIT_PTHREAD_CONDATTR_GETPSHARED 4743276789Sdim#endif 4744276789Sdim 4745276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK 4746276789SdimINTERCEPTOR_PTHREAD_CONDATTR_GET(clock, sizeof(int)) 4747276789Sdim#define INIT_PTHREAD_CONDATTR_GETCLOCK \ 4748276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock); 4749276789Sdim#else 4750276789Sdim#define INIT_PTHREAD_CONDATTR_GETCLOCK 4751276789Sdim#endif 4752276789Sdim 4753276789Sdim#if SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED 4754276789SdimINTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android 4755276789Sdim#define INIT_PTHREAD_BARRIERATTR_GETPSHARED \ 4756276789Sdim COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared); 4757276789Sdim#else 4758276789Sdim#define INIT_PTHREAD_BARRIERATTR_GETPSHARED 4759276789Sdim#endif 4760276789Sdim 4761274201Sdim#if SANITIZER_INTERCEPT_TMPNAM 4762274201SdimINTERCEPTOR(char *, tmpnam, char *s) { 4763274201Sdim void *ctx; 4764274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s); 4765274201Sdim char *res = REAL(tmpnam)(s); 4766274201Sdim if (res) { 4767274201Sdim if (s) 4768276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4769276789Sdim // its metadata. See 4770296417Sdim // https://github.com/google/sanitizers/issues/321. 4771274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1); 4772274201Sdim else 4773276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); 4774274201Sdim } 4775274201Sdim return res; 4776274201Sdim} 4777274201Sdim#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam); 4778274201Sdim#else 4779274201Sdim#define INIT_TMPNAM 4780274201Sdim#endif 4781274201Sdim 4782274201Sdim#if SANITIZER_INTERCEPT_TMPNAM_R 4783274201SdimINTERCEPTOR(char *, tmpnam_r, char *s) { 4784274201Sdim void *ctx; 4785274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s); 4786276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4787276789Sdim // its metadata. See 4788296417Sdim // https://github.com/google/sanitizers/issues/321. 4789274201Sdim char *res = REAL(tmpnam_r)(s); 4790274201Sdim if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1); 4791274201Sdim return res; 4792274201Sdim} 4793274201Sdim#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r); 4794274201Sdim#else 4795274201Sdim#define INIT_TMPNAM_R 4796274201Sdim#endif 4797274201Sdim 4798353358Sdim#if SANITIZER_INTERCEPT_TTYNAME 4799353358SdimINTERCEPTOR(char *, ttyname, int fd) { 4800353358Sdim void *ctx; 4801353358Sdim COMMON_INTERCEPTOR_ENTER(ctx, ttyname, fd); 4802353358Sdim char *res = REAL(ttyname)(fd); 4803353358Sdim if (res != nullptr) 4804353358Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); 4805353358Sdim return res; 4806353358Sdim} 4807353358Sdim#define INIT_TTYNAME COMMON_INTERCEPT_FUNCTION(ttyname); 4808353358Sdim#else 4809353358Sdim#define INIT_TTYNAME 4810353358Sdim#endif 4811353358Sdim 4812314564Sdim#if SANITIZER_INTERCEPT_TTYNAME_R 4813314564SdimINTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) { 4814314564Sdim void *ctx; 4815314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize); 4816314564Sdim int res = REAL(ttyname_r)(fd, name, namesize); 4817314564Sdim if (res == 0) 4818314564Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1); 4819314564Sdim return res; 4820314564Sdim} 4821314564Sdim#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r); 4822314564Sdim#else 4823314564Sdim#define INIT_TTYNAME_R 4824314564Sdim#endif 4825314564Sdim 4826274201Sdim#if SANITIZER_INTERCEPT_TEMPNAM 4827274201SdimINTERCEPTOR(char *, tempnam, char *dir, char *pfx) { 4828274201Sdim void *ctx; 4829274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx); 4830274201Sdim if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1); 4831274201Sdim if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1); 4832274201Sdim char *res = REAL(tempnam)(dir, pfx); 4833276789Sdim if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); 4834274201Sdim return res; 4835274201Sdim} 4836274201Sdim#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam); 4837274201Sdim#else 4838274201Sdim#define INIT_TEMPNAM 4839274201Sdim#endif 4840274201Sdim 4841327952Sdim#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && !SANITIZER_NETBSD 4842274201SdimINTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) { 4843274201Sdim void *ctx; 4844274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name); 4845288943Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0); 4846274201Sdim COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name); 4847274201Sdim return REAL(pthread_setname_np)(thread, name); 4848274201Sdim} 4849274201Sdim#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np); 4850327952Sdim#elif SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && SANITIZER_NETBSD 4851327952SdimINTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name, void *arg) { 4852327952Sdim void *ctx; 4853327952Sdim char newname[32]; // PTHREAD_MAX_NAMELEN_NP=32 4854327952Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg); 4855327952Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0); 4856327952Sdim internal_snprintf(newname, sizeof(newname), name, arg); 4857327952Sdim COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, newname); 4858327952Sdim return REAL(pthread_setname_np)(thread, name, arg); 4859327952Sdim} 4860327952Sdim#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np); 4861274201Sdim#else 4862274201Sdim#define INIT_PTHREAD_SETNAME_NP 4863274201Sdim#endif 4864274201Sdim 4865327952Sdim#if SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP 4866327952SdimINTERCEPTOR(int, pthread_getname_np, uptr thread, char *name, SIZE_T len) { 4867327952Sdim void *ctx; 4868327952Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_getname_np, thread, name, len); 4869327952Sdim int res = REAL(pthread_getname_np)(thread, name, len); 4870327952Sdim if (!res) 4871327952Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strnlen(name, len) + 1); 4872327952Sdim return res; 4873327952Sdim} 4874327952Sdim#define INIT_PTHREAD_GETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_getname_np); 4875327952Sdim#else 4876327952Sdim#define INIT_PTHREAD_GETNAME_NP 4877327952Sdim#endif 4878327952Sdim 4879274201Sdim#if SANITIZER_INTERCEPT_SINCOS 4880274201SdimINTERCEPTOR(void, sincos, double x, double *sin, double *cos) { 4881274201Sdim void *ctx; 4882274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos); 4883276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4884276789Sdim // its metadata. See 4885296417Sdim // https://github.com/google/sanitizers/issues/321. 4886274201Sdim REAL(sincos)(x, sin, cos); 4887274201Sdim if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin)); 4888274201Sdim if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos)); 4889274201Sdim} 4890274201SdimINTERCEPTOR(void, sincosf, float x, float *sin, float *cos) { 4891274201Sdim void *ctx; 4892274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos); 4893276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4894276789Sdim // its metadata. See 4895296417Sdim // https://github.com/google/sanitizers/issues/321. 4896274201Sdim REAL(sincosf)(x, sin, cos); 4897274201Sdim if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin)); 4898274201Sdim if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos)); 4899274201Sdim} 4900274201SdimINTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) { 4901274201Sdim void *ctx; 4902274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos); 4903276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4904276789Sdim // its metadata. See 4905296417Sdim // https://github.com/google/sanitizers/issues/321. 4906274201Sdim REAL(sincosl)(x, sin, cos); 4907274201Sdim if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin)); 4908274201Sdim if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos)); 4909274201Sdim} 4910274201Sdim#define INIT_SINCOS \ 4911274201Sdim COMMON_INTERCEPT_FUNCTION(sincos); \ 4912274201Sdim COMMON_INTERCEPT_FUNCTION(sincosf); \ 4913309124Sdim COMMON_INTERCEPT_FUNCTION_LDBL(sincosl); 4914274201Sdim#else 4915274201Sdim#define INIT_SINCOS 4916274201Sdim#endif 4917274201Sdim 4918274201Sdim#if SANITIZER_INTERCEPT_REMQUO 4919274201SdimINTERCEPTOR(double, remquo, double x, double y, int *quo) { 4920274201Sdim void *ctx; 4921274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo); 4922276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4923276789Sdim // its metadata. See 4924296417Sdim // https://github.com/google/sanitizers/issues/321. 4925274201Sdim double res = REAL(remquo)(x, y, quo); 4926274201Sdim if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo)); 4927274201Sdim return res; 4928274201Sdim} 4929274201SdimINTERCEPTOR(float, remquof, float x, float y, int *quo) { 4930274201Sdim void *ctx; 4931274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo); 4932276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4933276789Sdim // its metadata. See 4934296417Sdim // https://github.com/google/sanitizers/issues/321. 4935274201Sdim float res = REAL(remquof)(x, y, quo); 4936274201Sdim if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo)); 4937274201Sdim return res; 4938274201Sdim} 4939344779Sdim#define INIT_REMQUO \ 4940344779Sdim COMMON_INTERCEPT_FUNCTION(remquo); \ 4941344779Sdim COMMON_INTERCEPT_FUNCTION(remquof); 4942344779Sdim#else 4943344779Sdim#define INIT_REMQUO 4944344779Sdim#endif 4945344779Sdim 4946344779Sdim#if SANITIZER_INTERCEPT_REMQUOL 4947274201SdimINTERCEPTOR(long double, remquol, long double x, long double y, int *quo) { 4948274201Sdim void *ctx; 4949274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo); 4950276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 4951276789Sdim // its metadata. See 4952296417Sdim // https://github.com/google/sanitizers/issues/321. 4953274201Sdim long double res = REAL(remquol)(x, y, quo); 4954274201Sdim if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo)); 4955274201Sdim return res; 4956274201Sdim} 4957344779Sdim#define INIT_REMQUOL \ 4958309124Sdim COMMON_INTERCEPT_FUNCTION_LDBL(remquol); 4959274201Sdim#else 4960344779Sdim#define INIT_REMQUOL 4961274201Sdim#endif 4962274201Sdim 4963274201Sdim#if SANITIZER_INTERCEPT_LGAMMA 4964274201Sdimextern int signgam; 4965274201SdimINTERCEPTOR(double, lgamma, double x) { 4966274201Sdim void *ctx; 4967274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x); 4968274201Sdim double res = REAL(lgamma)(x); 4969274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam)); 4970274201Sdim return res; 4971274201Sdim} 4972274201SdimINTERCEPTOR(float, lgammaf, float x) { 4973274201Sdim void *ctx; 4974274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x); 4975274201Sdim float res = REAL(lgammaf)(x); 4976274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam)); 4977274201Sdim return res; 4978274201Sdim} 4979344779Sdim#define INIT_LGAMMA \ 4980344779Sdim COMMON_INTERCEPT_FUNCTION(lgamma); \ 4981344779Sdim COMMON_INTERCEPT_FUNCTION(lgammaf); 4982344779Sdim#else 4983344779Sdim#define INIT_LGAMMA 4984344779Sdim#endif 4985344779Sdim 4986344779Sdim#if SANITIZER_INTERCEPT_LGAMMAL 4987274201SdimINTERCEPTOR(long double, lgammal, long double x) { 4988274201Sdim void *ctx; 4989274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x); 4990274201Sdim long double res = REAL(lgammal)(x); 4991274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam)); 4992274201Sdim return res; 4993274201Sdim} 4994344779Sdim#define INIT_LGAMMAL \ 4995309124Sdim COMMON_INTERCEPT_FUNCTION_LDBL(lgammal); 4996274201Sdim#else 4997344779Sdim#define INIT_LGAMMAL 4998274201Sdim#endif 4999274201Sdim 5000274201Sdim#if SANITIZER_INTERCEPT_LGAMMA_R 5001274201SdimINTERCEPTOR(double, lgamma_r, double x, int *signp) { 5002274201Sdim void *ctx; 5003274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp); 5004276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5005276789Sdim // its metadata. See 5006296417Sdim // https://github.com/google/sanitizers/issues/321. 5007274201Sdim double res = REAL(lgamma_r)(x, signp); 5008274201Sdim if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp)); 5009274201Sdim return res; 5010274201Sdim} 5011274201SdimINTERCEPTOR(float, lgammaf_r, float x, int *signp) { 5012274201Sdim void *ctx; 5013274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp); 5014276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5015276789Sdim // its metadata. See 5016296417Sdim // https://github.com/google/sanitizers/issues/321. 5017274201Sdim float res = REAL(lgammaf_r)(x, signp); 5018274201Sdim if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp)); 5019274201Sdim return res; 5020274201Sdim} 5021276789Sdim#define INIT_LGAMMA_R \ 5022276789Sdim COMMON_INTERCEPT_FUNCTION(lgamma_r); \ 5023276789Sdim COMMON_INTERCEPT_FUNCTION(lgammaf_r); 5024276789Sdim#else 5025276789Sdim#define INIT_LGAMMA_R 5026276789Sdim#endif 5027276789Sdim 5028276789Sdim#if SANITIZER_INTERCEPT_LGAMMAL_R 5029274201SdimINTERCEPTOR(long double, lgammal_r, long double x, int *signp) { 5030274201Sdim void *ctx; 5031274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp); 5032276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5033276789Sdim // its metadata. See 5034296417Sdim // https://github.com/google/sanitizers/issues/321. 5035274201Sdim long double res = REAL(lgammal_r)(x, signp); 5036274201Sdim if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp)); 5037274201Sdim return res; 5038274201Sdim} 5039309124Sdim#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r); 5040274201Sdim#else 5041276789Sdim#define INIT_LGAMMAL_R 5042274201Sdim#endif 5043274201Sdim 5044274201Sdim#if SANITIZER_INTERCEPT_DRAND48_R 5045274201SdimINTERCEPTOR(int, drand48_r, void *buffer, double *result) { 5046274201Sdim void *ctx; 5047274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result); 5048276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5049276789Sdim // its metadata. See 5050296417Sdim // https://github.com/google/sanitizers/issues/321. 5051274201Sdim int res = REAL(drand48_r)(buffer, result); 5052274201Sdim if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 5053274201Sdim return res; 5054274201Sdim} 5055274201SdimINTERCEPTOR(int, lrand48_r, void *buffer, long *result) { 5056274201Sdim void *ctx; 5057274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result); 5058276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5059276789Sdim // its metadata. See 5060296417Sdim // https://github.com/google/sanitizers/issues/321. 5061274201Sdim int res = REAL(lrand48_r)(buffer, result); 5062274201Sdim if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); 5063274201Sdim return res; 5064274201Sdim} 5065274201Sdim#define INIT_DRAND48_R \ 5066274201Sdim COMMON_INTERCEPT_FUNCTION(drand48_r); \ 5067274201Sdim COMMON_INTERCEPT_FUNCTION(lrand48_r); 5068274201Sdim#else 5069274201Sdim#define INIT_DRAND48_R 5070274201Sdim#endif 5071274201Sdim 5072276789Sdim#if SANITIZER_INTERCEPT_RAND_R 5073276789SdimINTERCEPTOR(int, rand_r, unsigned *seedp) { 5074276789Sdim void *ctx; 5075276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp); 5076276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp)); 5077276789Sdim return REAL(rand_r)(seedp); 5078276789Sdim} 5079276789Sdim#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r); 5080276789Sdim#else 5081276789Sdim#define INIT_RAND_R 5082276789Sdim#endif 5083276789Sdim 5084274201Sdim#if SANITIZER_INTERCEPT_GETLINE 5085274201SdimINTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) { 5086274201Sdim void *ctx; 5087274201Sdim COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream); 5088276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5089276789Sdim // its metadata. See 5090296417Sdim // https://github.com/google/sanitizers/issues/321. 5091274201Sdim SSIZE_T res = REAL(getline)(lineptr, n, stream); 5092274201Sdim if (res > 0) { 5093274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr)); 5094274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); 5095274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1); 5096274201Sdim } 5097274201Sdim return res; 5098274201Sdim} 5099288943Sdim 5100288943Sdim// FIXME: under ASan the call below may write to freed memory and corrupt its 5101288943Sdim// metadata. See 5102296417Sdim// https://github.com/google/sanitizers/issues/321. 5103288943Sdim#define GETDELIM_INTERCEPTOR_IMPL(vname) \ 5104288943Sdim { \ 5105288943Sdim void *ctx; \ 5106288943Sdim COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream); \ 5107288943Sdim SSIZE_T res = REAL(vname)(lineptr, n, delim, stream); \ 5108288943Sdim if (res > 0) { \ 5109288943Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr)); \ 5110288943Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); \ 5111288943Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1); \ 5112288943Sdim } \ 5113288943Sdim return res; \ 5114288943Sdim } 5115288943Sdim 5116276789SdimINTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim, 5117288943Sdim void *stream) 5118288943SdimGETDELIM_INTERCEPTOR_IMPL(__getdelim) 5119288943Sdim 5120288943Sdim// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor 5121288943Sdim// with its own body. 5122276789SdimINTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim, 5123288943Sdim void *stream) 5124288943SdimGETDELIM_INTERCEPTOR_IMPL(getdelim) 5125288943Sdim 5126276789Sdim#define INIT_GETLINE \ 5127276789Sdim COMMON_INTERCEPT_FUNCTION(getline); \ 5128276789Sdim COMMON_INTERCEPT_FUNCTION(__getdelim); \ 5129274201Sdim COMMON_INTERCEPT_FUNCTION(getdelim); 5130274201Sdim#else 5131274201Sdim#define INIT_GETLINE 5132274201Sdim#endif 5133274201Sdim 5134276789Sdim#if SANITIZER_INTERCEPT_ICONV 5135276789SdimINTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft, 5136276789Sdim char **outbuf, SIZE_T *outbytesleft) { 5137276789Sdim void *ctx; 5138276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf, 5139276789Sdim outbytesleft); 5140276789Sdim if (inbytesleft) 5141276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, inbytesleft, sizeof(*inbytesleft)); 5142276789Sdim if (inbuf && inbytesleft) 5143276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, *inbuf, *inbytesleft); 5144276789Sdim if (outbytesleft) 5145276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, outbytesleft, sizeof(*outbytesleft)); 5146296417Sdim void *outbuf_orig = outbuf ? *outbuf : nullptr; 5147276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5148276789Sdim // its metadata. See 5149296417Sdim // https://github.com/google/sanitizers/issues/321. 5150276789Sdim SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft); 5151321369Sdim if (outbuf && *outbuf > outbuf_orig) { 5152276789Sdim SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig; 5153276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz); 5154276789Sdim } 5155276789Sdim return res; 5156276789Sdim} 5157276789Sdim#define INIT_ICONV COMMON_INTERCEPT_FUNCTION(iconv); 5158276789Sdim#else 5159276789Sdim#define INIT_ICONV 5160276789Sdim#endif 5161276789Sdim 5162276789Sdim#if SANITIZER_INTERCEPT_TIMES 5163276789SdimINTERCEPTOR(__sanitizer_clock_t, times, void *tms) { 5164276789Sdim void *ctx; 5165276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, times, tms); 5166276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5167276789Sdim // its metadata. See 5168296417Sdim // https://github.com/google/sanitizers/issues/321. 5169276789Sdim __sanitizer_clock_t res = REAL(times)(tms); 5170276789Sdim if (res != (__sanitizer_clock_t)-1 && tms) 5171276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz); 5172276789Sdim return res; 5173276789Sdim} 5174276789Sdim#define INIT_TIMES COMMON_INTERCEPT_FUNCTION(times); 5175276789Sdim#else 5176276789Sdim#define INIT_TIMES 5177276789Sdim#endif 5178276789Sdim 5179276789Sdim#if SANITIZER_INTERCEPT_TLS_GET_ADDR 5180309124Sdim#if !SANITIZER_S390 5181276789Sdim#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr) 5182280031Sdim// If you see any crashes around this functions, there are 2 known issues with 5183280031Sdim// it: 1. __tls_get_addr can be called with mis-aligned stack due to: 5184280031Sdim// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066 5185280031Sdim// 2. It can be called recursively if sanitizer code uses __tls_get_addr 5186280031Sdim// to access thread local variables (it should not happen normally, 5187280031Sdim// because sanitizers use initial-exec tls model). 5188276789SdimINTERCEPTOR(void *, __tls_get_addr, void *arg) { 5189276789Sdim void *ctx; 5190276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg); 5191276789Sdim void *res = REAL(__tls_get_addr)(arg); 5192288943Sdim uptr tls_begin, tls_end; 5193288943Sdim COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end); 5194288943Sdim DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end); 5195276789Sdim if (dtv) { 5196276789Sdim // New DTLS block has been allocated. 5197276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size); 5198276789Sdim } 5199276789Sdim return res; 5200276789Sdim} 5201309124Sdim#if SANITIZER_PPC 5202309124Sdim// On PowerPC, we also need to intercept __tls_get_addr_opt, which has 5203309124Sdim// mostly the same semantics as __tls_get_addr, but its presence enables 5204309124Sdim// some optimizations in linker (which are safe to ignore here). 5205309124Sdimextern "C" __attribute__((alias("__interceptor___tls_get_addr"), 5206309124Sdim visibility("default"))) 5207309124Sdimvoid *__tls_get_addr_opt(void *arg); 5208309124Sdim#endif 5209309124Sdim#else // SANITIZER_S390 5210309124Sdim// On s390, we have to intercept two functions here: 5211309124Sdim// - __tls_get_addr_internal, which is a glibc-internal function that is like 5212309124Sdim// the usual __tls_get_addr, but returns a TP-relative offset instead of 5213309124Sdim// a proper pointer. It is used by dlsym for TLS symbols. 5214309124Sdim// - __tls_get_offset, which is like the above, but also takes a GOT-relative 5215309124Sdim// descriptor offset as an argument instead of a pointer. GOT address 5216309124Sdim// is passed in r12, so it's necessary to write it in assembly. This is 5217309124Sdim// the function used by the compiler. 5218321369Sdimextern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg)); 5219321369Sdim#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset) 5220321369SdimDEFINE_REAL(uptr, __tls_get_offset, void *arg) 5221321369Sdimextern "C" uptr __tls_get_offset(void *arg); 5222321369Sdimextern "C" uptr __interceptor___tls_get_offset(void *arg); 5223309124SdimINTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { 5224309124Sdim void *ctx; 5225309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg); 5226321369Sdim uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset)); 5227309124Sdim uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer()); 5228309124Sdim void *ptr = reinterpret_cast<void *>(res + tp); 5229309124Sdim uptr tls_begin, tls_end; 5230309124Sdim COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end); 5231309124Sdim DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end); 5232309124Sdim if (dtv) { 5233309124Sdim // New DTLS block has been allocated. 5234309124Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size); 5235309124Sdim } 5236309124Sdim return res; 5237309124Sdim} 5238321369Sdim// We need a hidden symbol aliasing the above, so that we can jump 5239309124Sdim// directly to it from the assembly below. 5240309124Sdimextern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"), 5241321369Sdim visibility("hidden"))) 5242321369Sdimuptr __tls_get_addr_hidden(void *arg); 5243309124Sdim// Now carefully intercept __tls_get_offset. 5244309124Sdimasm( 5245309124Sdim ".text\n" 5246309124Sdim// The __intercept_ version has to exist, so that gen_dynamic_list.py 5247309124Sdim// exports our symbol. 5248321369Sdim ".weak __tls_get_offset\n" 5249321369Sdim ".type __tls_get_offset, @function\n" 5250321369Sdim "__tls_get_offset:\n" 5251309124Sdim ".global __interceptor___tls_get_offset\n" 5252321369Sdim ".type __interceptor___tls_get_offset, @function\n" 5253309124Sdim "__interceptor___tls_get_offset:\n" 5254309124Sdim#ifdef __s390x__ 5255309124Sdim "la %r2, 0(%r2,%r12)\n" 5256321369Sdim "jg __tls_get_addr_hidden\n" 5257276789Sdim#else 5258309124Sdim "basr %r3,0\n" 5259309124Sdim "0: la %r2,0(%r2,%r12)\n" 5260309124Sdim "l %r4,1f-0b(%r3)\n" 5261309124Sdim "b 0(%r4,%r3)\n" 5262321369Sdim "1: .long __tls_get_addr_hidden - 0b\n" 5263309124Sdim#endif 5264321369Sdim ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n" 5265321369Sdim// Assembly wrapper to call REAL(__tls_get_offset)(arg) 5266321369Sdim ".type __tls_get_offset_wrapper, @function\n" 5267321369Sdim "__tls_get_offset_wrapper:\n" 5268321369Sdim#ifdef __s390x__ 5269321369Sdim "sgr %r2,%r12\n" 5270321369Sdim#else 5271321369Sdim "sr %r2,%r12\n" 5272321369Sdim#endif 5273321369Sdim "br %r3\n" 5274321369Sdim ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n" 5275309124Sdim); 5276309124Sdim#endif // SANITIZER_S390 5277309124Sdim#else 5278276789Sdim#define INIT_TLS_GET_ADDR 5279276789Sdim#endif 5280276789Sdim 5281276789Sdim#if SANITIZER_INTERCEPT_LISTXATTR 5282276789SdimINTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) { 5283276789Sdim void *ctx; 5284276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size); 5285276789Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 5286276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5287276789Sdim // its metadata. See 5288296417Sdim // https://github.com/google/sanitizers/issues/321. 5289276789Sdim SSIZE_T res = REAL(listxattr)(path, list, size); 5290276789Sdim // Here and below, size == 0 is a special case where nothing is written to the 5291276789Sdim // buffer, and res contains the desired buffer size. 5292276789Sdim if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res); 5293276789Sdim return res; 5294276789Sdim} 5295276789SdimINTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) { 5296276789Sdim void *ctx; 5297276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size); 5298276789Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 5299276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5300276789Sdim // its metadata. See 5301296417Sdim // https://github.com/google/sanitizers/issues/321. 5302276789Sdim SSIZE_T res = REAL(llistxattr)(path, list, size); 5303276789Sdim if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res); 5304276789Sdim return res; 5305276789Sdim} 5306276789SdimINTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) { 5307276789Sdim void *ctx; 5308276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size); 5309276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5310276789Sdim // its metadata. See 5311296417Sdim // https://github.com/google/sanitizers/issues/321. 5312276789Sdim SSIZE_T res = REAL(flistxattr)(fd, list, size); 5313276789Sdim if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res); 5314276789Sdim return res; 5315276789Sdim} 5316276789Sdim#define INIT_LISTXATTR \ 5317276789Sdim COMMON_INTERCEPT_FUNCTION(listxattr); \ 5318276789Sdim COMMON_INTERCEPT_FUNCTION(llistxattr); \ 5319276789Sdim COMMON_INTERCEPT_FUNCTION(flistxattr); 5320276789Sdim#else 5321276789Sdim#define INIT_LISTXATTR 5322276789Sdim#endif 5323276789Sdim 5324276789Sdim#if SANITIZER_INTERCEPT_GETXATTR 5325276789SdimINTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value, 5326276789Sdim SIZE_T size) { 5327276789Sdim void *ctx; 5328276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size); 5329276789Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 5330276789Sdim if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 5331276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5332276789Sdim // its metadata. See 5333296417Sdim // https://github.com/google/sanitizers/issues/321. 5334276789Sdim SSIZE_T res = REAL(getxattr)(path, name, value, size); 5335276789Sdim if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res); 5336276789Sdim return res; 5337276789Sdim} 5338276789SdimINTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value, 5339276789Sdim SIZE_T size) { 5340276789Sdim void *ctx; 5341276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size); 5342276789Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 5343276789Sdim if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 5344276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5345276789Sdim // its metadata. See 5346296417Sdim // https://github.com/google/sanitizers/issues/321. 5347276789Sdim SSIZE_T res = REAL(lgetxattr)(path, name, value, size); 5348276789Sdim if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res); 5349276789Sdim return res; 5350276789Sdim} 5351276789SdimINTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value, 5352276789Sdim SIZE_T size) { 5353276789Sdim void *ctx; 5354276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size); 5355276789Sdim if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 5356276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5357276789Sdim // its metadata. See 5358296417Sdim // https://github.com/google/sanitizers/issues/321. 5359276789Sdim SSIZE_T res = REAL(fgetxattr)(fd, name, value, size); 5360276789Sdim if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res); 5361276789Sdim return res; 5362276789Sdim} 5363276789Sdim#define INIT_GETXATTR \ 5364276789Sdim COMMON_INTERCEPT_FUNCTION(getxattr); \ 5365276789Sdim COMMON_INTERCEPT_FUNCTION(lgetxattr); \ 5366276789Sdim COMMON_INTERCEPT_FUNCTION(fgetxattr); 5367276789Sdim#else 5368276789Sdim#define INIT_GETXATTR 5369276789Sdim#endif 5370276789Sdim 5371276789Sdim#if SANITIZER_INTERCEPT_GETRESID 5372276789SdimINTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) { 5373276789Sdim void *ctx; 5374276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid); 5375276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5376276789Sdim // its metadata. See 5377296417Sdim // https://github.com/google/sanitizers/issues/321. 5378276789Sdim int res = REAL(getresuid)(ruid, euid, suid); 5379276789Sdim if (res >= 0) { 5380276789Sdim if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz); 5381276789Sdim if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz); 5382276789Sdim if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz); 5383276789Sdim } 5384276789Sdim return res; 5385276789Sdim} 5386276789SdimINTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) { 5387276789Sdim void *ctx; 5388276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid); 5389276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5390276789Sdim // its metadata. See 5391296417Sdim // https://github.com/google/sanitizers/issues/321. 5392276789Sdim int res = REAL(getresgid)(rgid, egid, sgid); 5393276789Sdim if (res >= 0) { 5394276789Sdim if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz); 5395276789Sdim if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz); 5396276789Sdim if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz); 5397276789Sdim } 5398276789Sdim return res; 5399276789Sdim} 5400276789Sdim#define INIT_GETRESID \ 5401276789Sdim COMMON_INTERCEPT_FUNCTION(getresuid); \ 5402276789Sdim COMMON_INTERCEPT_FUNCTION(getresgid); 5403276789Sdim#else 5404276789Sdim#define INIT_GETRESID 5405276789Sdim#endif 5406276789Sdim 5407276789Sdim#if SANITIZER_INTERCEPT_GETIFADDRS 5408276789Sdim// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to 5409276789Sdim// intercept freeifaddrs(). If that ceases to be the case, we might need to 5410276789Sdim// intercept it to poison the memory again. 5411276789SdimINTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) { 5412276789Sdim void *ctx; 5413276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap); 5414276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5415276789Sdim // its metadata. See 5416296417Sdim // https://github.com/google/sanitizers/issues/321. 5417276789Sdim int res = REAL(getifaddrs)(ifap); 5418276789Sdim if (res == 0 && ifap) { 5419276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *)); 5420276789Sdim __sanitizer_ifaddrs *p = *ifap; 5421276789Sdim while (p) { 5422276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs)); 5423276789Sdim if (p->ifa_name) 5424276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name, 5425276789Sdim REAL(strlen)(p->ifa_name) + 1); 5426276789Sdim if (p->ifa_addr) 5427276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz); 5428276789Sdim if (p->ifa_netmask) 5429276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz); 5430276789Sdim // On Linux this is a union, but the other member also points to a 5431276789Sdim // struct sockaddr, so the following is sufficient. 5432276789Sdim if (p->ifa_dstaddr) 5433276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz); 5434276789Sdim // FIXME(smatveev): Unpoison p->ifa_data as well. 5435276789Sdim p = p->ifa_next; 5436276789Sdim } 5437276789Sdim } 5438276789Sdim return res; 5439276789Sdim} 5440276789Sdim#define INIT_GETIFADDRS \ 5441276789Sdim COMMON_INTERCEPT_FUNCTION(getifaddrs); 5442276789Sdim#else 5443276789Sdim#define INIT_GETIFADDRS 5444276789Sdim#endif 5445276789Sdim 5446276789Sdim#if SANITIZER_INTERCEPT_IF_INDEXTONAME 5447276789SdimINTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) { 5448276789Sdim void *ctx; 5449276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname); 5450276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5451276789Sdim // its metadata. See 5452296417Sdim // https://github.com/google/sanitizers/issues/321. 5453276789Sdim char *res = REAL(if_indextoname)(ifindex, ifname); 5454276789Sdim if (res && ifname) 5455276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1); 5456276789Sdim return res; 5457276789Sdim} 5458276789SdimINTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) { 5459276789Sdim void *ctx; 5460276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname); 5461276789Sdim if (ifname) 5462276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1); 5463276789Sdim return REAL(if_nametoindex)(ifname); 5464276789Sdim} 5465276789Sdim#define INIT_IF_INDEXTONAME \ 5466276789Sdim COMMON_INTERCEPT_FUNCTION(if_indextoname); \ 5467276789Sdim COMMON_INTERCEPT_FUNCTION(if_nametoindex); 5468276789Sdim#else 5469276789Sdim#define INIT_IF_INDEXTONAME 5470276789Sdim#endif 5471276789Sdim 5472276789Sdim#if SANITIZER_INTERCEPT_CAPGET 5473276789SdimINTERCEPTOR(int, capget, void *hdrp, void *datap) { 5474276789Sdim void *ctx; 5475276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap); 5476276789Sdim if (hdrp) 5477276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz); 5478276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5479276789Sdim // its metadata. See 5480296417Sdim // https://github.com/google/sanitizers/issues/321. 5481276789Sdim int res = REAL(capget)(hdrp, datap); 5482276789Sdim if (res == 0 && datap) 5483276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz); 5484276789Sdim // We can also return -1 and write to hdrp->version if the version passed in 5485276789Sdim // hdrp->version is unsupported. But that's not a trivial condition to check, 5486276789Sdim // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent. 5487276789Sdim return res; 5488276789Sdim} 5489276789SdimINTERCEPTOR(int, capset, void *hdrp, const void *datap) { 5490276789Sdim void *ctx; 5491276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap); 5492276789Sdim if (hdrp) 5493276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz); 5494276789Sdim if (datap) 5495276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz); 5496276789Sdim return REAL(capset)(hdrp, datap); 5497276789Sdim} 5498276789Sdim#define INIT_CAPGET \ 5499276789Sdim COMMON_INTERCEPT_FUNCTION(capget); \ 5500276789Sdim COMMON_INTERCEPT_FUNCTION(capset); 5501276789Sdim#else 5502276789Sdim#define INIT_CAPGET 5503276789Sdim#endif 5504276789Sdim 5505276789Sdim#if SANITIZER_INTERCEPT_AEABI_MEM 5506276789SdimINTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) { 5507314564Sdim void *ctx; 5508314564Sdim COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); 5509276789Sdim} 5510314564Sdim 5511276789SdimINTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) { 5512314564Sdim void *ctx; 5513314564Sdim COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); 5514276789Sdim} 5515314564Sdim 5516276789SdimINTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) { 5517314564Sdim void *ctx; 5518314564Sdim COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); 5519276789Sdim} 5520314564Sdim 5521276789SdimINTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) { 5522314564Sdim void *ctx; 5523314564Sdim COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); 5524276789Sdim} 5525314564Sdim 5526276789SdimINTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) { 5527314564Sdim void *ctx; 5528314564Sdim COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); 5529276789Sdim} 5530314564Sdim 5531276789SdimINTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) { 5532314564Sdim void *ctx; 5533314564Sdim COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); 5534276789Sdim} 5535314564Sdim 5536276789Sdim// Note the argument order. 5537276789SdimINTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) { 5538314564Sdim void *ctx; 5539314564Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); 5540276789Sdim} 5541314564Sdim 5542276789SdimINTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) { 5543314564Sdim void *ctx; 5544314564Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); 5545276789Sdim} 5546314564Sdim 5547276789SdimINTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) { 5548314564Sdim void *ctx; 5549314564Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); 5550276789Sdim} 5551314564Sdim 5552276789SdimINTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) { 5553314564Sdim void *ctx; 5554314564Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); 5555276789Sdim} 5556314564Sdim 5557276789SdimINTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) { 5558314564Sdim void *ctx; 5559314564Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); 5560276789Sdim} 5561314564Sdim 5562276789SdimINTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) { 5563314564Sdim void *ctx; 5564314564Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); 5565276789Sdim} 5566314564Sdim 5567276789Sdim#define INIT_AEABI_MEM \ 5568276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \ 5569276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \ 5570276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \ 5571276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \ 5572276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \ 5573276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \ 5574276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \ 5575276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \ 5576276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \ 5577276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \ 5578276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \ 5579276789Sdim COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8); 5580276789Sdim#else 5581276789Sdim#define INIT_AEABI_MEM 5582276789Sdim#endif // SANITIZER_INTERCEPT_AEABI_MEM 5583276789Sdim 5584276789Sdim#if SANITIZER_INTERCEPT___BZERO 5585276789SdimINTERCEPTOR(void *, __bzero, void *block, uptr size) { 5586314564Sdim void *ctx; 5587314564Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); 5588276789Sdim} 5589276789Sdim#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero); 5590276789Sdim#else 5591276789Sdim#define INIT___BZERO 5592276789Sdim#endif // SANITIZER_INTERCEPT___BZERO 5593276789Sdim 5594353358Sdim#if SANITIZER_INTERCEPT_BZERO 5595353358SdimINTERCEPTOR(void *, bzero, void *block, uptr size) { 5596353358Sdim void *ctx; 5597353358Sdim COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); 5598353358Sdim} 5599353358Sdim#define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero); 5600353358Sdim#else 5601353358Sdim#define INIT_BZERO 5602353358Sdim#endif // SANITIZER_INTERCEPT_BZERO 5603353358Sdim 5604276789Sdim#if SANITIZER_INTERCEPT_FTIME 5605276789SdimINTERCEPTOR(int, ftime, __sanitizer_timeb *tp) { 5606276789Sdim void *ctx; 5607276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp); 5608276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5609276789Sdim // its metadata. See 5610296417Sdim // https://github.com/google/sanitizers/issues/321. 5611276789Sdim int res = REAL(ftime)(tp); 5612276789Sdim if (tp) 5613276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp)); 5614276789Sdim return res; 5615276789Sdim} 5616276789Sdim#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime); 5617276789Sdim#else 5618276789Sdim#define INIT_FTIME 5619276789Sdim#endif // SANITIZER_INTERCEPT_FTIME 5620276789Sdim 5621276789Sdim#if SANITIZER_INTERCEPT_XDR 5622276789SdimINTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr, 5623276789Sdim unsigned size, int op) { 5624276789Sdim void *ctx; 5625276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op); 5626276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5627276789Sdim // its metadata. See 5628296417Sdim // https://github.com/google/sanitizers/issues/321. 5629276789Sdim REAL(xdrmem_create)(xdrs, addr, size, op); 5630276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs)); 5631276789Sdim if (op == __sanitizer_XDR_ENCODE) { 5632276789Sdim // It's not obvious how much data individual xdr_ routines write. 5633276789Sdim // Simply unpoison the entire target buffer in advance. 5634276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size); 5635276789Sdim } 5636276789Sdim} 5637276789Sdim 5638276789SdimINTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) { 5639276789Sdim void *ctx; 5640276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op); 5641276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5642276789Sdim // its metadata. See 5643296417Sdim // https://github.com/google/sanitizers/issues/321. 5644276789Sdim REAL(xdrstdio_create)(xdrs, file, op); 5645276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs)); 5646276789Sdim} 5647276789Sdim 5648276789Sdim// FIXME: under ASan the call below may write to freed memory and corrupt 5649276789Sdim// its metadata. See 5650296417Sdim// https://github.com/google/sanitizers/issues/321. 5651276789Sdim#define XDR_INTERCEPTOR(F, T) \ 5652276789Sdim INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) { \ 5653276789Sdim void *ctx; \ 5654276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p); \ 5655276789Sdim if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) \ 5656276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p)); \ 5657276789Sdim int res = REAL(F)(xdrs, p); \ 5658276789Sdim if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \ 5659276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \ 5660276789Sdim return res; \ 5661276789Sdim } 5662276789Sdim 5663276789SdimXDR_INTERCEPTOR(xdr_short, short) 5664276789SdimXDR_INTERCEPTOR(xdr_u_short, unsigned short) 5665276789SdimXDR_INTERCEPTOR(xdr_int, int) 5666276789SdimXDR_INTERCEPTOR(xdr_u_int, unsigned) 5667276789SdimXDR_INTERCEPTOR(xdr_long, long) 5668276789SdimXDR_INTERCEPTOR(xdr_u_long, unsigned long) 5669276789SdimXDR_INTERCEPTOR(xdr_hyper, long long) 5670276789SdimXDR_INTERCEPTOR(xdr_u_hyper, unsigned long long) 5671276789SdimXDR_INTERCEPTOR(xdr_longlong_t, long long) 5672276789SdimXDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long) 5673276789SdimXDR_INTERCEPTOR(xdr_int8_t, u8) 5674276789SdimXDR_INTERCEPTOR(xdr_uint8_t, u8) 5675276789SdimXDR_INTERCEPTOR(xdr_int16_t, u16) 5676276789SdimXDR_INTERCEPTOR(xdr_uint16_t, u16) 5677276789SdimXDR_INTERCEPTOR(xdr_int32_t, u32) 5678276789SdimXDR_INTERCEPTOR(xdr_uint32_t, u32) 5679276789SdimXDR_INTERCEPTOR(xdr_int64_t, u64) 5680276789SdimXDR_INTERCEPTOR(xdr_uint64_t, u64) 5681276789SdimXDR_INTERCEPTOR(xdr_quad_t, long long) 5682276789SdimXDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long) 5683276789SdimXDR_INTERCEPTOR(xdr_bool, bool) 5684276789SdimXDR_INTERCEPTOR(xdr_enum, int) 5685276789SdimXDR_INTERCEPTOR(xdr_char, char) 5686276789SdimXDR_INTERCEPTOR(xdr_u_char, unsigned char) 5687276789SdimXDR_INTERCEPTOR(xdr_float, float) 5688276789SdimXDR_INTERCEPTOR(xdr_double, double) 5689276789Sdim 5690276789Sdim// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer, 5691276789Sdim// wrapstring, sizeof 5692276789Sdim 5693276789SdimINTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep, 5694276789Sdim unsigned maxsize) { 5695276789Sdim void *ctx; 5696276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize); 5697276789Sdim if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) { 5698276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p)); 5699276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep)); 5700276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep); 5701276789Sdim } 5702276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5703276789Sdim // its metadata. See 5704296417Sdim // https://github.com/google/sanitizers/issues/321. 5705276789Sdim int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize); 5706276789Sdim if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) { 5707276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); 5708276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep)); 5709276789Sdim if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep); 5710276789Sdim } 5711276789Sdim return res; 5712276789Sdim} 5713276789Sdim 5714276789SdimINTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p, 5715276789Sdim unsigned maxsize) { 5716276789Sdim void *ctx; 5717276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize); 5718276789Sdim if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) { 5719276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p)); 5720276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1); 5721276789Sdim } 5722276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5723276789Sdim // its metadata. See 5724296417Sdim // https://github.com/google/sanitizers/issues/321. 5725276789Sdim int res = REAL(xdr_string)(xdrs, p, maxsize); 5726276789Sdim if (p && xdrs->x_op == __sanitizer_XDR_DECODE) { 5727276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); 5728276789Sdim if (res && *p) 5729276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1); 5730276789Sdim } 5731276789Sdim return res; 5732276789Sdim} 5733276789Sdim 5734276789Sdim#define INIT_XDR \ 5735276789Sdim COMMON_INTERCEPT_FUNCTION(xdrmem_create); \ 5736276789Sdim COMMON_INTERCEPT_FUNCTION(xdrstdio_create); \ 5737276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_short); \ 5738276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_u_short); \ 5739276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_int); \ 5740276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_u_int); \ 5741276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_long); \ 5742276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_u_long); \ 5743276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_hyper); \ 5744276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_u_hyper); \ 5745276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_longlong_t); \ 5746276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \ 5747276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_int8_t); \ 5748276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_uint8_t); \ 5749276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_int16_t); \ 5750276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_uint16_t); \ 5751276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_int32_t); \ 5752276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_uint32_t); \ 5753276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_int64_t); \ 5754276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_uint64_t); \ 5755276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_quad_t); \ 5756276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t); \ 5757276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_bool); \ 5758276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_enum); \ 5759276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_char); \ 5760276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_u_char); \ 5761276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_float); \ 5762276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_double); \ 5763276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_bytes); \ 5764276789Sdim COMMON_INTERCEPT_FUNCTION(xdr_string); 5765276789Sdim#else 5766276789Sdim#define INIT_XDR 5767276789Sdim#endif // SANITIZER_INTERCEPT_XDR 5768276789Sdim 5769276789Sdim#if SANITIZER_INTERCEPT_TSEARCH 5770276789SdimINTERCEPTOR(void *, tsearch, void *key, void **rootp, 5771276789Sdim int (*compar)(const void *, const void *)) { 5772276789Sdim void *ctx; 5773276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar); 5774276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5775276789Sdim // its metadata. See 5776296417Sdim // https://github.com/google/sanitizers/issues/321. 5777276789Sdim void *res = REAL(tsearch)(key, rootp, compar); 5778276789Sdim if (res && *(void **)res == key) 5779276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *)); 5780276789Sdim return res; 5781276789Sdim} 5782276789Sdim#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch); 5783276789Sdim#else 5784276789Sdim#define INIT_TSEARCH 5785276789Sdim#endif 5786276789Sdim 5787276789Sdim#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \ 5788276789Sdim SANITIZER_INTERCEPT_OPEN_MEMSTREAM 5789276789Sdimvoid unpoison_file(__sanitizer_FILE *fp) { 5790276789Sdim#if SANITIZER_HAS_STRUCT_FILE 5791276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp)); 5792344779Sdim#if SANITIZER_NETBSD 5793344779Sdim if (fp->_bf._base && fp->_bf._size > 0) 5794344779Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_bf._base, 5795344779Sdim fp->_bf._size); 5796344779Sdim#else 5797276789Sdim if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end) 5798276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base, 5799276789Sdim fp->_IO_read_end - fp->_IO_read_base); 5800344779Sdim#endif 5801276789Sdim#endif // SANITIZER_HAS_STRUCT_FILE 5802276789Sdim} 5803276789Sdim#endif 5804276789Sdim 5805276789Sdim#if SANITIZER_INTERCEPT_LIBIO_INTERNALS 5806276789Sdim// These guys are called when a .c source is built with -O2. 5807276789SdimINTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) { 5808276789Sdim void *ctx; 5809276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp); 5810276789Sdim int res = REAL(__uflow)(fp); 5811276789Sdim unpoison_file(fp); 5812276789Sdim return res; 5813276789Sdim} 5814276789SdimINTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) { 5815276789Sdim void *ctx; 5816276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp); 5817276789Sdim int res = REAL(__underflow)(fp); 5818276789Sdim unpoison_file(fp); 5819276789Sdim return res; 5820276789Sdim} 5821276789SdimINTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) { 5822276789Sdim void *ctx; 5823276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch); 5824276789Sdim int res = REAL(__overflow)(fp, ch); 5825276789Sdim unpoison_file(fp); 5826276789Sdim return res; 5827276789Sdim} 5828276789SdimINTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) { 5829276789Sdim void *ctx; 5830276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp); 5831276789Sdim int res = REAL(__wuflow)(fp); 5832276789Sdim unpoison_file(fp); 5833276789Sdim return res; 5834276789Sdim} 5835276789SdimINTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) { 5836276789Sdim void *ctx; 5837276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp); 5838276789Sdim int res = REAL(__wunderflow)(fp); 5839276789Sdim unpoison_file(fp); 5840276789Sdim return res; 5841276789Sdim} 5842276789SdimINTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) { 5843276789Sdim void *ctx; 5844276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch); 5845276789Sdim int res = REAL(__woverflow)(fp, ch); 5846276789Sdim unpoison_file(fp); 5847276789Sdim return res; 5848276789Sdim} 5849276789Sdim#define INIT_LIBIO_INTERNALS \ 5850276789Sdim COMMON_INTERCEPT_FUNCTION(__uflow); \ 5851276789Sdim COMMON_INTERCEPT_FUNCTION(__underflow); \ 5852276789Sdim COMMON_INTERCEPT_FUNCTION(__overflow); \ 5853276789Sdim COMMON_INTERCEPT_FUNCTION(__wuflow); \ 5854276789Sdim COMMON_INTERCEPT_FUNCTION(__wunderflow); \ 5855276789Sdim COMMON_INTERCEPT_FUNCTION(__woverflow); 5856276789Sdim#else 5857276789Sdim#define INIT_LIBIO_INTERNALS 5858276789Sdim#endif 5859276789Sdim 5860276789Sdim#if SANITIZER_INTERCEPT_FOPEN 5861276789SdimINTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) { 5862276789Sdim void *ctx; 5863276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode); 5864296417Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 5865276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1); 5866276789Sdim __sanitizer_FILE *res = REAL(fopen)(path, mode); 5867276789Sdim COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path); 5868276789Sdim if (res) unpoison_file(res); 5869276789Sdim return res; 5870276789Sdim} 5871276789SdimINTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) { 5872276789Sdim void *ctx; 5873276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode); 5874276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1); 5875276789Sdim __sanitizer_FILE *res = REAL(fdopen)(fd, mode); 5876276789Sdim if (res) unpoison_file(res); 5877276789Sdim return res; 5878276789Sdim} 5879276789SdimINTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode, 5880276789Sdim __sanitizer_FILE *fp) { 5881276789Sdim void *ctx; 5882276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp); 5883296417Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 5884276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1); 5885276789Sdim COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp); 5886276789Sdim __sanitizer_FILE *res = REAL(freopen)(path, mode, fp); 5887276789Sdim COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path); 5888276789Sdim if (res) unpoison_file(res); 5889276789Sdim return res; 5890276789Sdim} 5891276789Sdim#define INIT_FOPEN \ 5892276789Sdim COMMON_INTERCEPT_FUNCTION(fopen); \ 5893276789Sdim COMMON_INTERCEPT_FUNCTION(fdopen); \ 5894276789Sdim COMMON_INTERCEPT_FUNCTION(freopen); 5895276789Sdim#else 5896276789Sdim#define INIT_FOPEN 5897276789Sdim#endif 5898276789Sdim 5899276789Sdim#if SANITIZER_INTERCEPT_FOPEN64 5900276789SdimINTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) { 5901276789Sdim void *ctx; 5902276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode); 5903276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 5904276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1); 5905276789Sdim __sanitizer_FILE *res = REAL(fopen64)(path, mode); 5906276789Sdim COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path); 5907276789Sdim if (res) unpoison_file(res); 5908276789Sdim return res; 5909276789Sdim} 5910276789SdimINTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode, 5911276789Sdim __sanitizer_FILE *fp) { 5912276789Sdim void *ctx; 5913276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp); 5914296417Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 5915276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1); 5916276789Sdim COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp); 5917276789Sdim __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp); 5918276789Sdim COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path); 5919276789Sdim if (res) unpoison_file(res); 5920276789Sdim return res; 5921276789Sdim} 5922276789Sdim#define INIT_FOPEN64 \ 5923276789Sdim COMMON_INTERCEPT_FUNCTION(fopen64); \ 5924276789Sdim COMMON_INTERCEPT_FUNCTION(freopen64); 5925276789Sdim#else 5926276789Sdim#define INIT_FOPEN64 5927276789Sdim#endif 5928276789Sdim 5929276789Sdim#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM 5930276789SdimINTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) { 5931276789Sdim void *ctx; 5932276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc); 5933276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5934276789Sdim // its metadata. See 5935296417Sdim // https://github.com/google/sanitizers/issues/321. 5936276789Sdim __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc); 5937276789Sdim if (res) { 5938276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr)); 5939276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc)); 5940276789Sdim unpoison_file(res); 5941276789Sdim FileMetadata file = {ptr, sizeloc}; 5942276789Sdim SetInterceptorMetadata(res, file); 5943276789Sdim } 5944276789Sdim return res; 5945276789Sdim} 5946276789SdimINTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr, 5947276789Sdim SIZE_T *sizeloc) { 5948276789Sdim void *ctx; 5949276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc); 5950276789Sdim __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc); 5951276789Sdim if (res) { 5952276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr)); 5953276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc)); 5954276789Sdim unpoison_file(res); 5955276789Sdim FileMetadata file = {(char **)ptr, sizeloc}; 5956276789Sdim SetInterceptorMetadata(res, file); 5957276789Sdim } 5958276789Sdim return res; 5959276789Sdim} 5960276789SdimINTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size, 5961276789Sdim const char *mode) { 5962276789Sdim void *ctx; 5963276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode); 5964276789Sdim // FIXME: under ASan the call below may write to freed memory and corrupt 5965276789Sdim // its metadata. See 5966296417Sdim // https://github.com/google/sanitizers/issues/321. 5967276789Sdim __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode); 5968276789Sdim if (res) unpoison_file(res); 5969276789Sdim return res; 5970276789Sdim} 5971276789Sdim#define INIT_OPEN_MEMSTREAM \ 5972276789Sdim COMMON_INTERCEPT_FUNCTION(open_memstream); \ 5973276789Sdim COMMON_INTERCEPT_FUNCTION(open_wmemstream); \ 5974276789Sdim COMMON_INTERCEPT_FUNCTION(fmemopen); 5975276789Sdim#else 5976276789Sdim#define INIT_OPEN_MEMSTREAM 5977276789Sdim#endif 5978276789Sdim 5979276789Sdim#if SANITIZER_INTERCEPT_OBSTACK 5980276789Sdimstatic void initialize_obstack(__sanitizer_obstack *obstack) { 5981276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack)); 5982276789Sdim if (obstack->chunk) 5983276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk, 5984276789Sdim sizeof(*obstack->chunk)); 5985276789Sdim} 5986276789Sdim 5987276789SdimINTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz, 5988276789Sdim int align, void *(*alloc_fn)(uptr arg, uptr sz), 5989276789Sdim void (*free_fn)(uptr arg, void *p)) { 5990276789Sdim void *ctx; 5991276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn, 5992276789Sdim free_fn); 5993276789Sdim int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn); 5994276789Sdim if (res) initialize_obstack(obstack); 5995276789Sdim return res; 5996276789Sdim} 5997276789SdimINTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz, 5998276789Sdim int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) { 5999276789Sdim void *ctx; 6000276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn, 6001276789Sdim free_fn); 6002276789Sdim int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn); 6003276789Sdim if (res) initialize_obstack(obstack); 6004276789Sdim return res; 6005276789Sdim} 6006276789SdimINTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) { 6007276789Sdim void *ctx; 6008276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length); 6009276789Sdim REAL(_obstack_newchunk)(obstack, length); 6010276789Sdim if (obstack->chunk) 6011276789Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE( 6012276789Sdim obstack->chunk, obstack->next_free - (char *)obstack->chunk); 6013276789Sdim} 6014276789Sdim#define INIT_OBSTACK \ 6015276789Sdim COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \ 6016276789Sdim COMMON_INTERCEPT_FUNCTION(_obstack_begin); \ 6017276789Sdim COMMON_INTERCEPT_FUNCTION(_obstack_newchunk); 6018276789Sdim#else 6019276789Sdim#define INIT_OBSTACK 6020276789Sdim#endif 6021276789Sdim 6022276789Sdim#if SANITIZER_INTERCEPT_FFLUSH 6023276789SdimINTERCEPTOR(int, fflush, __sanitizer_FILE *fp) { 6024276789Sdim void *ctx; 6025276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp); 6026276789Sdim int res = REAL(fflush)(fp); 6027276789Sdim // FIXME: handle fp == NULL 6028276789Sdim if (fp) { 6029276789Sdim const FileMetadata *m = GetInterceptorMetadata(fp); 6030276789Sdim if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size); 6031276789Sdim } 6032276789Sdim return res; 6033276789Sdim} 6034276789Sdim#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush); 6035276789Sdim#else 6036276789Sdim#define INIT_FFLUSH 6037276789Sdim#endif 6038276789Sdim 6039276789Sdim#if SANITIZER_INTERCEPT_FCLOSE 6040276789SdimINTERCEPTOR(int, fclose, __sanitizer_FILE *fp) { 6041276789Sdim void *ctx; 6042276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp); 6043296417Sdim COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp); 6044296417Sdim const FileMetadata *m = GetInterceptorMetadata(fp); 6045296417Sdim int res = REAL(fclose)(fp); 6046296417Sdim if (m) { 6047296417Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size); 6048296417Sdim DeleteInterceptorMetadata(fp); 6049276789Sdim } 6050296417Sdim return res; 6051276789Sdim} 6052276789Sdim#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose); 6053276789Sdim#else 6054276789Sdim#define INIT_FCLOSE 6055276789Sdim#endif 6056276789Sdim 6057276789Sdim#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE 6058276789SdimINTERCEPTOR(void*, dlopen, const char *filename, int flag) { 6059276789Sdim void *ctx; 6060276789Sdim COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag); 6061288943Sdim if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0); 6062288943Sdim COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag); 6063276789Sdim void *res = REAL(dlopen)(filename, flag); 6064327952Sdim Symbolizer::GetOrInit()->InvalidateModuleList(); 6065276789Sdim COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res); 6066276789Sdim return res; 6067276789Sdim} 6068276789Sdim 6069276789SdimINTERCEPTOR(int, dlclose, void *handle) { 6070276789Sdim void *ctx; 6071276789Sdim COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle); 6072276789Sdim int res = REAL(dlclose)(handle); 6073327952Sdim Symbolizer::GetOrInit()->InvalidateModuleList(); 6074276789Sdim COMMON_INTERCEPTOR_LIBRARY_UNLOADED(); 6075276789Sdim return res; 6076276789Sdim} 6077276789Sdim#define INIT_DLOPEN_DLCLOSE \ 6078276789Sdim COMMON_INTERCEPT_FUNCTION(dlopen); \ 6079276789Sdim COMMON_INTERCEPT_FUNCTION(dlclose); 6080276789Sdim#else 6081276789Sdim#define INIT_DLOPEN_DLCLOSE 6082276789Sdim#endif 6083276789Sdim 6084276789Sdim#if SANITIZER_INTERCEPT_GETPASS 6085276789SdimINTERCEPTOR(char *, getpass, const char *prompt) { 6086276789Sdim void *ctx; 6087276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt); 6088276789Sdim if (prompt) 6089276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1); 6090276789Sdim char *res = REAL(getpass)(prompt); 6091276789Sdim if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res)+1); 6092276789Sdim return res; 6093276789Sdim} 6094276789Sdim 6095276789Sdim#define INIT_GETPASS COMMON_INTERCEPT_FUNCTION(getpass); 6096276789Sdim#else 6097276789Sdim#define INIT_GETPASS 6098276789Sdim#endif 6099276789Sdim 6100276789Sdim#if SANITIZER_INTERCEPT_TIMERFD 6101276789SdimINTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value, 6102276789Sdim void *old_value) { 6103276789Sdim void *ctx; 6104276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value, 6105276789Sdim old_value); 6106276789Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz); 6107276789Sdim int res = REAL(timerfd_settime)(fd, flags, new_value, old_value); 6108276789Sdim if (res != -1 && old_value) 6109276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerspec_sz); 6110276789Sdim return res; 6111276789Sdim} 6112276789Sdim 6113276789SdimINTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) { 6114276789Sdim void *ctx; 6115276789Sdim COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value); 6116276789Sdim int res = REAL(timerfd_gettime)(fd, curr_value); 6117276789Sdim if (res != -1 && curr_value) 6118276789Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerspec_sz); 6119276789Sdim return res; 6120276789Sdim} 6121276789Sdim#define INIT_TIMERFD \ 6122276789Sdim COMMON_INTERCEPT_FUNCTION(timerfd_settime); \ 6123276789Sdim COMMON_INTERCEPT_FUNCTION(timerfd_gettime); 6124276789Sdim#else 6125276789Sdim#define INIT_TIMERFD 6126276789Sdim#endif 6127276789Sdim 6128276789Sdim#if SANITIZER_INTERCEPT_MLOCKX 6129276789Sdim// Linux kernel has a bug that leads to kernel deadlock if a process 6130276789Sdim// maps TBs of memory and then calls mlock(). 6131276789Sdimstatic void MlockIsUnsupported() { 6132276789Sdim static atomic_uint8_t printed; 6133276789Sdim if (atomic_exchange(&printed, 1, memory_order_relaxed)) 6134276789Sdim return; 6135296417Sdim VPrintf(1, "%s ignores mlock/mlockall/munlock/munlockall\n", 6136276789Sdim SanitizerToolName); 6137276789Sdim} 6138276789Sdim 6139276789SdimINTERCEPTOR(int, mlock, const void *addr, uptr len) { 6140276789Sdim MlockIsUnsupported(); 6141276789Sdim return 0; 6142276789Sdim} 6143276789Sdim 6144276789SdimINTERCEPTOR(int, munlock, const void *addr, uptr len) { 6145276789Sdim MlockIsUnsupported(); 6146276789Sdim return 0; 6147276789Sdim} 6148276789Sdim 6149276789SdimINTERCEPTOR(int, mlockall, int flags) { 6150276789Sdim MlockIsUnsupported(); 6151276789Sdim return 0; 6152276789Sdim} 6153276789Sdim 6154276789SdimINTERCEPTOR(int, munlockall, void) { 6155276789Sdim MlockIsUnsupported(); 6156276789Sdim return 0; 6157276789Sdim} 6158276789Sdim 6159276789Sdim#define INIT_MLOCKX \ 6160276789Sdim COMMON_INTERCEPT_FUNCTION(mlock); \ 6161276789Sdim COMMON_INTERCEPT_FUNCTION(munlock); \ 6162276789Sdim COMMON_INTERCEPT_FUNCTION(mlockall); \ 6163276789Sdim COMMON_INTERCEPT_FUNCTION(munlockall); 6164276789Sdim 6165276789Sdim#else 6166276789Sdim#define INIT_MLOCKX 6167276789Sdim#endif // SANITIZER_INTERCEPT_MLOCKX 6168276789Sdim 6169288943Sdim#if SANITIZER_INTERCEPT_FOPENCOOKIE 6170288943Sdimstruct WrappedCookie { 6171288943Sdim void *real_cookie; 6172288943Sdim __sanitizer_cookie_io_functions_t real_io_funcs; 6173288943Sdim}; 6174288943Sdim 6175288943Sdimstatic uptr wrapped_read(void *cookie, char *buf, uptr size) { 6176288943Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 6177288943Sdim WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie; 6178288943Sdim __sanitizer_cookie_io_read real_read = wrapped_cookie->real_io_funcs.read; 6179288943Sdim return real_read ? real_read(wrapped_cookie->real_cookie, buf, size) : 0; 6180288943Sdim} 6181288943Sdim 6182288943Sdimstatic uptr wrapped_write(void *cookie, const char *buf, uptr size) { 6183288943Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 6184288943Sdim WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie; 6185288943Sdim __sanitizer_cookie_io_write real_write = wrapped_cookie->real_io_funcs.write; 6186288943Sdim return real_write ? real_write(wrapped_cookie->real_cookie, buf, size) : size; 6187288943Sdim} 6188288943Sdim 6189288943Sdimstatic int wrapped_seek(void *cookie, u64 *offset, int whence) { 6190288943Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 6191288943Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset)); 6192288943Sdim WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie; 6193288943Sdim __sanitizer_cookie_io_seek real_seek = wrapped_cookie->real_io_funcs.seek; 6194288943Sdim return real_seek ? real_seek(wrapped_cookie->real_cookie, offset, whence) 6195288943Sdim : -1; 6196288943Sdim} 6197288943Sdim 6198288943Sdimstatic int wrapped_close(void *cookie) { 6199288943Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 6200288943Sdim WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie; 6201288943Sdim __sanitizer_cookie_io_close real_close = wrapped_cookie->real_io_funcs.close; 6202288943Sdim int res = real_close ? real_close(wrapped_cookie->real_cookie) : 0; 6203288943Sdim InternalFree(wrapped_cookie); 6204288943Sdim return res; 6205288943Sdim} 6206288943Sdim 6207288943SdimINTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode, 6208288943Sdim __sanitizer_cookie_io_functions_t io_funcs) { 6209288943Sdim void *ctx; 6210288943Sdim COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs); 6211288943Sdim WrappedCookie *wrapped_cookie = 6212288943Sdim (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie)); 6213288943Sdim wrapped_cookie->real_cookie = cookie; 6214288943Sdim wrapped_cookie->real_io_funcs = io_funcs; 6215288943Sdim __sanitizer_FILE *res = 6216288943Sdim REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write, 6217288943Sdim wrapped_seek, wrapped_close}); 6218288943Sdim return res; 6219288943Sdim} 6220288943Sdim 6221288943Sdim#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie); 6222288943Sdim#else 6223288943Sdim#define INIT_FOPENCOOKIE 6224288943Sdim#endif // SANITIZER_INTERCEPT_FOPENCOOKIE 6225288943Sdim 6226296417Sdim#if SANITIZER_INTERCEPT_SEM 6227296417SdimINTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) { 6228296417Sdim void *ctx; 6229296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value); 6230296417Sdim // Workaround a bug in glibc's "old" semaphore implementation by 6231296417Sdim // zero-initializing the sem_t contents. This has to be done here because 6232296417Sdim // interceptors bind to the lowest symbols version by default, hitting the 6233296417Sdim // buggy code path while the non-sanitized build of the same code works fine. 6234296417Sdim REAL(memset)(s, 0, sizeof(*s)); 6235296417Sdim int res = REAL(sem_init)(s, pshared, value); 6236296417Sdim return res; 6237296417Sdim} 6238296417Sdim 6239296417SdimINTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) { 6240296417Sdim void *ctx; 6241296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s); 6242296417Sdim int res = REAL(sem_destroy)(s); 6243296417Sdim return res; 6244296417Sdim} 6245296417Sdim 6246296417SdimINTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) { 6247296417Sdim void *ctx; 6248296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s); 6249296417Sdim int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s); 6250296417Sdim if (res == 0) { 6251296417Sdim COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s); 6252296417Sdim } 6253296417Sdim return res; 6254296417Sdim} 6255296417Sdim 6256296417SdimINTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) { 6257296417Sdim void *ctx; 6258296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s); 6259296417Sdim int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s); 6260296417Sdim if (res == 0) { 6261296417Sdim COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s); 6262296417Sdim } 6263296417Sdim return res; 6264296417Sdim} 6265296417Sdim 6266296417SdimINTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) { 6267296417Sdim void *ctx; 6268296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime); 6269296417Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz); 6270296417Sdim int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime); 6271296417Sdim if (res == 0) { 6272296417Sdim COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s); 6273296417Sdim } 6274296417Sdim return res; 6275296417Sdim} 6276296417Sdim 6277296417SdimINTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) { 6278296417Sdim void *ctx; 6279296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s); 6280296417Sdim COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s); 6281296417Sdim int res = REAL(sem_post)(s); 6282296417Sdim return res; 6283296417Sdim} 6284296417Sdim 6285296417SdimINTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) { 6286296417Sdim void *ctx; 6287296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval); 6288296417Sdim int res = REAL(sem_getvalue)(s, sval); 6289296417Sdim if (res == 0) { 6290296417Sdim COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s); 6291296417Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sval, sizeof(*sval)); 6292296417Sdim } 6293296417Sdim return res; 6294296417Sdim} 6295296417Sdim#define INIT_SEM \ 6296296417Sdim COMMON_INTERCEPT_FUNCTION(sem_init); \ 6297296417Sdim COMMON_INTERCEPT_FUNCTION(sem_destroy); \ 6298296417Sdim COMMON_INTERCEPT_FUNCTION(sem_wait); \ 6299296417Sdim COMMON_INTERCEPT_FUNCTION(sem_trywait); \ 6300296417Sdim COMMON_INTERCEPT_FUNCTION(sem_timedwait); \ 6301296417Sdim COMMON_INTERCEPT_FUNCTION(sem_post); \ 6302296417Sdim COMMON_INTERCEPT_FUNCTION(sem_getvalue); 6303296417Sdim#else 6304296417Sdim#define INIT_SEM 6305296417Sdim#endif // SANITIZER_INTERCEPT_SEM 6306296417Sdim 6307296417Sdim#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL 6308296417SdimINTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) { 6309296417Sdim void *ctx; 6310296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate); 6311296417Sdim int res = REAL(pthread_setcancelstate)(state, oldstate); 6312327952Sdim if (res == 0 && oldstate != nullptr) 6313296417Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate)); 6314296417Sdim return res; 6315296417Sdim} 6316296417Sdim 6317296417SdimINTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) { 6318296417Sdim void *ctx; 6319296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype); 6320296417Sdim int res = REAL(pthread_setcanceltype)(type, oldtype); 6321327952Sdim if (res == 0 && oldtype != nullptr) 6322296417Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype)); 6323296417Sdim return res; 6324296417Sdim} 6325296417Sdim#define INIT_PTHREAD_SETCANCEL \ 6326296417Sdim COMMON_INTERCEPT_FUNCTION(pthread_setcancelstate); \ 6327296417Sdim COMMON_INTERCEPT_FUNCTION(pthread_setcanceltype); 6328296417Sdim#else 6329296417Sdim#define INIT_PTHREAD_SETCANCEL 6330296417Sdim#endif 6331296417Sdim 6332296417Sdim#if SANITIZER_INTERCEPT_MINCORE 6333296417SdimINTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) { 6334296417Sdim void *ctx; 6335296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec); 6336296417Sdim int res = REAL(mincore)(addr, length, vec); 6337296417Sdim if (res == 0) { 6338296417Sdim uptr page_size = GetPageSizeCached(); 6339296417Sdim uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size; 6340296417Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size); 6341296417Sdim } 6342296417Sdim return res; 6343296417Sdim} 6344296417Sdim#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore); 6345296417Sdim#else 6346296417Sdim#define INIT_MINCORE 6347296417Sdim#endif 6348296417Sdim 6349296417Sdim#if SANITIZER_INTERCEPT_PROCESS_VM_READV 6350296417SdimINTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov, 6351296417Sdim uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt, 6352296417Sdim uptr flags) { 6353296417Sdim void *ctx; 6354296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt, 6355296417Sdim remote_iov, riovcnt, flags); 6356296417Sdim SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov, 6357296417Sdim riovcnt, flags); 6358296417Sdim if (res > 0) 6359296417Sdim write_iovec(ctx, local_iov, liovcnt, res); 6360296417Sdim return res; 6361296417Sdim} 6362296417Sdim 6363296417SdimINTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov, 6364296417Sdim uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt, 6365296417Sdim uptr flags) { 6366296417Sdim void *ctx; 6367296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt, 6368296417Sdim remote_iov, riovcnt, flags); 6369296417Sdim SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov, 6370296417Sdim riovcnt, flags); 6371296417Sdim if (res > 0) 6372296417Sdim read_iovec(ctx, local_iov, liovcnt, res); 6373296417Sdim return res; 6374296417Sdim} 6375296417Sdim#define INIT_PROCESS_VM_READV \ 6376296417Sdim COMMON_INTERCEPT_FUNCTION(process_vm_readv); \ 6377296417Sdim COMMON_INTERCEPT_FUNCTION(process_vm_writev); 6378296417Sdim#else 6379296417Sdim#define INIT_PROCESS_VM_READV 6380296417Sdim#endif 6381296417Sdim 6382296417Sdim#if SANITIZER_INTERCEPT_CTERMID 6383296417SdimINTERCEPTOR(char *, ctermid, char *s) { 6384296417Sdim void *ctx; 6385296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s); 6386296417Sdim char *res = REAL(ctermid)(s); 6387296417Sdim if (res) { 6388296417Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); 6389296417Sdim } 6390296417Sdim return res; 6391296417Sdim} 6392296417Sdim#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid); 6393296417Sdim#else 6394296417Sdim#define INIT_CTERMID 6395296417Sdim#endif 6396296417Sdim 6397296417Sdim#if SANITIZER_INTERCEPT_CTERMID_R 6398296417SdimINTERCEPTOR(char *, ctermid_r, char *s) { 6399296417Sdim void *ctx; 6400296417Sdim COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s); 6401296417Sdim char *res = REAL(ctermid_r)(s); 6402296417Sdim if (res) { 6403296417Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); 6404296417Sdim } 6405296417Sdim return res; 6406296417Sdim} 6407296417Sdim#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r); 6408296417Sdim#else 6409296417Sdim#define INIT_CTERMID_R 6410296417Sdim#endif 6411296417Sdim 6412309124Sdim#if SANITIZER_INTERCEPT_RECV_RECVFROM 6413309124SdimINTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { 6414309124Sdim void *ctx; 6415309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags); 6416309124Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 6417309124Sdim SSIZE_T res = REAL(recv)(fd, buf, len, flags); 6418309124Sdim if (res > 0) { 6419309124Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len)); 6420309124Sdim } 6421309124Sdim if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 6422309124Sdim return res; 6423309124Sdim} 6424309124Sdim 6425309124SdimINTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, 6426309124Sdim void *srcaddr, int *addrlen) { 6427309124Sdim void *ctx; 6428309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr, 6429309124Sdim addrlen); 6430309124Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 6431309124Sdim SIZE_T srcaddr_sz; 6432309124Sdim if (srcaddr) srcaddr_sz = *addrlen; 6433309124Sdim (void)srcaddr_sz; // prevent "set but not used" warning 6434309124Sdim SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); 6435309124Sdim if (res > 0) { 6436309124Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len)); 6437309124Sdim if (srcaddr) 6438309124Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr, 6439309124Sdim Min((SIZE_T)*addrlen, srcaddr_sz)); 6440309124Sdim } 6441309124Sdim return res; 6442309124Sdim} 6443309124Sdim#define INIT_RECV_RECVFROM \ 6444309124Sdim COMMON_INTERCEPT_FUNCTION(recv); \ 6445309124Sdim COMMON_INTERCEPT_FUNCTION(recvfrom); 6446309124Sdim#else 6447309124Sdim#define INIT_RECV_RECVFROM 6448309124Sdim#endif 6449309124Sdim 6450309124Sdim#if SANITIZER_INTERCEPT_SEND_SENDTO 6451309124SdimINTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) { 6452309124Sdim void *ctx; 6453309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags); 6454309124Sdim if (fd >= 0) { 6455309124Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 6456309124Sdim COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 6457309124Sdim } 6458309124Sdim SSIZE_T res = REAL(send)(fd, buf, len, flags); 6459309124Sdim if (common_flags()->intercept_send && res > 0) 6460309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len)); 6461309124Sdim return res; 6462309124Sdim} 6463309124Sdim 6464309124SdimINTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags, 6465309124Sdim void *dstaddr, int addrlen) { 6466309124Sdim void *ctx; 6467309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen); 6468309124Sdim if (fd >= 0) { 6469309124Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 6470309124Sdim COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 6471309124Sdim } 6472309124Sdim // Can't check dstaddr as it may have uninitialized padding at the end. 6473309124Sdim SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen); 6474309124Sdim if (common_flags()->intercept_send && res > 0) 6475309124Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len)); 6476309124Sdim return res; 6477309124Sdim} 6478309124Sdim#define INIT_SEND_SENDTO \ 6479309124Sdim COMMON_INTERCEPT_FUNCTION(send); \ 6480309124Sdim COMMON_INTERCEPT_FUNCTION(sendto); 6481309124Sdim#else 6482309124Sdim#define INIT_SEND_SENDTO 6483309124Sdim#endif 6484309124Sdim 6485309124Sdim#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE 6486309124SdimINTERCEPTOR(int, eventfd_read, int fd, u64 *value) { 6487309124Sdim void *ctx; 6488309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value); 6489309124Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 6490309124Sdim int res = REAL(eventfd_read)(fd, value); 6491309124Sdim if (res == 0) { 6492309124Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value)); 6493309124Sdim if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 6494309124Sdim } 6495309124Sdim return res; 6496309124Sdim} 6497309124SdimINTERCEPTOR(int, eventfd_write, int fd, u64 value) { 6498309124Sdim void *ctx; 6499309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value); 6500309124Sdim if (fd >= 0) { 6501309124Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 6502309124Sdim COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); 6503309124Sdim } 6504309124Sdim int res = REAL(eventfd_write)(fd, value); 6505309124Sdim return res; 6506309124Sdim} 6507309124Sdim#define INIT_EVENTFD_READ_WRITE \ 6508309124Sdim COMMON_INTERCEPT_FUNCTION(eventfd_read); \ 6509309124Sdim COMMON_INTERCEPT_FUNCTION(eventfd_write) 6510309124Sdim#else 6511309124Sdim#define INIT_EVENTFD_READ_WRITE 6512309124Sdim#endif 6513309124Sdim 6514309124Sdim#if SANITIZER_INTERCEPT_STAT 6515309124SdimINTERCEPTOR(int, stat, const char *path, void *buf) { 6516309124Sdim void *ctx; 6517309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf); 6518309124Sdim if (common_flags()->intercept_stat) 6519309124Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); 6520309124Sdim int res = REAL(stat)(path, buf); 6521309124Sdim if (!res) 6522309124Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz); 6523309124Sdim return res; 6524309124Sdim} 6525309124Sdim#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat) 6526309124Sdim#else 6527309124Sdim#define INIT_STAT 6528309124Sdim#endif 6529309124Sdim 6530341825Sdim#if SANITIZER_INTERCEPT_LSTAT 6531341825SdimINTERCEPTOR(int, lstat, const char *path, void *buf) { 6532341825Sdim void *ctx; 6533341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, lstat, path, buf); 6534341825Sdim if (common_flags()->intercept_stat) 6535341825Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); 6536341825Sdim int res = REAL(lstat)(path, buf); 6537341825Sdim if (!res) 6538341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz); 6539341825Sdim return res; 6540341825Sdim} 6541341825Sdim#define INIT_LSTAT COMMON_INTERCEPT_FUNCTION(lstat) 6542341825Sdim#else 6543341825Sdim#define INIT_LSTAT 6544341825Sdim#endif 6545341825Sdim 6546309124Sdim#if SANITIZER_INTERCEPT___XSTAT 6547309124SdimINTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { 6548309124Sdim void *ctx; 6549309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf); 6550309124Sdim if (common_flags()->intercept_stat) 6551309124Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); 6552309124Sdim int res = REAL(__xstat)(version, path, buf); 6553309124Sdim if (!res) 6554309124Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz); 6555309124Sdim return res; 6556309124Sdim} 6557309124Sdim#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat) 6558309124Sdim#else 6559309124Sdim#define INIT___XSTAT 6560309124Sdim#endif 6561309124Sdim 6562309124Sdim#if SANITIZER_INTERCEPT___XSTAT64 6563309124SdimINTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { 6564309124Sdim void *ctx; 6565309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf); 6566309124Sdim if (common_flags()->intercept_stat) 6567309124Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); 6568309124Sdim int res = REAL(__xstat64)(version, path, buf); 6569309124Sdim if (!res) 6570309124Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz); 6571309124Sdim return res; 6572309124Sdim} 6573309124Sdim#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64) 6574309124Sdim#else 6575309124Sdim#define INIT___XSTAT64 6576309124Sdim#endif 6577309124Sdim 6578309124Sdim#if SANITIZER_INTERCEPT___LXSTAT 6579309124SdimINTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { 6580309124Sdim void *ctx; 6581309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf); 6582309124Sdim if (common_flags()->intercept_stat) 6583309124Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); 6584309124Sdim int res = REAL(__lxstat)(version, path, buf); 6585309124Sdim if (!res) 6586309124Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz); 6587309124Sdim return res; 6588309124Sdim} 6589309124Sdim#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat) 6590309124Sdim#else 6591309124Sdim#define INIT___LXSTAT 6592309124Sdim#endif 6593309124Sdim 6594309124Sdim#if SANITIZER_INTERCEPT___LXSTAT64 6595309124SdimINTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { 6596309124Sdim void *ctx; 6597309124Sdim COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf); 6598309124Sdim if (common_flags()->intercept_stat) 6599309124Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); 6600309124Sdim int res = REAL(__lxstat64)(version, path, buf); 6601309124Sdim if (!res) 6602309124Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz); 6603309124Sdim return res; 6604309124Sdim} 6605309124Sdim#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64) 6606309124Sdim#else 6607309124Sdim#define INIT___LXSTAT64 6608309124Sdim#endif 6609309124Sdim 6610309124Sdim// FIXME: add other *stat interceptor 6611309124Sdim 6612314564Sdim#if SANITIZER_INTERCEPT_UTMP 6613314564SdimINTERCEPTOR(void *, getutent, int dummy) { 6614314564Sdim void *ctx; 6615314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy); 6616314564Sdim void *res = REAL(getutent)(dummy); 6617314564Sdim if (res) 6618314564Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz); 6619314564Sdim return res; 6620314564Sdim} 6621314564SdimINTERCEPTOR(void *, getutid, void *ut) { 6622314564Sdim void *ctx; 6623314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut); 6624314564Sdim void *res = REAL(getutid)(ut); 6625314564Sdim if (res) 6626314564Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz); 6627314564Sdim return res; 6628314564Sdim} 6629314564SdimINTERCEPTOR(void *, getutline, void *ut) { 6630314564Sdim void *ctx; 6631314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut); 6632314564Sdim void *res = REAL(getutline)(ut); 6633314564Sdim if (res) 6634314564Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz); 6635314564Sdim return res; 6636314564Sdim} 6637314564Sdim#define INIT_UTMP \ 6638314564Sdim COMMON_INTERCEPT_FUNCTION(getutent); \ 6639314564Sdim COMMON_INTERCEPT_FUNCTION(getutid); \ 6640314564Sdim COMMON_INTERCEPT_FUNCTION(getutline); 6641314564Sdim#else 6642314564Sdim#define INIT_UTMP 6643314564Sdim#endif 6644314564Sdim 6645314564Sdim#if SANITIZER_INTERCEPT_UTMPX 6646314564SdimINTERCEPTOR(void *, getutxent, int dummy) { 6647314564Sdim void *ctx; 6648314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy); 6649314564Sdim void *res = REAL(getutxent)(dummy); 6650314564Sdim if (res) 6651314564Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz); 6652314564Sdim return res; 6653314564Sdim} 6654314564SdimINTERCEPTOR(void *, getutxid, void *ut) { 6655314564Sdim void *ctx; 6656314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut); 6657314564Sdim void *res = REAL(getutxid)(ut); 6658314564Sdim if (res) 6659314564Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz); 6660314564Sdim return res; 6661314564Sdim} 6662314564SdimINTERCEPTOR(void *, getutxline, void *ut) { 6663314564Sdim void *ctx; 6664314564Sdim COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut); 6665314564Sdim void *res = REAL(getutxline)(ut); 6666314564Sdim if (res) 6667314564Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz); 6668314564Sdim return res; 6669314564Sdim} 6670344779SdimINTERCEPTOR(void *, pututxline, const void *ut) { 6671344779Sdim void *ctx; 6672344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, pututxline, ut); 6673344779Sdim if (ut) 6674344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ut, __sanitizer::struct_utmpx_sz); 6675344779Sdim void *res = REAL(pututxline)(ut); 6676344779Sdim if (res) 6677344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_utmpx_sz); 6678344779Sdim return res; 6679344779Sdim} 6680314564Sdim#define INIT_UTMPX \ 6681314564Sdim COMMON_INTERCEPT_FUNCTION(getutxent); \ 6682314564Sdim COMMON_INTERCEPT_FUNCTION(getutxid); \ 6683344779Sdim COMMON_INTERCEPT_FUNCTION(getutxline); \ 6684344779Sdim COMMON_INTERCEPT_FUNCTION(pututxline); 6685314564Sdim#else 6686314564Sdim#define INIT_UTMPX 6687314564Sdim#endif 6688314564Sdim 6689321369Sdim#if SANITIZER_INTERCEPT_GETLOADAVG 6690321369SdimINTERCEPTOR(int, getloadavg, double *loadavg, int nelem) { 6691321369Sdim void *ctx; 6692321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem); 6693321369Sdim int res = REAL(getloadavg)(loadavg, nelem); 6694321369Sdim if (res > 0) 6695321369Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg)); 6696321369Sdim return res; 6697321369Sdim} 6698321369Sdim#define INIT_GETLOADAVG \ 6699321369Sdim COMMON_INTERCEPT_FUNCTION(getloadavg); 6700321369Sdim#else 6701321369Sdim#define INIT_GETLOADAVG 6702321369Sdim#endif 6703321369Sdim 6704321369Sdim#if SANITIZER_INTERCEPT_MCHECK_MPROBE 6705321369SdimINTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) { 6706321369Sdim return 0; 6707321369Sdim} 6708321369Sdim 6709321369SdimINTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) { 6710321369Sdim return 0; 6711321369Sdim} 6712321369Sdim 6713321369SdimINTERCEPTOR(int, mprobe, void *ptr) { 6714321369Sdim return 0; 6715321369Sdim} 6716321369Sdim#endif 6717321369Sdim 6718321369SdimINTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { 6719321369Sdim void *ctx; 6720321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s); 6721321369Sdim SIZE_T res = REAL(wcslen)(s); 6722321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1)); 6723321369Sdim return res; 6724321369Sdim} 6725321369Sdim 6726321369SdimINTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) { 6727321369Sdim void *ctx; 6728321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n); 6729321369Sdim SIZE_T res = REAL(wcsnlen)(s, n); 6730321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n)); 6731321369Sdim return res; 6732321369Sdim} 6733321369Sdim#define INIT_WCSLEN \ 6734321369Sdim COMMON_INTERCEPT_FUNCTION(wcslen); \ 6735321369Sdim COMMON_INTERCEPT_FUNCTION(wcsnlen); 6736321369Sdim 6737321369Sdim#if SANITIZER_INTERCEPT_WCSCAT 6738321369SdimINTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) { 6739321369Sdim void *ctx; 6740321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src); 6741321369Sdim SIZE_T src_size = REAL(wcslen)(src); 6742321369Sdim SIZE_T dst_size = REAL(wcslen)(dst); 6743321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t)); 6744321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t)); 6745321369Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size, 6746321369Sdim (src_size + 1) * sizeof(wchar_t)); 6747360784Sdim return REAL(wcscat)(dst, src); 6748321369Sdim} 6749321369Sdim 6750321369SdimINTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) { 6751321369Sdim void *ctx; 6752321369Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n); 6753321369Sdim SIZE_T src_size = REAL(wcsnlen)(src, n); 6754321369Sdim SIZE_T dst_size = REAL(wcslen)(dst); 6755321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, 6756321369Sdim Min(src_size + 1, n) * sizeof(wchar_t)); 6757321369Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t)); 6758321369Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size, 6759321369Sdim (src_size + 1) * sizeof(wchar_t)); 6760360784Sdim return REAL(wcsncat)(dst, src, n); 6761321369Sdim} 6762321369Sdim#define INIT_WCSCAT \ 6763321369Sdim COMMON_INTERCEPT_FUNCTION(wcscat); \ 6764321369Sdim COMMON_INTERCEPT_FUNCTION(wcsncat); 6765321369Sdim#else 6766321369Sdim#define INIT_WCSCAT 6767321369Sdim#endif 6768321369Sdim 6769353358Sdim#if SANITIZER_INTERCEPT_WCSDUP 6770353358SdimINTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) { 6771353358Sdim void *ctx; 6772353358Sdim COMMON_INTERCEPTOR_ENTER(ctx, wcsdup, s); 6773353358Sdim SIZE_T len = REAL(wcslen)(s); 6774353358Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (len + 1)); 6775353358Sdim wchar_t *result = REAL(wcsdup)(s); 6776353358Sdim if (result) 6777353358Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(wchar_t) * (len + 1)); 6778353358Sdim return result; 6779353358Sdim} 6780353358Sdim 6781353358Sdim#define INIT_WCSDUP COMMON_INTERCEPT_FUNCTION(wcsdup); 6782353358Sdim#else 6783353358Sdim#define INIT_WCSDUP 6784353358Sdim#endif 6785353358Sdim 6786341825Sdim#if SANITIZER_INTERCEPT_STRXFRM 6787341825Sdimstatic SIZE_T RealStrLen(const char *str) { return REAL(strlen)(str); } 6788341825Sdim 6789341825Sdimstatic SIZE_T RealStrLen(const wchar_t *str) { return REAL(wcslen)(str); } 6790341825Sdim 6791341825Sdim#define STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len, ...) \ 6792341825Sdim { \ 6793341825Sdim void *ctx; \ 6794341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, strxfrm, dest, src, len, ##__VA_ARGS__); \ 6795341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, \ 6796341825Sdim sizeof(*src) * (RealStrLen(src) + 1)); \ 6797341825Sdim SIZE_T res = REAL(strxfrm)(dest, src, len, ##__VA_ARGS__); \ 6798341825Sdim if (res < len) \ 6799341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, sizeof(*src) * (res + 1)); \ 6800341825Sdim return res; \ 6801341825Sdim } 6802341825Sdim 6803341825SdimINTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T len) { 6804341825Sdim STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len); 6805341825Sdim} 6806341825Sdim 6807341825SdimINTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T len, 6808341825Sdim void *locale) { 6809341825Sdim STRXFRM_INTERCEPTOR_IMPL(strxfrm_l, dest, src, len, locale); 6810341825Sdim} 6811341825Sdim 6812341825Sdim#define INIT_STRXFRM \ 6813341825Sdim COMMON_INTERCEPT_FUNCTION(strxfrm); \ 6814341825Sdim COMMON_INTERCEPT_FUNCTION(strxfrm_l); 6815341825Sdim#else 6816341825Sdim#define INIT_STRXFRM 6817341825Sdim#endif 6818341825Sdim 6819341825Sdim#if SANITIZER_INTERCEPT___STRXFRM_L 6820341825SdimINTERCEPTOR(SIZE_T, __strxfrm_l, char *dest, const char *src, SIZE_T len, 6821341825Sdim void *locale) { 6822341825Sdim STRXFRM_INTERCEPTOR_IMPL(__strxfrm_l, dest, src, len, locale); 6823341825Sdim} 6824341825Sdim 6825341825Sdim#define INIT___STRXFRM_L COMMON_INTERCEPT_FUNCTION(__strxfrm_l); 6826341825Sdim#else 6827341825Sdim#define INIT___STRXFRM_L 6828341825Sdim#endif 6829341825Sdim 6830341825Sdim#if SANITIZER_INTERCEPT_WCSXFRM 6831341825SdimINTERCEPTOR(SIZE_T, wcsxfrm, wchar_t *dest, const wchar_t *src, SIZE_T len) { 6832341825Sdim STRXFRM_INTERCEPTOR_IMPL(wcsxfrm, dest, src, len); 6833341825Sdim} 6834341825Sdim 6835341825SdimINTERCEPTOR(SIZE_T, wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len, 6836341825Sdim void *locale) { 6837341825Sdim STRXFRM_INTERCEPTOR_IMPL(wcsxfrm_l, dest, src, len, locale); 6838341825Sdim} 6839341825Sdim 6840341825Sdim#define INIT_WCSXFRM \ 6841341825Sdim COMMON_INTERCEPT_FUNCTION(wcsxfrm); \ 6842341825Sdim COMMON_INTERCEPT_FUNCTION(wcsxfrm_l); 6843341825Sdim#else 6844341825Sdim#define INIT_WCSXFRM 6845341825Sdim#endif 6846341825Sdim 6847341825Sdim#if SANITIZER_INTERCEPT___WCSXFRM_L 6848341825SdimINTERCEPTOR(SIZE_T, __wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len, 6849341825Sdim void *locale) { 6850341825Sdim STRXFRM_INTERCEPTOR_IMPL(__wcsxfrm_l, dest, src, len, locale); 6851341825Sdim} 6852341825Sdim 6853341825Sdim#define INIT___WCSXFRM_L COMMON_INTERCEPT_FUNCTION(__wcsxfrm_l); 6854341825Sdim#else 6855341825Sdim#define INIT___WCSXFRM_L 6856341825Sdim#endif 6857341825Sdim 6858341825Sdim#if SANITIZER_INTERCEPT_ACCT 6859341825SdimINTERCEPTOR(int, acct, const char *file) { 6860341825Sdim void *ctx; 6861341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, acct, file); 6862341825Sdim if (file) 6863341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1); 6864341825Sdim return REAL(acct)(file); 6865341825Sdim} 6866341825Sdim#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct) 6867341825Sdim#else 6868341825Sdim#define INIT_ACCT 6869341825Sdim#endif 6870341825Sdim 6871341825Sdim#if SANITIZER_INTERCEPT_USER_FROM_UID 6872341825SdimINTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) { 6873341825Sdim void *ctx; 6874341825Sdim const char *user; 6875341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser); 6876341825Sdim user = REAL(user_from_uid)(uid, nouser); 6877341825Sdim if (user) 6878341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, REAL(strlen)(user) + 1); 6879341825Sdim return user; 6880341825Sdim} 6881341825Sdim#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid) 6882341825Sdim#else 6883341825Sdim#define INIT_USER_FROM_UID 6884341825Sdim#endif 6885341825Sdim 6886341825Sdim#if SANITIZER_INTERCEPT_UID_FROM_USER 6887341825SdimINTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) { 6888341825Sdim void *ctx; 6889341825Sdim int res; 6890341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid); 6891341825Sdim if (name) 6892341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 6893341825Sdim res = REAL(uid_from_user)(name, uid); 6894341825Sdim if (uid) 6895341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid)); 6896341825Sdim return res; 6897341825Sdim} 6898341825Sdim#define INIT_UID_FROM_USER COMMON_INTERCEPT_FUNCTION(uid_from_user) 6899341825Sdim#else 6900341825Sdim#define INIT_UID_FROM_USER 6901341825Sdim#endif 6902341825Sdim 6903341825Sdim#if SANITIZER_INTERCEPT_GROUP_FROM_GID 6904341825SdimINTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) { 6905341825Sdim void *ctx; 6906341825Sdim const char *group; 6907341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup); 6908341825Sdim group = REAL(group_from_gid)(gid, nogroup); 6909341825Sdim if (group) 6910341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, REAL(strlen)(group) + 1); 6911341825Sdim return group; 6912341825Sdim} 6913341825Sdim#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid) 6914341825Sdim#else 6915341825Sdim#define INIT_GROUP_FROM_GID 6916341825Sdim#endif 6917341825Sdim 6918341825Sdim#if SANITIZER_INTERCEPT_GID_FROM_GROUP 6919341825SdimINTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) { 6920341825Sdim void *ctx; 6921341825Sdim int res; 6922341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid); 6923341825Sdim if (group) 6924341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, group, REAL(strlen)(group) + 1); 6925341825Sdim res = REAL(gid_from_group)(group, gid); 6926341825Sdim if (gid) 6927341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid)); 6928341825Sdim return res; 6929341825Sdim} 6930341825Sdim#define INIT_GID_FROM_GROUP COMMON_INTERCEPT_FUNCTION(gid_from_group) 6931341825Sdim#else 6932341825Sdim#define INIT_GID_FROM_GROUP 6933341825Sdim#endif 6934341825Sdim 6935341825Sdim#if SANITIZER_INTERCEPT_ACCESS 6936341825SdimINTERCEPTOR(int, access, const char *path, int mode) { 6937341825Sdim void *ctx; 6938341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode); 6939341825Sdim if (path) 6940341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 6941341825Sdim return REAL(access)(path, mode); 6942341825Sdim} 6943341825Sdim#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access) 6944341825Sdim#else 6945341825Sdim#define INIT_ACCESS 6946341825Sdim#endif 6947341825Sdim 6948341825Sdim#if SANITIZER_INTERCEPT_FACCESSAT 6949341825SdimINTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) { 6950341825Sdim void *ctx; 6951341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags); 6952341825Sdim if (path) 6953341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 6954341825Sdim return REAL(faccessat)(fd, path, mode, flags); 6955341825Sdim} 6956341825Sdim#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat) 6957341825Sdim#else 6958341825Sdim#define INIT_FACCESSAT 6959341825Sdim#endif 6960341825Sdim 6961341825Sdim#if SANITIZER_INTERCEPT_GETGROUPLIST 6962341825SdimINTERCEPTOR(int, getgrouplist, const char *name, u32 basegid, u32 *groups, 6963341825Sdim int *ngroups) { 6964341825Sdim void *ctx; 6965341825Sdim int res; 6966341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getgrouplist, name, basegid, groups, ngroups); 6967341825Sdim if (name) 6968341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 6969341825Sdim if (ngroups) 6970341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ngroups, sizeof(*ngroups)); 6971341825Sdim res = REAL(getgrouplist)(name, basegid, groups, ngroups); 6972341825Sdim if (!res && groups && ngroups) { 6973341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups)); 6974341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups)); 6975341825Sdim } 6976341825Sdim return res; 6977341825Sdim} 6978341825Sdim 6979341825Sdim#define INIT_GETGROUPLIST COMMON_INTERCEPT_FUNCTION(getgrouplist); 6980341825Sdim#else 6981341825Sdim#define INIT_GETGROUPLIST 6982341825Sdim#endif 6983341825Sdim 6984341825Sdim#if SANITIZER_INTERCEPT_GETGROUPMEMBERSHIP 6985341825SdimINTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups, 6986341825Sdim int maxgrp, int *ngroups) { 6987341825Sdim void *ctx; 6988341825Sdim int res; 6989341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getgroupmembership, name, basegid, groups, 6990341825Sdim maxgrp, ngroups); 6991341825Sdim if (name) 6992341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 6993341825Sdim res = REAL(getgroupmembership)(name, basegid, groups, maxgrp, ngroups); 6994341825Sdim if (!res && groups && ngroups) { 6995341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups)); 6996341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups)); 6997341825Sdim } 6998341825Sdim return res; 6999341825Sdim} 7000341825Sdim 7001341825Sdim#define INIT_GETGROUPMEMBERSHIP COMMON_INTERCEPT_FUNCTION(getgroupmembership); 7002341825Sdim#else 7003341825Sdim#define INIT_GETGROUPMEMBERSHIP 7004341825Sdim#endif 7005341825Sdim 7006341825Sdim#if SANITIZER_INTERCEPT_READLINK 7007341825SdimINTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) { 7008341825Sdim void* ctx; 7009341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz); 7010341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 7011341825Sdim SSIZE_T res = REAL(readlink)(path, buf, bufsiz); 7012341825Sdim if (res > 0) 7013341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res); 7014341825Sdim return res; 7015341825Sdim} 7016341825Sdim 7017341825Sdim#define INIT_READLINK COMMON_INTERCEPT_FUNCTION(readlink) 7018341825Sdim#else 7019341825Sdim#define INIT_READLINK 7020341825Sdim#endif 7021341825Sdim 7022341825Sdim#if SANITIZER_INTERCEPT_READLINKAT 7023341825SdimINTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf, 7024341825Sdim SIZE_T bufsiz) { 7025341825Sdim void* ctx; 7026341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz); 7027341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 7028341825Sdim SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz); 7029341825Sdim if (res > 0) 7030341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res); 7031341825Sdim return res; 7032341825Sdim} 7033341825Sdim 7034341825Sdim#define INIT_READLINKAT COMMON_INTERCEPT_FUNCTION(readlinkat) 7035341825Sdim#else 7036341825Sdim#define INIT_READLINKAT 7037341825Sdim#endif 7038341825Sdim 7039341825Sdim#if SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT 7040341825SdimINTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname, 7041341825Sdim struct file_handle *handle, int *mount_id, int flags) { 7042341825Sdim void* ctx; 7043341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle, 7044341825Sdim mount_id, flags); 7045341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, REAL(strlen)(pathname) + 1); 7046341825Sdim 7047341825Sdim __sanitizer_file_handle *sanitizer_handle = 7048341825Sdim reinterpret_cast<__sanitizer_file_handle*>(handle); 7049341825Sdim COMMON_INTERCEPTOR_READ_RANGE( 7050341825Sdim ctx, &sanitizer_handle->handle_bytes, 7051341825Sdim sizeof(sanitizer_handle->handle_bytes)); 7052341825Sdim 7053341825Sdim int res = REAL(name_to_handle_at)(dirfd, pathname, handle, mount_id, flags); 7054341825Sdim if (!res) { 7055341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE( 7056341825Sdim ctx, &sanitizer_handle->handle_bytes, 7057341825Sdim sizeof(sanitizer_handle->handle_bytes)); 7058341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE( 7059341825Sdim ctx, &sanitizer_handle->handle_type, 7060341825Sdim sizeof(sanitizer_handle->handle_type)); 7061341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE( 7062341825Sdim ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes); 7063341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mount_id, sizeof(*mount_id)); 7064341825Sdim } 7065341825Sdim return res; 7066341825Sdim} 7067341825Sdim 7068341825Sdim#define INIT_NAME_TO_HANDLE_AT COMMON_INTERCEPT_FUNCTION(name_to_handle_at) 7069341825Sdim#else 7070341825Sdim#define INIT_NAME_TO_HANDLE_AT 7071341825Sdim#endif 7072341825Sdim 7073341825Sdim#if SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT 7074341825SdimINTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle, 7075341825Sdim int flags) { 7076341825Sdim void* ctx; 7077341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, open_by_handle_at, mount_fd, handle, flags); 7078341825Sdim 7079341825Sdim __sanitizer_file_handle *sanitizer_handle = 7080341825Sdim reinterpret_cast<__sanitizer_file_handle*>(handle); 7081341825Sdim COMMON_INTERCEPTOR_READ_RANGE( 7082341825Sdim ctx, &sanitizer_handle->handle_bytes, 7083341825Sdim sizeof(sanitizer_handle->handle_bytes)); 7084341825Sdim COMMON_INTERCEPTOR_READ_RANGE( 7085341825Sdim ctx, &sanitizer_handle->handle_type, 7086341825Sdim sizeof(sanitizer_handle->handle_type)); 7087341825Sdim COMMON_INTERCEPTOR_READ_RANGE( 7088341825Sdim ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes); 7089341825Sdim 7090341825Sdim return REAL(open_by_handle_at)(mount_fd, handle, flags); 7091341825Sdim} 7092341825Sdim 7093341825Sdim#define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at) 7094341825Sdim#else 7095341825Sdim#define INIT_OPEN_BY_HANDLE_AT 7096341825Sdim#endif 7097341825Sdim 7098341825Sdim#if SANITIZER_INTERCEPT_STRLCPY 7099341825SdimINTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) { 7100341825Sdim void *ctx; 7101341825Sdim SIZE_T res; 7102341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, strlcpy, dst, src, size); 7103341825Sdim if (src) { 7104341825Sdim // Keep strnlen as macro argument, as macro may ignore it. 7105341825Sdim COMMON_INTERCEPTOR_READ_STRING( 7106341825Sdim ctx, src, Min(internal_strnlen(src, size), size - 1) + 1); 7107341825Sdim } 7108341825Sdim res = REAL(strlcpy)(dst, src, size); 7109341825Sdim COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, REAL(strlen)(dst) + 1); 7110341825Sdim return res; 7111341825Sdim} 7112341825Sdim 7113341825SdimINTERCEPTOR(SIZE_T, strlcat, char *dst, char *src, SIZE_T size) { 7114341825Sdim void *ctx; 7115341825Sdim SIZE_T len = 0; 7116341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, strlcat, dst, src, size); 7117341825Sdim // src is checked in the strlcpy() interceptor 7118341825Sdim if (dst) { 7119341825Sdim len = internal_strnlen(dst, size); 7120341825Sdim COMMON_INTERCEPTOR_READ_STRING(ctx, dst, Min(len, size - 1) + 1); 7121341825Sdim } 7122341825Sdim // Reuse the rest of the code in the strlcpy() interceptor 7123341825Sdim return WRAP(strlcpy)(dst + len, src, size - len) + len; 7124341825Sdim} 7125341825Sdim#define INIT_STRLCPY \ 7126341825Sdim COMMON_INTERCEPT_FUNCTION(strlcpy); \ 7127341825Sdim COMMON_INTERCEPT_FUNCTION(strlcat); 7128341825Sdim#else 7129341825Sdim#define INIT_STRLCPY 7130341825Sdim#endif 7131341825Sdim 7132341825Sdim#if SANITIZER_INTERCEPT_MMAP 7133341825SdimINTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd, 7134341825Sdim OFF_T off) { 7135341825Sdim void *ctx; 7136341825Sdim if (common_flags()->detect_write_exec) 7137341825Sdim ReportMmapWriteExec(prot); 7138341825Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 7139341825Sdim return (void *)internal_mmap(addr, sz, prot, flags, fd, off); 7140341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off); 7141341825Sdim COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, off); 7142341825Sdim} 7143341825Sdim 7144341825SdimINTERCEPTOR(int, mprotect, void *addr, SIZE_T sz, int prot) { 7145341825Sdim void *ctx; 7146341825Sdim if (common_flags()->detect_write_exec) 7147341825Sdim ReportMmapWriteExec(prot); 7148341825Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 7149341825Sdim return (int)internal_mprotect(addr, sz, prot); 7150341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, mprotect, addr, sz, prot); 7151341825Sdim MprotectMallocZones(addr, prot); 7152341825Sdim return REAL(mprotect)(addr, sz, prot); 7153341825Sdim} 7154341825Sdim#define INIT_MMAP \ 7155341825Sdim COMMON_INTERCEPT_FUNCTION(mmap); \ 7156341825Sdim COMMON_INTERCEPT_FUNCTION(mprotect); 7157341825Sdim#else 7158341825Sdim#define INIT_MMAP 7159341825Sdim#endif 7160341825Sdim 7161341825Sdim#if SANITIZER_INTERCEPT_MMAP64 7162341825SdimINTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, int fd, 7163341825Sdim OFF64_T off) { 7164341825Sdim void *ctx; 7165341825Sdim if (common_flags()->detect_write_exec) 7166341825Sdim ReportMmapWriteExec(prot); 7167341825Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 7168341825Sdim return (void *)internal_mmap(addr, sz, prot, flags, fd, off); 7169341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off); 7170341825Sdim COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap64, addr, sz, prot, flags, fd, off); 7171341825Sdim} 7172341825Sdim#define INIT_MMAP64 COMMON_INTERCEPT_FUNCTION(mmap64); 7173341825Sdim#else 7174341825Sdim#define INIT_MMAP64 7175341825Sdim#endif 7176341825Sdim 7177341825Sdim#if SANITIZER_INTERCEPT_DEVNAME 7178341825SdimINTERCEPTOR(char *, devname, u64 dev, u32 type) { 7179341825Sdim void *ctx; 7180341825Sdim char *name; 7181341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, devname, dev, type); 7182341825Sdim name = REAL(devname)(dev, type); 7183341825Sdim if (name) 7184341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1); 7185341825Sdim return name; 7186341825Sdim} 7187341825Sdim#define INIT_DEVNAME COMMON_INTERCEPT_FUNCTION(devname); 7188341825Sdim#else 7189341825Sdim#define INIT_DEVNAME 7190341825Sdim#endif 7191341825Sdim 7192341825Sdim#if SANITIZER_INTERCEPT_DEVNAME_R 7193344779Sdim#if SANITIZER_NETBSD 7194344779Sdim#define DEVNAME_R_RETTYPE int 7195344779Sdim#define DEVNAME_R_SUCCESS(x) (!(x)) 7196344779Sdim#else 7197344779Sdim#define DEVNAME_R_RETTYPE char* 7198344779Sdim#define DEVNAME_R_SUCCESS(x) (x) 7199344779Sdim#endif 7200344779SdimINTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path, 7201344779Sdim uptr len) { 7202341825Sdim void *ctx; 7203341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len); 7204344779Sdim DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len); 7205344779Sdim if (DEVNAME_R_SUCCESS(res)) 7206341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, REAL(strlen)(path) + 1); 7207341825Sdim return res; 7208341825Sdim} 7209341825Sdim#define INIT_DEVNAME_R COMMON_INTERCEPT_FUNCTION(devname_r); 7210341825Sdim#else 7211341825Sdim#define INIT_DEVNAME_R 7212341825Sdim#endif 7213341825Sdim 7214341825Sdim#if SANITIZER_INTERCEPT_FGETLN 7215341825SdimINTERCEPTOR(char *, fgetln, __sanitizer_FILE *stream, SIZE_T *len) { 7216341825Sdim void *ctx; 7217341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, fgetln, stream, len); 7218341825Sdim char *str = REAL(fgetln)(stream, len); 7219341825Sdim if (str && len) { 7220341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len)); 7221341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, *len); 7222341825Sdim } 7223341825Sdim return str; 7224341825Sdim} 7225341825Sdim#define INIT_FGETLN COMMON_INTERCEPT_FUNCTION(fgetln) 7226341825Sdim#else 7227341825Sdim#define INIT_FGETLN 7228341825Sdim#endif 7229341825Sdim 7230341825Sdim#if SANITIZER_INTERCEPT_STRMODE 7231341825SdimINTERCEPTOR(void, strmode, u32 mode, char *bp) { 7232341825Sdim void *ctx; 7233341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, strmode, mode, bp); 7234341825Sdim REAL(strmode)(mode, bp); 7235341825Sdim if (bp) 7236341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, REAL(strlen)(bp) + 1); 7237341825Sdim} 7238341825Sdim#define INIT_STRMODE COMMON_INTERCEPT_FUNCTION(strmode) 7239341825Sdim#else 7240341825Sdim#define INIT_STRMODE 7241341825Sdim#endif 7242341825Sdim 7243341825Sdim#if SANITIZER_INTERCEPT_TTYENT 7244341825SdimINTERCEPTOR(struct __sanitizer_ttyent *, getttyent, void) { 7245341825Sdim void *ctx; 7246341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getttyent); 7247341825Sdim struct __sanitizer_ttyent *ttyent = REAL(getttyent)(); 7248341825Sdim if (ttyent) 7249341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz); 7250341825Sdim return ttyent; 7251341825Sdim} 7252341825SdimINTERCEPTOR(struct __sanitizer_ttyent *, getttynam, char *name) { 7253341825Sdim void *ctx; 7254341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getttynam, name); 7255341825Sdim if (name) 7256341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 7257341825Sdim struct __sanitizer_ttyent *ttyent = REAL(getttynam)(name); 7258341825Sdim if (ttyent) 7259341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz); 7260341825Sdim return ttyent; 7261341825Sdim} 7262341825SdimINTERCEPTOR(int, setttyentpath, char *path) { 7263341825Sdim void *ctx; 7264341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, setttyentpath, path); 7265341825Sdim if (path) 7266341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 7267341825Sdim return REAL(setttyentpath)(path); 7268341825Sdim} 7269341825Sdim#define INIT_TTYENT \ 7270341825Sdim COMMON_INTERCEPT_FUNCTION(getttyent); \ 7271341825Sdim COMMON_INTERCEPT_FUNCTION(getttynam); \ 7272341825Sdim COMMON_INTERCEPT_FUNCTION(setttyentpath) 7273341825Sdim#else 7274341825Sdim#define INIT_TTYENT 7275341825Sdim#endif 7276341825Sdim 7277341825Sdim#if SANITIZER_INTERCEPT_PROTOENT 7278341825SdimINTERCEPTOR(struct __sanitizer_protoent *, getprotoent) { 7279341825Sdim void *ctx; 7280341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getprotoent); 7281341825Sdim struct __sanitizer_protoent *p = REAL(getprotoent)(); 7282341825Sdim if (p) { 7283341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); 7284341825Sdim 7285341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1); 7286341825Sdim 7287341825Sdim SIZE_T pp_size = 1; // One handles the trailing \0 7288341825Sdim 7289341825Sdim for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size) 7290341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1); 7291341825Sdim 7292341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, 7293341825Sdim pp_size * sizeof(char **)); 7294341825Sdim } 7295341825Sdim return p; 7296341825Sdim} 7297341825Sdim 7298341825SdimINTERCEPTOR(struct __sanitizer_protoent *, getprotobyname, const char *name) { 7299341825Sdim void *ctx; 7300341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname, name); 7301341825Sdim if (name) 7302341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 7303341825Sdim struct __sanitizer_protoent *p = REAL(getprotobyname)(name); 7304341825Sdim if (p) { 7305341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); 7306341825Sdim 7307341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1); 7308341825Sdim 7309341825Sdim SIZE_T pp_size = 1; // One handles the trailing \0 7310341825Sdim 7311341825Sdim for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size) 7312341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1); 7313341825Sdim 7314341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, 7315341825Sdim pp_size * sizeof(char **)); 7316341825Sdim } 7317341825Sdim return p; 7318341825Sdim} 7319341825Sdim 7320341825SdimINTERCEPTOR(struct __sanitizer_protoent *, getprotobynumber, int proto) { 7321341825Sdim void *ctx; 7322341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber, proto); 7323341825Sdim struct __sanitizer_protoent *p = REAL(getprotobynumber)(proto); 7324341825Sdim if (p) { 7325341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); 7326341825Sdim 7327341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1); 7328341825Sdim 7329341825Sdim SIZE_T pp_size = 1; // One handles the trailing \0 7330341825Sdim 7331341825Sdim for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size) 7332341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1); 7333341825Sdim 7334341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, 7335341825Sdim pp_size * sizeof(char **)); 7336341825Sdim } 7337341825Sdim return p; 7338341825Sdim} 7339341825Sdim#define INIT_PROTOENT \ 7340341825Sdim COMMON_INTERCEPT_FUNCTION(getprotoent); \ 7341341825Sdim COMMON_INTERCEPT_FUNCTION(getprotobyname); \ 7342341825Sdim COMMON_INTERCEPT_FUNCTION(getprotobynumber) 7343341825Sdim#else 7344341825Sdim#define INIT_PROTOENT 7345341825Sdim#endif 7346341825Sdim 7347341825Sdim#if SANITIZER_INTERCEPT_NETENT 7348341825SdimINTERCEPTOR(struct __sanitizer_netent *, getnetent) { 7349341825Sdim void *ctx; 7350341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getnetent); 7351341825Sdim struct __sanitizer_netent *n = REAL(getnetent)(); 7352341825Sdim if (n) { 7353341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); 7354341825Sdim 7355341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1); 7356341825Sdim 7357341825Sdim SIZE_T nn_size = 1; // One handles the trailing \0 7358341825Sdim 7359341825Sdim for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) 7360341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1); 7361341825Sdim 7362341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, 7363341825Sdim nn_size * sizeof(char **)); 7364341825Sdim } 7365341825Sdim return n; 7366341825Sdim} 7367341825Sdim 7368341825SdimINTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) { 7369341825Sdim void *ctx; 7370341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name); 7371341825Sdim if (name) 7372341825Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 7373341825Sdim struct __sanitizer_netent *n = REAL(getnetbyname)(name); 7374341825Sdim if (n) { 7375341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); 7376341825Sdim 7377341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1); 7378341825Sdim 7379341825Sdim SIZE_T nn_size = 1; // One handles the trailing \0 7380341825Sdim 7381341825Sdim for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) 7382341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1); 7383341825Sdim 7384341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, 7385341825Sdim nn_size * sizeof(char **)); 7386341825Sdim } 7387341825Sdim return n; 7388341825Sdim} 7389341825Sdim 7390341825SdimINTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) { 7391341825Sdim void *ctx; 7392341825Sdim COMMON_INTERCEPTOR_ENTER(ctx, getnetbyaddr, net, type); 7393341825Sdim struct __sanitizer_netent *n = REAL(getnetbyaddr)(net, type); 7394341825Sdim if (n) { 7395341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); 7396341825Sdim 7397341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1); 7398341825Sdim 7399341825Sdim SIZE_T nn_size = 1; // One handles the trailing \0 7400341825Sdim 7401341825Sdim for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) 7402341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1); 7403341825Sdim 7404341825Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, 7405341825Sdim nn_size * sizeof(char **)); 7406341825Sdim } 7407341825Sdim return n; 7408341825Sdim} 7409341825Sdim#define INIT_NETENT \ 7410341825Sdim COMMON_INTERCEPT_FUNCTION(getnetent); \ 7411341825Sdim COMMON_INTERCEPT_FUNCTION(getnetbyname); \ 7412341825Sdim COMMON_INTERCEPT_FUNCTION(getnetbyaddr) 7413341825Sdim#else 7414341825Sdim#define INIT_NETENT 7415341825Sdim#endif 7416341825Sdim 7417344779Sdim#if SANITIZER_INTERCEPT_GETMNTINFO 7418344779SdimINTERCEPTOR(int, getmntinfo, void **mntbufp, int flags) { 7419344779Sdim void *ctx; 7420344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, getmntinfo, mntbufp, flags); 7421344779Sdim int cnt = REAL(getmntinfo)(mntbufp, flags); 7422344779Sdim if (cnt > 0 && mntbufp) { 7423344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *)); 7424344779Sdim if (*mntbufp) 7425344779Sdim#if SANITIZER_NETBSD 7426344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs_sz); 7427344779Sdim#else 7428344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statfs_sz); 7429344779Sdim#endif 7430344779Sdim } 7431344779Sdim return cnt; 7432344779Sdim} 7433344779Sdim#define INIT_GETMNTINFO COMMON_INTERCEPT_FUNCTION(getmntinfo) 7434344779Sdim#else 7435344779Sdim#define INIT_GETMNTINFO 7436344779Sdim#endif 7437344779Sdim 7438344779Sdim#if SANITIZER_INTERCEPT_MI_VECTOR_HASH 7439344779SdimINTERCEPTOR(void, mi_vector_hash, const void *key, SIZE_T len, u32 seed, 7440344779Sdim u32 hashes[3]) { 7441344779Sdim void *ctx; 7442344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, mi_vector_hash, key, len, seed, hashes); 7443344779Sdim if (key) 7444344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, key, len); 7445344779Sdim REAL(mi_vector_hash)(key, len, seed, hashes); 7446344779Sdim if (hashes) 7447344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hashes, sizeof(hashes[0]) * 3); 7448344779Sdim} 7449344779Sdim#define INIT_MI_VECTOR_HASH COMMON_INTERCEPT_FUNCTION(mi_vector_hash) 7450344779Sdim#else 7451344779Sdim#define INIT_MI_VECTOR_HASH 7452344779Sdim#endif 7453344779Sdim 7454344779Sdim#if SANITIZER_INTERCEPT_SETVBUF 7455344779SdimINTERCEPTOR(int, setvbuf, __sanitizer_FILE *stream, char *buf, int mode, 7456344779Sdim SIZE_T size) { 7457344779Sdim void *ctx; 7458344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, setvbuf, stream, buf, mode, size); 7459344779Sdim int ret = REAL(setvbuf)(stream, buf, mode, size); 7460344779Sdim if (buf) 7461344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size); 7462344779Sdim if (stream) 7463344779Sdim unpoison_file(stream); 7464344779Sdim return ret; 7465344779Sdim} 7466344779Sdim 7467344779SdimINTERCEPTOR(void, setbuf, __sanitizer_FILE *stream, char *buf) { 7468344779Sdim void *ctx; 7469344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, setbuf, stream, buf); 7470344779Sdim REAL(setbuf)(stream, buf); 7471344779Sdim if (buf) { 7472344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz); 7473344779Sdim } 7474344779Sdim if (stream) 7475344779Sdim unpoison_file(stream); 7476344779Sdim} 7477344779Sdim 7478344779SdimINTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, int mode) { 7479344779Sdim void *ctx; 7480344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, mode); 7481344779Sdim REAL(setbuffer)(stream, buf, mode); 7482344779Sdim if (buf) { 7483344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz); 7484344779Sdim } 7485344779Sdim if (stream) 7486344779Sdim unpoison_file(stream); 7487344779Sdim} 7488344779Sdim 7489344779SdimINTERCEPTOR(void, setlinebuf, __sanitizer_FILE *stream) { 7490344779Sdim void *ctx; 7491344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, setlinebuf, stream); 7492344779Sdim REAL(setlinebuf)(stream); 7493344779Sdim if (stream) 7494344779Sdim unpoison_file(stream); 7495344779Sdim} 7496344779Sdim#define INIT_SETVBUF COMMON_INTERCEPT_FUNCTION(setvbuf); \ 7497344779Sdim COMMON_INTERCEPT_FUNCTION(setbuf); \ 7498344779Sdim COMMON_INTERCEPT_FUNCTION(setbuffer); \ 7499344779Sdim COMMON_INTERCEPT_FUNCTION(setlinebuf) 7500344779Sdim#else 7501344779Sdim#define INIT_SETVBUF 7502344779Sdim#endif 7503344779Sdim 7504344779Sdim#if SANITIZER_INTERCEPT_GETVFSSTAT 7505344779SdimINTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) { 7506344779Sdim void *ctx; 7507344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags); 7508344779Sdim int ret = REAL(getvfsstat)(buf, bufsize, flags); 7509344779Sdim if (buf && ret > 0) 7510344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs_sz); 7511344779Sdim return ret; 7512344779Sdim} 7513344779Sdim#define INIT_GETVFSSTAT COMMON_INTERCEPT_FUNCTION(getvfsstat) 7514344779Sdim#else 7515344779Sdim#define INIT_GETVFSSTAT 7516344779Sdim#endif 7517344779Sdim 7518344779Sdim#if SANITIZER_INTERCEPT_REGEX 7519344779SdimINTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) { 7520344779Sdim void *ctx; 7521344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags); 7522344779Sdim if (pattern) 7523344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, REAL(strlen)(pattern) + 1); 7524344779Sdim int res = REAL(regcomp)(preg, pattern, cflags); 7525344779Sdim if (!res) 7526344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz); 7527344779Sdim return res; 7528344779Sdim} 7529344779SdimINTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch, 7530344779Sdim struct __sanitizer_regmatch *pmatch[], int eflags) { 7531344779Sdim void *ctx; 7532344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, regexec, preg, string, nmatch, pmatch, eflags); 7533344779Sdim if (preg) 7534344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz); 7535344779Sdim if (string) 7536344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, string, REAL(strlen)(string) + 1); 7537344779Sdim int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags); 7538344779Sdim if (!res && pmatch) 7539344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz); 7540344779Sdim return res; 7541344779Sdim} 7542344779SdimINTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf, 7543344779Sdim SIZE_T errbuf_size) { 7544344779Sdim void *ctx; 7545344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, regerror, errcode, preg, errbuf, errbuf_size); 7546344779Sdim if (preg) 7547344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz); 7548344779Sdim SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size); 7549344779Sdim if (errbuf) 7550344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, REAL(strlen)(errbuf) + 1); 7551344779Sdim return res; 7552344779Sdim} 7553344779SdimINTERCEPTOR(void, regfree, const void *preg) { 7554344779Sdim void *ctx; 7555344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, regfree, preg); 7556344779Sdim if (preg) 7557344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz); 7558344779Sdim REAL(regfree)(preg); 7559344779Sdim} 7560344779Sdim#define INIT_REGEX \ 7561344779Sdim COMMON_INTERCEPT_FUNCTION(regcomp); \ 7562344779Sdim COMMON_INTERCEPT_FUNCTION(regexec); \ 7563344779Sdim COMMON_INTERCEPT_FUNCTION(regerror); \ 7564344779Sdim COMMON_INTERCEPT_FUNCTION(regfree); 7565344779Sdim#else 7566344779Sdim#define INIT_REGEX 7567344779Sdim#endif 7568344779Sdim 7569344779Sdim#if SANITIZER_INTERCEPT_REGEXSUB 7570344779SdimINTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub, 7571344779Sdim const struct __sanitizer_regmatch *rm, const char *str) { 7572344779Sdim void *ctx; 7573344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str); 7574344779Sdim if (sub) 7575344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1); 7576344779Sdim // The implementation demands and hardcodes 10 elements 7577344779Sdim if (rm) 7578344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz); 7579344779Sdim if (str) 7580344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1); 7581344779Sdim SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str); 7582344779Sdim if (res > 0 && buf) 7583344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1); 7584344779Sdim return res; 7585344779Sdim} 7586344779SdimINTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub, 7587344779Sdim const struct __sanitizer_regmatch *rm, const char *sstr) { 7588344779Sdim void *ctx; 7589344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr); 7590344779Sdim if (sub) 7591344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1); 7592344779Sdim // Hardcode 10 elements as this is hardcoded size 7593344779Sdim if (rm) 7594344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz); 7595344779Sdim if (sstr) 7596344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, REAL(strlen)(sstr) + 1); 7597344779Sdim SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr); 7598344779Sdim if (res > 0 && buf) { 7599344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *)); 7600344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, REAL(strlen)(*buf) + 1); 7601344779Sdim } 7602344779Sdim return res; 7603344779Sdim} 7604344779Sdim 7605344779Sdim#define INIT_REGEXSUB \ 7606344779Sdim COMMON_INTERCEPT_FUNCTION(regnsub); \ 7607344779Sdim COMMON_INTERCEPT_FUNCTION(regasub); 7608344779Sdim#else 7609344779Sdim#define INIT_REGEXSUB 7610344779Sdim#endif 7611344779Sdim 7612344779Sdim#if SANITIZER_INTERCEPT_FTS 7613344779SdimINTERCEPTOR(void *, fts_open, char *const *path_argv, int options, 7614344779Sdim int (*compar)(void **, void **)) { 7615344779Sdim void *ctx; 7616344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fts_open, path_argv, options, compar); 7617344779Sdim if (path_argv) { 7618344779Sdim for (char *const *pa = path_argv; ; ++pa) { 7619344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **)); 7620344779Sdim if (!*pa) 7621344779Sdim break; 7622344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1); 7623344779Sdim } 7624344779Sdim } 7625344779Sdim // TODO(kamil): handle compar callback 7626344779Sdim void *fts = REAL(fts_open)(path_argv, options, compar); 7627344779Sdim if (fts) 7628344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, fts, struct_FTS_sz); 7629344779Sdim return fts; 7630344779Sdim} 7631344779Sdim 7632344779SdimINTERCEPTOR(void *, fts_read, void *ftsp) { 7633344779Sdim void *ctx; 7634344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fts_read, ftsp); 7635344779Sdim if (ftsp) 7636344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz); 7637344779Sdim void *ftsent = REAL(fts_read)(ftsp); 7638344779Sdim if (ftsent) 7639344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz); 7640344779Sdim return ftsent; 7641344779Sdim} 7642344779Sdim 7643344779SdimINTERCEPTOR(void *, fts_children, void *ftsp, int options) { 7644344779Sdim void *ctx; 7645344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fts_children, ftsp, options); 7646344779Sdim if (ftsp) 7647344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz); 7648344779Sdim void *ftsent = REAL(fts_children)(ftsp, options); 7649344779Sdim if (ftsent) 7650344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz); 7651344779Sdim return ftsent; 7652344779Sdim} 7653344779Sdim 7654344779SdimINTERCEPTOR(int, fts_set, void *ftsp, void *f, int options) { 7655344779Sdim void *ctx; 7656344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fts_set, ftsp, f, options); 7657344779Sdim if (ftsp) 7658344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz); 7659344779Sdim if (f) 7660344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, f, struct_FTSENT_sz); 7661344779Sdim return REAL(fts_set)(ftsp, f, options); 7662344779Sdim} 7663344779Sdim 7664344779SdimINTERCEPTOR(int, fts_close, void *ftsp) { 7665344779Sdim void *ctx; 7666344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fts_close, ftsp); 7667344779Sdim if (ftsp) 7668344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz); 7669344779Sdim return REAL(fts_close)(ftsp); 7670344779Sdim} 7671344779Sdim#define INIT_FTS \ 7672344779Sdim COMMON_INTERCEPT_FUNCTION(fts_open); \ 7673344779Sdim COMMON_INTERCEPT_FUNCTION(fts_read); \ 7674344779Sdim COMMON_INTERCEPT_FUNCTION(fts_children); \ 7675344779Sdim COMMON_INTERCEPT_FUNCTION(fts_set); \ 7676344779Sdim COMMON_INTERCEPT_FUNCTION(fts_close); 7677344779Sdim#else 7678344779Sdim#define INIT_FTS 7679344779Sdim#endif 7680344779Sdim 7681344779Sdim#if SANITIZER_INTERCEPT_SYSCTL 7682344779SdimINTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp, 7683344779Sdim SIZE_T *oldlenp, void *newp, SIZE_T newlen) { 7684344779Sdim void *ctx; 7685344779Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 7686344779Sdim return internal_sysctl(name, namelen, oldp, oldlenp, newp, newlen); 7687344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp, 7688344779Sdim newlen); 7689344779Sdim if (name) 7690344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, namelen * sizeof(*name)); 7691344779Sdim if (oldlenp) 7692344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp)); 7693344779Sdim if (newp && newlen) 7694344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen); 7695344779Sdim int res = REAL(sysctl)(name, namelen, oldp, oldlenp, newp, newlen); 7696344779Sdim if (!res) { 7697344779Sdim if (oldlenp) { 7698344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp)); 7699344779Sdim if (oldp) 7700344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp); 7701344779Sdim } 7702344779Sdim } 7703344779Sdim return res; 7704344779Sdim} 7705344779Sdim 7706344779SdimINTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp, 7707344779Sdim void *newp, SIZE_T newlen) { 7708344779Sdim void *ctx; 7709344779Sdim if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) 7710344779Sdim return internal_sysctlbyname(sname, oldp, oldlenp, newp, newlen); 7711344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp, 7712344779Sdim newlen); 7713344779Sdim if (sname) 7714344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1); 7715344779Sdim if (oldlenp) 7716344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp)); 7717344779Sdim if (newp && newlen) 7718344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen); 7719344779Sdim int res = REAL(sysctlbyname)(sname, oldp, oldlenp, newp, newlen); 7720344779Sdim if (!res) { 7721344779Sdim if (oldlenp) { 7722344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp)); 7723344779Sdim if (oldp) 7724344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp); 7725344779Sdim } 7726344779Sdim } 7727344779Sdim return res; 7728344779Sdim} 7729344779Sdim 7730344779SdimINTERCEPTOR(int, sysctlnametomib, const char *sname, int *name, 7731344779Sdim SIZE_T *namelenp) { 7732344779Sdim void *ctx; 7733344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp); 7734344779Sdim if (sname) 7735344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1); 7736344779Sdim if (namelenp) 7737344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp)); 7738344779Sdim int res = REAL(sysctlnametomib)(sname, name, namelenp); 7739344779Sdim if (!res) { 7740344779Sdim if (namelenp) { 7741344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp)); 7742344779Sdim if (name) 7743344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name)); 7744344779Sdim } 7745344779Sdim } 7746344779Sdim return res; 7747344779Sdim} 7748344779Sdim 7749344779Sdim#define INIT_SYSCTL \ 7750344779Sdim COMMON_INTERCEPT_FUNCTION(sysctl); \ 7751344779Sdim COMMON_INTERCEPT_FUNCTION(sysctlbyname); \ 7752344779Sdim COMMON_INTERCEPT_FUNCTION(sysctlnametomib); 7753344779Sdim#else 7754344779Sdim#define INIT_SYSCTL 7755344779Sdim#endif 7756344779Sdim 7757344779Sdim#if SANITIZER_INTERCEPT_ASYSCTL 7758344779SdimINTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) { 7759344779Sdim void *ctx; 7760344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len); 7761344779Sdim if (name) 7762344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, sizeof(*name) * namelen); 7763344779Sdim void *res = REAL(asysctl)(name, namelen, len); 7764344779Sdim if (res && len) { 7765344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len)); 7766344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len); 7767344779Sdim } 7768344779Sdim return res; 7769344779Sdim} 7770344779Sdim 7771344779SdimINTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) { 7772344779Sdim void *ctx; 7773344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len); 7774344779Sdim if (sname) 7775344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1); 7776344779Sdim void *res = REAL(asysctlbyname)(sname, len); 7777344779Sdim if (res && len) { 7778344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len)); 7779344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len); 7780344779Sdim } 7781344779Sdim return res; 7782344779Sdim} 7783344779Sdim#define INIT_ASYSCTL \ 7784344779Sdim COMMON_INTERCEPT_FUNCTION(asysctl); \ 7785344779Sdim COMMON_INTERCEPT_FUNCTION(asysctlbyname); 7786344779Sdim#else 7787344779Sdim#define INIT_ASYSCTL 7788344779Sdim#endif 7789344779Sdim 7790344779Sdim#if SANITIZER_INTERCEPT_SYSCTLGETMIBINFO 7791344779SdimINTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name, 7792344779Sdim unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode, 7793344779Sdim int v) { 7794344779Sdim void *ctx; 7795344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname, 7796344779Sdim csz, rnode, v); 7797344779Sdim if (sname) 7798344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1); 7799344779Sdim if (namelenp) 7800344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp)); 7801344779Sdim if (csz) 7802344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz)); 7803344779Sdim // Skip rnode, it's rarely used and not trivial to sanitize 7804344779Sdim // It's also used mostly internally 7805344779Sdim int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v); 7806344779Sdim if (!res) { 7807344779Sdim if (namelenp) { 7808344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp)); 7809344779Sdim if (name) 7810344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name)); 7811344779Sdim } 7812344779Sdim if (csz) { 7813344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz)); 7814344779Sdim if (cname) 7815344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz); 7816344779Sdim } 7817344779Sdim } 7818344779Sdim return res; 7819344779Sdim} 7820344779Sdim#define INIT_SYSCTLGETMIBINFO \ 7821344779Sdim COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo); 7822344779Sdim#else 7823344779Sdim#define INIT_SYSCTLGETMIBINFO 7824344779Sdim#endif 7825344779Sdim 7826344779Sdim#if SANITIZER_INTERCEPT_NL_LANGINFO 7827344779SdimINTERCEPTOR(char *, nl_langinfo, long item) { 7828344779Sdim void *ctx; 7829344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item); 7830344779Sdim char *ret = REAL(nl_langinfo)(item); 7831344779Sdim if (ret) 7832344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1); 7833344779Sdim return ret; 7834344779Sdim} 7835344779Sdim#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo) 7836344779Sdim#else 7837344779Sdim#define INIT_NL_LANGINFO 7838344779Sdim#endif 7839344779Sdim 7840344779Sdim#if SANITIZER_INTERCEPT_MODCTL 7841344779SdimINTERCEPTOR(int, modctl, int operation, void *argp) { 7842344779Sdim void *ctx; 7843344779Sdim int ret; 7844344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, modctl, operation, argp); 7845344779Sdim 7846344779Sdim if (operation == modctl_load) { 7847344779Sdim if (argp) { 7848344779Sdim __sanitizer_modctl_load_t *ml = (__sanitizer_modctl_load_t *)argp; 7849344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml)); 7850344779Sdim if (ml->ml_filename) 7851344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename, 7852344779Sdim REAL(strlen)(ml->ml_filename) + 1); 7853344779Sdim if (ml->ml_props) 7854344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen); 7855344779Sdim } 7856344779Sdim ret = REAL(modctl)(operation, argp); 7857344779Sdim } else if (operation == modctl_unload) { 7858344779Sdim if (argp) { 7859344779Sdim const char *name = (const char *)argp; 7860344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); 7861344779Sdim } 7862344779Sdim ret = REAL(modctl)(operation, argp); 7863344779Sdim } else if (operation == modctl_stat) { 7864344779Sdim uptr iov_len; 7865344779Sdim struct __sanitizer_iovec *iov = (struct __sanitizer_iovec *)argp; 7866344779Sdim if (iov) { 7867344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, iov, sizeof(*iov)); 7868344779Sdim iov_len = iov->iov_len; 7869344779Sdim } 7870344779Sdim ret = REAL(modctl)(operation, argp); 7871344779Sdim if (iov) 7872344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE( 7873344779Sdim ctx, iov->iov_base, Min(iov_len, iov->iov_len)); 7874360784Sdim } else if (operation == modctl_exists) { 7875344779Sdim ret = REAL(modctl)(operation, argp); 7876360784Sdim } else { 7877344779Sdim ret = REAL(modctl)(operation, argp); 7878360784Sdim } 7879344779Sdim 7880344779Sdim return ret; 7881344779Sdim} 7882344779Sdim#define INIT_MODCTL COMMON_INTERCEPT_FUNCTION(modctl) 7883344779Sdim#else 7884344779Sdim#define INIT_MODCTL 7885344779Sdim#endif 7886344779Sdim 7887344779Sdim#if SANITIZER_INTERCEPT_STRTONUM 7888344779SdimINTERCEPTOR(long long, strtonum, const char *nptr, long long minval, 7889344779Sdim long long maxval, const char **errstr) { 7890344779Sdim void *ctx; 7891344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strtonum, nptr, minval, maxval, errstr); 7892344779Sdim 7893344779Sdim // TODO(kamil): Implement strtoll as a common inteceptor 7894344779Sdim char *real_endptr; 7895344779Sdim long long ret = (long long)REAL(strtoimax)(nptr, &real_endptr, 10); 7896344779Sdim StrtolFixAndCheck(ctx, nptr, nullptr, real_endptr, 10); 7897344779Sdim 7898344779Sdim ret = REAL(strtonum)(nptr, minval, maxval, errstr); 7899344779Sdim if (errstr) { 7900344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *)); 7901344779Sdim if (*errstr) 7902344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, REAL(strlen)(*errstr) + 1); 7903344779Sdim } 7904344779Sdim return ret; 7905344779Sdim} 7906344779Sdim#define INIT_STRTONUM COMMON_INTERCEPT_FUNCTION(strtonum) 7907344779Sdim#else 7908344779Sdim#define INIT_STRTONUM 7909344779Sdim#endif 7910344779Sdim 7911344779Sdim#if SANITIZER_INTERCEPT_FPARSELN 7912344779SdimINTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len, 7913344779Sdim SIZE_T *lineno, const char delim[3], int flags) { 7914344779Sdim void *ctx; 7915344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fparseln, stream, len, lineno, delim, flags); 7916344779Sdim if (lineno) 7917344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, lineno, sizeof(*lineno)); 7918344779Sdim if (delim) 7919344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3); 7920344779Sdim char *ret = REAL(fparseln)(stream, len, lineno, delim, flags); 7921344779Sdim if (ret) { 7922344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1); 7923344779Sdim if (len) 7924344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len)); 7925344779Sdim if (lineno) 7926344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineno, sizeof(*lineno)); 7927344779Sdim } 7928344779Sdim return ret; 7929344779Sdim} 7930344779Sdim#define INIT_FPARSELN COMMON_INTERCEPT_FUNCTION(fparseln) 7931344779Sdim#else 7932344779Sdim#define INIT_FPARSELN 7933344779Sdim#endif 7934344779Sdim 7935344779Sdim#if SANITIZER_INTERCEPT_STATVFS1 7936344779SdimINTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) { 7937344779Sdim void *ctx; 7938344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags); 7939344779Sdim if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 7940344779Sdim int res = REAL(statvfs1)(path, buf, flags); 7941344779Sdim if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); 7942344779Sdim return res; 7943344779Sdim} 7944344779SdimINTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) { 7945344779Sdim void *ctx; 7946344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags); 7947344779Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 7948344779Sdim int res = REAL(fstatvfs1)(fd, buf, flags); 7949344779Sdim if (!res) { 7950344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); 7951344779Sdim if (fd >= 0) 7952344779Sdim COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 7953344779Sdim } 7954344779Sdim return res; 7955344779Sdim} 7956344779Sdim#define INIT_STATVFS1 \ 7957344779Sdim COMMON_INTERCEPT_FUNCTION(statvfs1); \ 7958344779Sdim COMMON_INTERCEPT_FUNCTION(fstatvfs1); 7959344779Sdim#else 7960344779Sdim#define INIT_STATVFS1 7961344779Sdim#endif 7962344779Sdim 7963344779Sdim#if SANITIZER_INTERCEPT_STRTOI 7964344779SdimINTERCEPTOR(INTMAX_T, strtoi, const char *nptr, char **endptr, int base, 7965344779Sdim INTMAX_T low, INTMAX_T high, int *rstatus) { 7966344779Sdim void *ctx; 7967344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strtoi, nptr, endptr, base, low, high, rstatus); 7968344779Sdim char *real_endptr; 7969344779Sdim INTMAX_T ret = REAL(strtoi)(nptr, &real_endptr, base, low, high, rstatus); 7970344779Sdim StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 7971344779Sdim if (rstatus) 7972344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus)); 7973344779Sdim return ret; 7974344779Sdim} 7975344779Sdim 7976344779SdimINTERCEPTOR(UINTMAX_T, strtou, const char *nptr, char **endptr, int base, 7977344779Sdim UINTMAX_T low, UINTMAX_T high, int *rstatus) { 7978344779Sdim void *ctx; 7979344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strtou, nptr, endptr, base, low, high, rstatus); 7980344779Sdim char *real_endptr; 7981344779Sdim UINTMAX_T ret = REAL(strtou)(nptr, &real_endptr, base, low, high, rstatus); 7982344779Sdim StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 7983344779Sdim if (rstatus) 7984344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus)); 7985344779Sdim return ret; 7986344779Sdim} 7987344779Sdim#define INIT_STRTOI \ 7988344779Sdim COMMON_INTERCEPT_FUNCTION(strtoi); \ 7989344779Sdim COMMON_INTERCEPT_FUNCTION(strtou) 7990344779Sdim#else 7991344779Sdim#define INIT_STRTOI 7992344779Sdim#endif 7993344779Sdim 7994344779Sdim#if SANITIZER_INTERCEPT_CAPSICUM 7995344779Sdim#define CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights, ...) \ 7996344779Sdim { \ 7997344779Sdim void *ctx; \ 7998344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_init, rights, ##__VA_ARGS__); \ 7999344779Sdim if (rights) \ 8000344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \ 8001344779Sdim __sanitizer_cap_rights_t *ret = \ 8002344779Sdim REAL(cap_rights_init)(rights, ##__VA_ARGS__); \ 8003344779Sdim if (ret) \ 8004344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \ 8005344779Sdim return ret; \ 8006344779Sdim } 8007344779Sdim 8008344779Sdim#define CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights, ...) \ 8009344779Sdim { \ 8010344779Sdim void *ctx; \ 8011344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_set, rights, ##__VA_ARGS__); \ 8012344779Sdim if (rights) \ 8013344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \ 8014344779Sdim __sanitizer_cap_rights_t *ret = \ 8015344779Sdim REAL(cap_rights_set)(rights, ##__VA_ARGS__); \ 8016344779Sdim if (ret) \ 8017344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \ 8018344779Sdim return ret; \ 8019344779Sdim } 8020344779Sdim 8021344779Sdim#define CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights, ...) \ 8022344779Sdim { \ 8023344779Sdim void *ctx; \ 8024344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_clear, rights, ##__VA_ARGS__); \ 8025344779Sdim if (rights) \ 8026344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \ 8027344779Sdim __sanitizer_cap_rights_t *ret = \ 8028344779Sdim REAL(cap_rights_clear)(rights, ##__VA_ARGS__); \ 8029344779Sdim if (ret) \ 8030344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \ 8031344779Sdim return ret; \ 8032344779Sdim } 8033344779Sdim 8034344779Sdim#define CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights, ...) \ 8035344779Sdim { \ 8036344779Sdim void *ctx; \ 8037344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_set, rights, ##__VA_ARGS__); \ 8038344779Sdim if (rights) \ 8039344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \ 8040344779Sdim return REAL(cap_rights_is_set)(rights, ##__VA_ARGS__); \ 8041344779Sdim } 8042344779Sdim 8043344779SdimINTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_init, 8044344779Sdim __sanitizer_cap_rights_t *rights) { 8045344779Sdim CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights); 8046344779Sdim} 8047344779Sdim 8048344779SdimINTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_set, 8049344779Sdim __sanitizer_cap_rights_t *rights) { 8050344779Sdim CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights); 8051344779Sdim} 8052344779Sdim 8053344779SdimINTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_clear, 8054344779Sdim __sanitizer_cap_rights_t *rights) { 8055344779Sdim CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights); 8056344779Sdim} 8057344779Sdim 8058344779SdimINTERCEPTOR(bool, cap_rights_is_set, 8059344779Sdim __sanitizer_cap_rights_t *rights) { 8060344779Sdim CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights); 8061344779Sdim} 8062344779Sdim 8063344779SdimINTERCEPTOR(int, cap_rights_limit, int fd, 8064344779Sdim const __sanitizer_cap_rights_t *rights) { 8065344779Sdim void *ctx; 8066344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_limit, fd, rights); 8067344779Sdim if (rights) 8068344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); 8069344779Sdim 8070344779Sdim return REAL(cap_rights_limit)(fd, rights); 8071344779Sdim} 8072344779Sdim 8073344779SdimINTERCEPTOR(int, cap_rights_get, int fd, __sanitizer_cap_rights_t *rights) { 8074344779Sdim void *ctx; 8075344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_get, fd, rights); 8076344779Sdim int ret = REAL(cap_rights_get)(fd, rights); 8077344779Sdim if (!ret && rights) 8078344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rights, sizeof(*rights)); 8079344779Sdim 8080344779Sdim return ret; 8081344779Sdim} 8082344779Sdim 8083344779SdimINTERCEPTOR(bool, cap_rights_is_valid, const __sanitizer_cap_rights_t *rights) { 8084344779Sdim void *ctx; 8085344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_valid, rights); 8086344779Sdim if (rights) 8087344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); 8088344779Sdim 8089344779Sdim return REAL(cap_rights_is_valid(rights)); 8090344779Sdim} 8091344779Sdim 8092344779SdimINTERCEPTOR(__sanitizer_cap_rights *, cap_rights_merge, 8093344779Sdim __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) { 8094344779Sdim void *ctx; 8095344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_merge, dst, src); 8096344779Sdim if (src) 8097344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src)); 8098344779Sdim 8099344779Sdim __sanitizer_cap_rights *ret = REAL(cap_rights_merge)(dst, src); 8100344779Sdim if (dst) 8101344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst)); 8102344779Sdim 8103344779Sdim return ret; 8104344779Sdim} 8105344779Sdim 8106344779SdimINTERCEPTOR(__sanitizer_cap_rights *, cap_rights_remove, 8107344779Sdim __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) { 8108344779Sdim void *ctx; 8109344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_remove, dst, src); 8110344779Sdim if (src) 8111344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src)); 8112344779Sdim 8113344779Sdim __sanitizer_cap_rights *ret = REAL(cap_rights_remove)(dst, src); 8114344779Sdim if (dst) 8115344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst)); 8116344779Sdim 8117344779Sdim return ret; 8118344779Sdim} 8119344779Sdim 8120344779SdimINTERCEPTOR(bool, cap_rights_contains, const __sanitizer_cap_rights *big, 8121344779Sdim const __sanitizer_cap_rights *little) { 8122344779Sdim void *ctx; 8123344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_contains, big, little); 8124344779Sdim if (little) 8125344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, little, sizeof(*little)); 8126344779Sdim if (big) 8127344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, big, sizeof(*big)); 8128344779Sdim 8129344779Sdim return REAL(cap_rights_contains)(big, little); 8130344779Sdim} 8131344779Sdim 8132344779SdimINTERCEPTOR(int, cap_ioctls_limit, int fd, const uptr *cmds, SIZE_T ncmds) { 8133344779Sdim void *ctx; 8134344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_limit, fd, cmds, ncmds); 8135344779Sdim if (cmds) 8136344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cmds, sizeof(*cmds) * ncmds); 8137344779Sdim 8138344779Sdim return REAL(cap_ioctls_limit)(fd, cmds, ncmds); 8139344779Sdim} 8140344779Sdim 8141344779SdimINTERCEPTOR(int, cap_ioctls_get, int fd, uptr *cmds, SIZE_T maxcmds) { 8142344779Sdim void *ctx; 8143344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_get, fd, cmds, maxcmds); 8144344779Sdim int ret = REAL(cap_ioctls_get)(fd, cmds, maxcmds); 8145344779Sdim if (!ret && cmds) 8146344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cmds, sizeof(*cmds) * maxcmds); 8147344779Sdim 8148344779Sdim return ret; 8149344779Sdim} 8150344779Sdim#define INIT_CAPSICUM \ 8151344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_init); \ 8152344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_set); \ 8153344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_clear); \ 8154344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_is_set); \ 8155344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_get); \ 8156344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_limit); \ 8157344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_contains); \ 8158344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_remove); \ 8159344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_merge); \ 8160344779Sdim COMMON_INTERCEPT_FUNCTION(cap_rights_is_valid); \ 8161344779Sdim COMMON_INTERCEPT_FUNCTION(cap_ioctls_get); \ 8162344779Sdim COMMON_INTERCEPT_FUNCTION(cap_ioctls_limit) 8163344779Sdim#else 8164344779Sdim#define INIT_CAPSICUM 8165344779Sdim#endif 8166344779Sdim 8167344779Sdim#if SANITIZER_INTERCEPT_SHA1 8168344779SdimINTERCEPTOR(void, SHA1Init, void *context) { 8169344779Sdim void *ctx; 8170344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA1Init, context); 8171344779Sdim REAL(SHA1Init)(context); 8172344779Sdim if (context) 8173344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz); 8174344779Sdim} 8175344779SdimINTERCEPTOR(void, SHA1Update, void *context, const u8 *data, unsigned len) { 8176344779Sdim void *ctx; 8177344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA1Update, context, data, len); 8178344779Sdim if (data && len > 0) 8179344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8180344779Sdim if (context) 8181344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz); 8182344779Sdim REAL(SHA1Update)(context, data, len); 8183344779Sdim if (context) 8184344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz); 8185344779Sdim} 8186344779SdimINTERCEPTOR(void, SHA1Final, u8 digest[20], void *context) { 8187344779Sdim void *ctx; 8188344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA1Final, digest, context); 8189344779Sdim if (context) 8190344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz); 8191344779Sdim REAL(SHA1Final)(digest, context); 8192344779Sdim if (digest) 8193344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20); 8194344779Sdim} 8195344779SdimINTERCEPTOR(void, SHA1Transform, u32 state[5], u8 buffer[64]) { 8196344779Sdim void *ctx; 8197344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA1Transform, state, buffer); 8198344779Sdim if (state) 8199344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5); 8200344779Sdim if (buffer) 8201344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u8) * 64); 8202344779Sdim REAL(SHA1Transform)(state, buffer); 8203344779Sdim if (state) 8204344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5); 8205344779Sdim} 8206344779SdimINTERCEPTOR(char *, SHA1End, void *context, char *buf) { 8207344779Sdim void *ctx; 8208344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA1End, context, buf); 8209344779Sdim if (context) 8210344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz); 8211344779Sdim char *ret = REAL(SHA1End)(context, buf); 8212344779Sdim if (ret) 8213344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length); 8214344779Sdim return ret; 8215344779Sdim} 8216344779SdimINTERCEPTOR(char *, SHA1File, char *filename, char *buf) { 8217344779Sdim void *ctx; 8218344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf); 8219344779Sdim if (filename) 8220344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); 8221344779Sdim char *ret = REAL(SHA1File)(filename, buf); 8222344779Sdim if (ret) 8223344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length); 8224344779Sdim return ret; 8225344779Sdim} 8226344779SdimINTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset, 8227344779Sdim OFF_T length) { 8228344779Sdim void *ctx; 8229344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length); 8230344779Sdim if (filename) 8231344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); 8232344779Sdim char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length); 8233344779Sdim if (ret) 8234344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length); 8235344779Sdim return ret; 8236344779Sdim} 8237344779SdimINTERCEPTOR(char *, SHA1Data, u8 *data, SIZE_T len, char *buf) { 8238344779Sdim void *ctx; 8239344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA1Data, data, len, buf); 8240344779Sdim if (data) 8241344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8242344779Sdim char *ret = REAL(SHA1Data)(data, len, buf); 8243344779Sdim if (ret) 8244344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length); 8245344779Sdim return ret; 8246344779Sdim} 8247344779Sdim#define INIT_SHA1 \ 8248344779Sdim COMMON_INTERCEPT_FUNCTION(SHA1Init); \ 8249344779Sdim COMMON_INTERCEPT_FUNCTION(SHA1Update); \ 8250344779Sdim COMMON_INTERCEPT_FUNCTION(SHA1Final); \ 8251344779Sdim COMMON_INTERCEPT_FUNCTION(SHA1Transform); \ 8252344779Sdim COMMON_INTERCEPT_FUNCTION(SHA1End); \ 8253344779Sdim COMMON_INTERCEPT_FUNCTION(SHA1File); \ 8254344779Sdim COMMON_INTERCEPT_FUNCTION(SHA1FileChunk); \ 8255344779Sdim COMMON_INTERCEPT_FUNCTION(SHA1Data) 8256344779Sdim#else 8257344779Sdim#define INIT_SHA1 8258344779Sdim#endif 8259344779Sdim 8260344779Sdim#if SANITIZER_INTERCEPT_MD4 8261344779SdimINTERCEPTOR(void, MD4Init, void *context) { 8262344779Sdim void *ctx; 8263344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD4Init, context); 8264344779Sdim REAL(MD4Init)(context); 8265344779Sdim if (context) 8266344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz); 8267344779Sdim} 8268344779Sdim 8269344779SdimINTERCEPTOR(void, MD4Update, void *context, const unsigned char *data, 8270344779Sdim unsigned int len) { 8271344779Sdim void *ctx; 8272344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD4Update, context, data, len); 8273344779Sdim if (data && len > 0) 8274344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8275344779Sdim if (context) 8276344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz); 8277344779Sdim REAL(MD4Update)(context, data, len); 8278344779Sdim if (context) 8279344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz); 8280344779Sdim} 8281344779Sdim 8282344779SdimINTERCEPTOR(void, MD4Final, unsigned char digest[16], void *context) { 8283344779Sdim void *ctx; 8284344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD4Final, digest, context); 8285344779Sdim if (context) 8286344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz); 8287344779Sdim REAL(MD4Final)(digest, context); 8288344779Sdim if (digest) 8289344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16); 8290344779Sdim} 8291344779Sdim 8292344779SdimINTERCEPTOR(char *, MD4End, void *context, char *buf) { 8293344779Sdim void *ctx; 8294344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD4End, context, buf); 8295344779Sdim if (context) 8296344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz); 8297344779Sdim char *ret = REAL(MD4End)(context, buf); 8298344779Sdim if (ret) 8299344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length); 8300344779Sdim return ret; 8301344779Sdim} 8302344779Sdim 8303344779SdimINTERCEPTOR(char *, MD4File, const char *filename, char *buf) { 8304344779Sdim void *ctx; 8305344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf); 8306344779Sdim if (filename) 8307344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); 8308344779Sdim char *ret = REAL(MD4File)(filename, buf); 8309344779Sdim if (ret) 8310344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length); 8311344779Sdim return ret; 8312344779Sdim} 8313344779Sdim 8314344779SdimINTERCEPTOR(char *, MD4Data, const unsigned char *data, unsigned int len, 8315344779Sdim char *buf) { 8316344779Sdim void *ctx; 8317344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD4Data, data, len, buf); 8318344779Sdim if (data && len > 0) 8319344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8320344779Sdim char *ret = REAL(MD4Data)(data, len, buf); 8321344779Sdim if (ret) 8322344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length); 8323344779Sdim return ret; 8324344779Sdim} 8325344779Sdim 8326344779Sdim#define INIT_MD4 \ 8327344779Sdim COMMON_INTERCEPT_FUNCTION(MD4Init); \ 8328344779Sdim COMMON_INTERCEPT_FUNCTION(MD4Update); \ 8329344779Sdim COMMON_INTERCEPT_FUNCTION(MD4Final); \ 8330344779Sdim COMMON_INTERCEPT_FUNCTION(MD4End); \ 8331344779Sdim COMMON_INTERCEPT_FUNCTION(MD4File); \ 8332344779Sdim COMMON_INTERCEPT_FUNCTION(MD4Data) 8333344779Sdim#else 8334344779Sdim#define INIT_MD4 8335344779Sdim#endif 8336344779Sdim 8337344779Sdim#if SANITIZER_INTERCEPT_RMD160 8338344779SdimINTERCEPTOR(void, RMD160Init, void *context) { 8339344779Sdim void *ctx; 8340344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, RMD160Init, context); 8341344779Sdim REAL(RMD160Init)(context); 8342344779Sdim if (context) 8343344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz); 8344344779Sdim} 8345344779SdimINTERCEPTOR(void, RMD160Update, void *context, const u8 *data, unsigned len) { 8346344779Sdim void *ctx; 8347344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, RMD160Update, context, data, len); 8348344779Sdim if (data && len > 0) 8349344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8350344779Sdim if (context) 8351344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz); 8352344779Sdim REAL(RMD160Update)(context, data, len); 8353344779Sdim if (context) 8354344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz); 8355344779Sdim} 8356344779SdimINTERCEPTOR(void, RMD160Final, u8 digest[20], void *context) { 8357344779Sdim void *ctx; 8358344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, RMD160Final, digest, context); 8359344779Sdim if (context) 8360344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz); 8361344779Sdim REAL(RMD160Final)(digest, context); 8362344779Sdim if (digest) 8363344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20); 8364344779Sdim} 8365344779SdimINTERCEPTOR(void, RMD160Transform, u32 state[5], u16 buffer[16]) { 8366344779Sdim void *ctx; 8367344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, RMD160Transform, state, buffer); 8368344779Sdim if (state) 8369344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5); 8370344779Sdim if (buffer) 8371344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u32) * 16); 8372344779Sdim REAL(RMD160Transform)(state, buffer); 8373344779Sdim if (state) 8374344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5); 8375344779Sdim} 8376344779SdimINTERCEPTOR(char *, RMD160End, void *context, char *buf) { 8377344779Sdim void *ctx; 8378344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, RMD160End, context, buf); 8379344779Sdim if (context) 8380344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz); 8381344779Sdim char *ret = REAL(RMD160End)(context, buf); 8382344779Sdim if (ret) 8383344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length); 8384344779Sdim return ret; 8385344779Sdim} 8386344779SdimINTERCEPTOR(char *, RMD160File, char *filename, char *buf) { 8387344779Sdim void *ctx; 8388344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf); 8389344779Sdim if (filename) 8390344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); 8391344779Sdim char *ret = REAL(RMD160File)(filename, buf); 8392344779Sdim if (ret) 8393344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length); 8394344779Sdim return ret; 8395344779Sdim} 8396344779SdimINTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset, 8397344779Sdim OFF_T length) { 8398344779Sdim void *ctx; 8399344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length); 8400344779Sdim if (filename) 8401344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); 8402344779Sdim char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length); 8403344779Sdim if (ret) 8404344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length); 8405344779Sdim return ret; 8406344779Sdim} 8407344779SdimINTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) { 8408344779Sdim void *ctx; 8409344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, RMD160Data, data, len, buf); 8410344779Sdim if (data && len > 0) 8411344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8412344779Sdim char *ret = REAL(RMD160Data)(data, len, buf); 8413344779Sdim if (ret) 8414344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length); 8415344779Sdim return ret; 8416344779Sdim} 8417344779Sdim#define INIT_RMD160 \ 8418344779Sdim COMMON_INTERCEPT_FUNCTION(RMD160Init); \ 8419344779Sdim COMMON_INTERCEPT_FUNCTION(RMD160Update); \ 8420344779Sdim COMMON_INTERCEPT_FUNCTION(RMD160Final); \ 8421344779Sdim COMMON_INTERCEPT_FUNCTION(RMD160Transform); \ 8422344779Sdim COMMON_INTERCEPT_FUNCTION(RMD160End); \ 8423344779Sdim COMMON_INTERCEPT_FUNCTION(RMD160File); \ 8424344779Sdim COMMON_INTERCEPT_FUNCTION(RMD160FileChunk); \ 8425344779Sdim COMMON_INTERCEPT_FUNCTION(RMD160Data) 8426344779Sdim#else 8427344779Sdim#define INIT_RMD160 8428344779Sdim#endif 8429344779Sdim 8430344779Sdim#if SANITIZER_INTERCEPT_MD5 8431344779SdimINTERCEPTOR(void, MD5Init, void *context) { 8432344779Sdim void *ctx; 8433344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD5Init, context); 8434344779Sdim REAL(MD5Init)(context); 8435344779Sdim if (context) 8436344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz); 8437344779Sdim} 8438344779Sdim 8439344779SdimINTERCEPTOR(void, MD5Update, void *context, const unsigned char *data, 8440344779Sdim unsigned int len) { 8441344779Sdim void *ctx; 8442344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD5Update, context, data, len); 8443344779Sdim if (data && len > 0) 8444344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8445344779Sdim if (context) 8446344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz); 8447344779Sdim REAL(MD5Update)(context, data, len); 8448344779Sdim if (context) 8449344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz); 8450344779Sdim} 8451344779Sdim 8452344779SdimINTERCEPTOR(void, MD5Final, unsigned char digest[16], void *context) { 8453344779Sdim void *ctx; 8454344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD5Final, digest, context); 8455344779Sdim if (context) 8456344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz); 8457344779Sdim REAL(MD5Final)(digest, context); 8458344779Sdim if (digest) 8459344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16); 8460344779Sdim} 8461344779Sdim 8462344779SdimINTERCEPTOR(char *, MD5End, void *context, char *buf) { 8463344779Sdim void *ctx; 8464344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD5End, context, buf); 8465344779Sdim if (context) 8466344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz); 8467344779Sdim char *ret = REAL(MD5End)(context, buf); 8468344779Sdim if (ret) 8469344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length); 8470344779Sdim return ret; 8471344779Sdim} 8472344779Sdim 8473344779SdimINTERCEPTOR(char *, MD5File, const char *filename, char *buf) { 8474344779Sdim void *ctx; 8475344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf); 8476344779Sdim if (filename) 8477344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); 8478344779Sdim char *ret = REAL(MD5File)(filename, buf); 8479344779Sdim if (ret) 8480344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length); 8481344779Sdim return ret; 8482344779Sdim} 8483344779Sdim 8484344779SdimINTERCEPTOR(char *, MD5Data, const unsigned char *data, unsigned int len, 8485344779Sdim char *buf) { 8486344779Sdim void *ctx; 8487344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD5Data, data, len, buf); 8488344779Sdim if (data && len > 0) 8489344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8490344779Sdim char *ret = REAL(MD5Data)(data, len, buf); 8491344779Sdim if (ret) 8492344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length); 8493344779Sdim return ret; 8494344779Sdim} 8495344779Sdim 8496344779Sdim#define INIT_MD5 \ 8497344779Sdim COMMON_INTERCEPT_FUNCTION(MD5Init); \ 8498344779Sdim COMMON_INTERCEPT_FUNCTION(MD5Update); \ 8499344779Sdim COMMON_INTERCEPT_FUNCTION(MD5Final); \ 8500344779Sdim COMMON_INTERCEPT_FUNCTION(MD5End); \ 8501344779Sdim COMMON_INTERCEPT_FUNCTION(MD5File); \ 8502344779Sdim COMMON_INTERCEPT_FUNCTION(MD5Data) 8503344779Sdim#else 8504344779Sdim#define INIT_MD5 8505344779Sdim#endif 8506344779Sdim 8507344779Sdim#if SANITIZER_INTERCEPT_FSEEK 8508344779SdimINTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) { 8509344779Sdim void *ctx; 8510344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fseek, stream, offset, whence); 8511344779Sdim return REAL(fseek)(stream, offset, whence); 8512344779Sdim} 8513344779SdimINTERCEPTOR(int, fseeko, __sanitizer_FILE *stream, OFF_T offset, int whence) { 8514344779Sdim void *ctx; 8515344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fseeko, stream, offset, whence); 8516344779Sdim return REAL(fseeko)(stream, offset, whence); 8517344779Sdim} 8518344779SdimINTERCEPTOR(long int, ftell, __sanitizer_FILE *stream) { 8519344779Sdim void *ctx; 8520344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, ftell, stream); 8521344779Sdim return REAL(ftell)(stream); 8522344779Sdim} 8523344779SdimINTERCEPTOR(OFF_T, ftello, __sanitizer_FILE *stream) { 8524344779Sdim void *ctx; 8525344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, ftello, stream); 8526344779Sdim return REAL(ftello)(stream); 8527344779Sdim} 8528344779SdimINTERCEPTOR(void, rewind, __sanitizer_FILE *stream) { 8529344779Sdim void *ctx; 8530344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, rewind, stream); 8531344779Sdim return REAL(rewind)(stream); 8532344779Sdim} 8533344779SdimINTERCEPTOR(int, fgetpos, __sanitizer_FILE *stream, void *pos) { 8534344779Sdim void *ctx; 8535344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fgetpos, stream, pos); 8536344779Sdim int ret = REAL(fgetpos)(stream, pos); 8537344779Sdim if (pos && !ret) 8538344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pos, fpos_t_sz); 8539344779Sdim return ret; 8540344779Sdim} 8541344779SdimINTERCEPTOR(int, fsetpos, __sanitizer_FILE *stream, const void *pos) { 8542344779Sdim void *ctx; 8543344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fsetpos, stream, pos); 8544344779Sdim if (pos) 8545344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, pos, fpos_t_sz); 8546344779Sdim return REAL(fsetpos)(stream, pos); 8547344779Sdim} 8548344779Sdim#define INIT_FSEEK \ 8549344779Sdim COMMON_INTERCEPT_FUNCTION(fseek); \ 8550344779Sdim COMMON_INTERCEPT_FUNCTION(fseeko); \ 8551344779Sdim COMMON_INTERCEPT_FUNCTION(ftell); \ 8552344779Sdim COMMON_INTERCEPT_FUNCTION(ftello); \ 8553344779Sdim COMMON_INTERCEPT_FUNCTION(rewind); \ 8554344779Sdim COMMON_INTERCEPT_FUNCTION(fgetpos); \ 8555344779Sdim COMMON_INTERCEPT_FUNCTION(fsetpos) 8556344779Sdim#else 8557344779Sdim#define INIT_FSEEK 8558344779Sdim#endif 8559344779Sdim 8560344779Sdim#if SANITIZER_INTERCEPT_MD2 8561344779SdimINTERCEPTOR(void, MD2Init, void *context) { 8562344779Sdim void *ctx; 8563344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD2Init, context); 8564344779Sdim REAL(MD2Init)(context); 8565344779Sdim if (context) 8566344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz); 8567344779Sdim} 8568344779Sdim 8569344779SdimINTERCEPTOR(void, MD2Update, void *context, const unsigned char *data, 8570344779Sdim unsigned int len) { 8571344779Sdim void *ctx; 8572344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD2Update, context, data, len); 8573344779Sdim if (data && len > 0) 8574344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8575344779Sdim if (context) 8576344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz); 8577344779Sdim REAL(MD2Update)(context, data, len); 8578344779Sdim if (context) 8579344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz); 8580344779Sdim} 8581344779Sdim 8582344779SdimINTERCEPTOR(void, MD2Final, unsigned char digest[16], void *context) { 8583344779Sdim void *ctx; 8584344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD2Final, digest, context); 8585344779Sdim if (context) 8586344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz); 8587344779Sdim REAL(MD2Final)(digest, context); 8588344779Sdim if (digest) 8589344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16); 8590344779Sdim} 8591344779Sdim 8592344779SdimINTERCEPTOR(char *, MD2End, void *context, char *buf) { 8593344779Sdim void *ctx; 8594344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD2End, context, buf); 8595344779Sdim if (context) 8596344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz); 8597344779Sdim char *ret = REAL(MD2End)(context, buf); 8598344779Sdim if (ret) 8599344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length); 8600344779Sdim return ret; 8601344779Sdim} 8602344779Sdim 8603344779SdimINTERCEPTOR(char *, MD2File, const char *filename, char *buf) { 8604344779Sdim void *ctx; 8605344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf); 8606344779Sdim if (filename) 8607344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); 8608344779Sdim char *ret = REAL(MD2File)(filename, buf); 8609344779Sdim if (ret) 8610344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length); 8611344779Sdim return ret; 8612344779Sdim} 8613344779Sdim 8614344779SdimINTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len, 8615344779Sdim char *buf) { 8616344779Sdim void *ctx; 8617344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, MD2Data, data, len, buf); 8618344779Sdim if (data && len > 0) 8619344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); 8620344779Sdim char *ret = REAL(MD2Data)(data, len, buf); 8621344779Sdim if (ret) 8622344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length); 8623344779Sdim return ret; 8624344779Sdim} 8625344779Sdim 8626344779Sdim#define INIT_MD2 \ 8627344779Sdim COMMON_INTERCEPT_FUNCTION(MD2Init); \ 8628344779Sdim COMMON_INTERCEPT_FUNCTION(MD2Update); \ 8629344779Sdim COMMON_INTERCEPT_FUNCTION(MD2Final); \ 8630344779Sdim COMMON_INTERCEPT_FUNCTION(MD2End); \ 8631344779Sdim COMMON_INTERCEPT_FUNCTION(MD2File); \ 8632344779Sdim COMMON_INTERCEPT_FUNCTION(MD2Data) 8633344779Sdim#else 8634344779Sdim#define INIT_MD2 8635344779Sdim#endif 8636344779Sdim 8637344779Sdim#if SANITIZER_INTERCEPT_SHA2 8638344779Sdim#define SHA2_INTERCEPTORS(LEN, SHA2_STATE_T) \ 8639344779Sdim INTERCEPTOR(void, SHA##LEN##_Init, void *context) { \ 8640344779Sdim void *ctx; \ 8641344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Init, context); \ 8642344779Sdim REAL(SHA##LEN##_Init)(context); \ 8643344779Sdim if (context) \ 8644344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \ 8645344779Sdim } \ 8646344779Sdim INTERCEPTOR(void, SHA##LEN##_Update, void *context, \ 8647344779Sdim const u8 *data, SIZE_T len) { \ 8648344779Sdim void *ctx; \ 8649344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Update, context, data, len); \ 8650344779Sdim if (data && len > 0) \ 8651344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \ 8652344779Sdim if (context) \ 8653344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \ 8654344779Sdim REAL(SHA##LEN##_Update)(context, data, len); \ 8655344779Sdim if (context) \ 8656344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \ 8657344779Sdim } \ 8658344779Sdim INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \ 8659344779Sdim void *context) { \ 8660344779Sdim void *ctx; \ 8661344779Sdim CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \ 8662344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \ 8663344779Sdim if (context) \ 8664344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \ 8665344779Sdim REAL(SHA##LEN##_Final)(digest, context); \ 8666344779Sdim if (digest) \ 8667344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, \ 8668344779Sdim sizeof(digest[0]) * \ 8669344779Sdim SHA##LEN##_digest_length); \ 8670344779Sdim } \ 8671344779Sdim INTERCEPTOR(char *, SHA##LEN##_End, void *context, char *buf) { \ 8672344779Sdim void *ctx; \ 8673344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_End, context, buf); \ 8674344779Sdim if (context) \ 8675344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \ 8676344779Sdim char *ret = REAL(SHA##LEN##_End)(context, buf); \ 8677344779Sdim if (ret) \ 8678344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \ 8679344779Sdim return ret; \ 8680344779Sdim } \ 8681344779Sdim INTERCEPTOR(char *, SHA##LEN##_File, const char *filename, char *buf) { \ 8682344779Sdim void *ctx; \ 8683344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \ 8684344779Sdim if (filename) \ 8685344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\ 8686344779Sdim char *ret = REAL(SHA##LEN##_File)(filename, buf); \ 8687344779Sdim if (ret) \ 8688344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \ 8689344779Sdim return ret; \ 8690344779Sdim } \ 8691344779Sdim INTERCEPTOR(char *, SHA##LEN##_FileChunk, const char *filename, char *buf, \ 8692344779Sdim OFF_T offset, OFF_T length) { \ 8693344779Sdim void *ctx; \ 8694344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \ 8695344779Sdim length); \ 8696344779Sdim if (filename) \ 8697344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\ 8698344779Sdim char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \ 8699344779Sdim if (ret) \ 8700344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \ 8701344779Sdim return ret; \ 8702344779Sdim } \ 8703344779Sdim INTERCEPTOR(char *, SHA##LEN##_Data, u8 *data, SIZE_T len, char *buf) { \ 8704344779Sdim void *ctx; \ 8705344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Data, data, len, buf); \ 8706344779Sdim if (data && len > 0) \ 8707344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \ 8708344779Sdim char *ret = REAL(SHA##LEN##_Data)(data, len, buf); \ 8709344779Sdim if (ret) \ 8710344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \ 8711344779Sdim return ret; \ 8712344779Sdim } 8713344779Sdim 8714344779SdimSHA2_INTERCEPTORS(224, u32); 8715344779SdimSHA2_INTERCEPTORS(256, u32); 8716344779SdimSHA2_INTERCEPTORS(384, u64); 8717344779SdimSHA2_INTERCEPTORS(512, u64); 8718344779Sdim 8719344779Sdim#define INIT_SHA2_INTECEPTORS(LEN) \ 8720344779Sdim COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \ 8721344779Sdim COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Update); \ 8722344779Sdim COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Final); \ 8723344779Sdim COMMON_INTERCEPT_FUNCTION(SHA##LEN##_End); \ 8724344779Sdim COMMON_INTERCEPT_FUNCTION(SHA##LEN##_File); \ 8725344779Sdim COMMON_INTERCEPT_FUNCTION(SHA##LEN##_FileChunk); \ 8726344779Sdim COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Data) 8727344779Sdim 8728344779Sdim#define INIT_SHA2 \ 8729344779Sdim INIT_SHA2_INTECEPTORS(224); \ 8730344779Sdim INIT_SHA2_INTECEPTORS(256); \ 8731344779Sdim INIT_SHA2_INTECEPTORS(384); \ 8732344779Sdim INIT_SHA2_INTECEPTORS(512) 8733344779Sdim#undef SHA2_INTERCEPTORS 8734344779Sdim#else 8735344779Sdim#define INIT_SHA2 8736344779Sdim#endif 8737344779Sdim 8738344779Sdim#if SANITIZER_INTERCEPT_VIS 8739344779SdimINTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) { 8740344779Sdim void *ctx; 8741344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, vis, dst, c, flag, nextc); 8742344779Sdim char *end = REAL(vis)(dst, c, flag, nextc); 8743344779Sdim // dst is NULL terminated and end points to the NULL char 8744344779Sdim if (dst && end) 8745344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1); 8746344779Sdim return end; 8747344779Sdim} 8748344779SdimINTERCEPTOR(char *, nvis, char *dst, SIZE_T dlen, int c, int flag, int nextc) { 8749344779Sdim void *ctx; 8750344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, nvis, dst, dlen, c, flag, nextc); 8751344779Sdim char *end = REAL(nvis)(dst, dlen, c, flag, nextc); 8752344779Sdim // nvis cannot make sure the dst is NULL terminated 8753344779Sdim if (dst && end) 8754344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1); 8755344779Sdim return end; 8756344779Sdim} 8757344779SdimINTERCEPTOR(int, strvis, char *dst, const char *src, int flag) { 8758344779Sdim void *ctx; 8759344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag); 8760344779Sdim if (src) 8761344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8762344779Sdim int len = REAL(strvis)(dst, src, flag); 8763344779Sdim if (dst) 8764344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1); 8765344779Sdim return len; 8766344779Sdim} 8767344779SdimINTERCEPTOR(int, stravis, char **dst, const char *src, int flag) { 8768344779Sdim void *ctx; 8769344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag); 8770344779Sdim if (src) 8771344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8772344779Sdim int len = REAL(stravis)(dst, src, flag); 8773344779Sdim if (dst) { 8774344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *)); 8775344779Sdim if (*dst) 8776344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *dst, len + 1); 8777344779Sdim } 8778344779Sdim return len; 8779344779Sdim} 8780344779SdimINTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) { 8781344779Sdim void *ctx; 8782344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag); 8783344779Sdim if (src) 8784344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8785344779Sdim int len = REAL(strnvis)(dst, dlen, src, flag); 8786344779Sdim // The interface will be valid even if there is no space for NULL char 8787344779Sdim if (dst && len > 0) 8788344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1); 8789344779Sdim return len; 8790344779Sdim} 8791344779SdimINTERCEPTOR(int, strvisx, char *dst, const char *src, SIZE_T len, int flag) { 8792344779Sdim void *ctx; 8793344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strvisx, dst, src, len, flag); 8794344779Sdim if (src) 8795344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len); 8796344779Sdim int ret = REAL(strvisx)(dst, src, len, flag); 8797344779Sdim if (dst) 8798344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8799344779Sdim return ret; 8800344779Sdim} 8801344779SdimINTERCEPTOR(int, strnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len, 8802344779Sdim int flag) { 8803344779Sdim void *ctx; 8804344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strnvisx, dst, dlen, src, len, flag); 8805344779Sdim if (src) 8806344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len); 8807344779Sdim int ret = REAL(strnvisx)(dst, dlen, src, len, flag); 8808344779Sdim if (dst && ret >= 0) 8809344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8810344779Sdim return ret; 8811344779Sdim} 8812344779SdimINTERCEPTOR(int, strenvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len, 8813344779Sdim int flag, int *cerr_ptr) { 8814344779Sdim void *ctx; 8815344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strenvisx, dst, dlen, src, len, flag, cerr_ptr); 8816344779Sdim if (src) 8817344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len); 8818344779Sdim // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold 8819344779Sdim // according to the implementation 8820344779Sdim if (cerr_ptr) 8821344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int)); 8822344779Sdim int ret = REAL(strenvisx)(dst, dlen, src, len, flag, cerr_ptr); 8823344779Sdim if (dst && ret >= 0) 8824344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8825344779Sdim if (cerr_ptr) 8826344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int)); 8827344779Sdim return ret; 8828344779Sdim} 8829344779SdimINTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc, 8830344779Sdim const char *extra) { 8831344779Sdim void *ctx; 8832344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra); 8833344779Sdim if (extra) 8834344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1); 8835344779Sdim char *end = REAL(svis)(dst, c, flag, nextc, extra); 8836344779Sdim if (dst && end) 8837344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1); 8838344779Sdim return end; 8839344779Sdim} 8840344779SdimINTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc, 8841344779Sdim const char *extra) { 8842344779Sdim void *ctx; 8843344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra); 8844344779Sdim if (extra) 8845344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1); 8846344779Sdim char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra); 8847344779Sdim if (dst && end) 8848344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, 8849344779Sdim Min((SIZE_T)(end - dst + 1), dlen)); 8850344779Sdim return end; 8851344779Sdim} 8852344779SdimINTERCEPTOR(int, strsvis, char *dst, const char *src, int flag, 8853344779Sdim const char *extra) { 8854344779Sdim void *ctx; 8855344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra); 8856344779Sdim if (src) 8857344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8858344779Sdim if (extra) 8859344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1); 8860344779Sdim int len = REAL(strsvis)(dst, src, flag, extra); 8861344779Sdim if (dst) 8862344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1); 8863344779Sdim return len; 8864344779Sdim} 8865344779SdimINTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag, 8866344779Sdim const char *extra) { 8867344779Sdim void *ctx; 8868344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra); 8869344779Sdim if (src) 8870344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8871344779Sdim if (extra) 8872344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1); 8873344779Sdim int len = REAL(strsnvis)(dst, dlen, src, flag, extra); 8874344779Sdim // The interface will be valid even if there is no space for NULL char 8875344779Sdim if (dst && len >= 0) 8876344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1); 8877344779Sdim return len; 8878344779Sdim} 8879344779SdimINTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag, 8880344779Sdim const char *extra) { 8881344779Sdim void *ctx; 8882344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strsvisx, dst, src, len, flag, extra); 8883344779Sdim if (src) 8884344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len); 8885344779Sdim if (extra) 8886344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1); 8887344779Sdim int ret = REAL(strsvisx)(dst, src, len, flag, extra); 8888344779Sdim if (dst) 8889344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8890344779Sdim return ret; 8891344779Sdim} 8892344779SdimINTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len, 8893344779Sdim int flag, const char *extra) { 8894344779Sdim void *ctx; 8895344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strsnvisx, dst, dlen, src, len, flag, extra); 8896344779Sdim if (src) 8897344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len); 8898344779Sdim if (extra) 8899344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1); 8900344779Sdim int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra); 8901344779Sdim if (dst && ret >= 0) 8902344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8903344779Sdim return ret; 8904344779Sdim} 8905344779SdimINTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src, 8906344779Sdim SIZE_T len, int flag, const char *extra, int *cerr_ptr) { 8907344779Sdim void *ctx; 8908344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strsenvisx, dst, dlen, src, len, flag, extra, 8909344779Sdim cerr_ptr); 8910344779Sdim if (src) 8911344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len); 8912344779Sdim if (extra) 8913344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1); 8914344779Sdim // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold 8915344779Sdim // according to the implementation 8916344779Sdim if (cerr_ptr) 8917344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int)); 8918344779Sdim int ret = REAL(strsenvisx)(dst, dlen, src, len, flag, extra, cerr_ptr); 8919344779Sdim if (dst && ret >= 0) 8920344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8921344779Sdim if (cerr_ptr) 8922344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int)); 8923344779Sdim return ret; 8924344779Sdim} 8925344779SdimINTERCEPTOR(int, unvis, char *cp, int c, int *astate, int flag) { 8926344779Sdim void *ctx; 8927344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, unvis, cp, c, astate, flag); 8928344779Sdim if (astate) 8929344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, astate, sizeof(*astate)); 8930344779Sdim int ret = REAL(unvis)(cp, c, astate, flag); 8931344779Sdim if (ret == unvis_valid || ret == unvis_validpush) { 8932344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cp, sizeof(*cp)); 8933344779Sdim } 8934344779Sdim return ret; 8935344779Sdim} 8936344779SdimINTERCEPTOR(int, strunvis, char *dst, const char *src) { 8937344779Sdim void *ctx; 8938344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src); 8939344779Sdim if (src) 8940344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8941344779Sdim int ret = REAL(strunvis)(dst, src); 8942344779Sdim if (ret != -1) 8943344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8944344779Sdim return ret; 8945344779Sdim} 8946344779SdimINTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) { 8947344779Sdim void *ctx; 8948344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src); 8949344779Sdim if (src) 8950344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8951344779Sdim int ret = REAL(strnunvis)(dst, dlen, src); 8952344779Sdim if (ret != -1) 8953344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8954344779Sdim return ret; 8955344779Sdim} 8956344779SdimINTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) { 8957344779Sdim void *ctx; 8958344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag); 8959344779Sdim if (src) 8960344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8961344779Sdim int ret = REAL(strunvisx)(dst, src, flag); 8962344779Sdim if (ret != -1) 8963344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8964344779Sdim return ret; 8965344779Sdim} 8966344779SdimINTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src, 8967344779Sdim int flag) { 8968344779Sdim void *ctx; 8969344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag); 8970344779Sdim if (src) 8971344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1); 8972344779Sdim int ret = REAL(strnunvisx)(dst, dlen, src, flag); 8973344779Sdim if (ret != -1) 8974344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1); 8975344779Sdim return ret; 8976344779Sdim} 8977344779Sdim#define INIT_VIS \ 8978344779Sdim COMMON_INTERCEPT_FUNCTION(vis); \ 8979344779Sdim COMMON_INTERCEPT_FUNCTION(nvis); \ 8980344779Sdim COMMON_INTERCEPT_FUNCTION(strvis); \ 8981344779Sdim COMMON_INTERCEPT_FUNCTION(stravis); \ 8982344779Sdim COMMON_INTERCEPT_FUNCTION(strnvis); \ 8983344779Sdim COMMON_INTERCEPT_FUNCTION(strvisx); \ 8984344779Sdim COMMON_INTERCEPT_FUNCTION(strnvisx); \ 8985344779Sdim COMMON_INTERCEPT_FUNCTION(strenvisx); \ 8986344779Sdim COMMON_INTERCEPT_FUNCTION(svis); \ 8987344779Sdim COMMON_INTERCEPT_FUNCTION(snvis); \ 8988344779Sdim COMMON_INTERCEPT_FUNCTION(strsvis); \ 8989344779Sdim COMMON_INTERCEPT_FUNCTION(strsnvis); \ 8990344779Sdim COMMON_INTERCEPT_FUNCTION(strsvisx); \ 8991344779Sdim COMMON_INTERCEPT_FUNCTION(strsnvisx); \ 8992344779Sdim COMMON_INTERCEPT_FUNCTION(strsenvisx); \ 8993344779Sdim COMMON_INTERCEPT_FUNCTION(unvis); \ 8994344779Sdim COMMON_INTERCEPT_FUNCTION(strunvis); \ 8995344779Sdim COMMON_INTERCEPT_FUNCTION(strnunvis); \ 8996344779Sdim COMMON_INTERCEPT_FUNCTION(strunvisx); \ 8997344779Sdim COMMON_INTERCEPT_FUNCTION(strnunvisx) 8998344779Sdim#else 8999344779Sdim#define INIT_VIS 9000344779Sdim#endif 9001344779Sdim 9002344779Sdim#if SANITIZER_INTERCEPT_CDB 9003344779SdimINTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) { 9004344779Sdim void *ctx; 9005344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags); 9006344779Sdim if (path) 9007344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 9008344779Sdim struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags); 9009344779Sdim if (cdbr) 9010344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr)); 9011344779Sdim return cdbr; 9012344779Sdim} 9013344779Sdim 9014344779SdimINTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open_mem, void *base, SIZE_T size, 9015344779Sdim int flags, void (*unmap)(void *, void *, SIZE_T), void *cookie) { 9016344779Sdim void *ctx; 9017344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open_mem, base, size, flags, unmap, 9018344779Sdim cookie); 9019344779Sdim if (base && size) 9020344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, base, size); 9021344779Sdim struct __sanitizer_cdbr *cdbr = 9022344779Sdim REAL(cdbr_open_mem)(base, size, flags, unmap, cookie); 9023344779Sdim if (cdbr) 9024344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr)); 9025344779Sdim return cdbr; 9026344779Sdim} 9027344779Sdim 9028344779SdimINTERCEPTOR(u32, cdbr_entries, struct __sanitizer_cdbr *cdbr) { 9029344779Sdim void *ctx; 9030344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbr_entries, cdbr); 9031344779Sdim if (cdbr) 9032344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr)); 9033344779Sdim return REAL(cdbr_entries)(cdbr); 9034344779Sdim} 9035344779Sdim 9036344779SdimINTERCEPTOR(int, cdbr_get, struct __sanitizer_cdbr *cdbr, u32 index, 9037344779Sdim const void **data, SIZE_T *datalen) { 9038344779Sdim void *ctx; 9039344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbr_get, cdbr, index, data, datalen); 9040344779Sdim if (cdbr) 9041344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr)); 9042344779Sdim int ret = REAL(cdbr_get)(cdbr, index, data, datalen); 9043344779Sdim if (!ret) { 9044344779Sdim if (data) 9045344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data)); 9046344779Sdim if (datalen) 9047344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen)); 9048344779Sdim if (data && datalen) 9049344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen); 9050344779Sdim } 9051344779Sdim return ret; 9052344779Sdim} 9053344779Sdim 9054344779SdimINTERCEPTOR(int, cdbr_find, struct __sanitizer_cdbr *cdbr, const void *key, 9055344779Sdim SIZE_T keylen, const void **data, SIZE_T *datalen) { 9056344779Sdim void *ctx; 9057344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbr_find, cdbr, key, keylen, data, datalen); 9058344779Sdim if (cdbr) 9059344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr)); 9060344779Sdim if (key) 9061344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen); 9062344779Sdim int ret = REAL(cdbr_find)(cdbr, key, keylen, data, datalen); 9063344779Sdim if (!ret) { 9064344779Sdim if (data) 9065344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data)); 9066344779Sdim if (datalen) 9067344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen)); 9068344779Sdim if (data && datalen) 9069344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen); 9070344779Sdim } 9071344779Sdim return ret; 9072344779Sdim} 9073344779Sdim 9074344779SdimINTERCEPTOR(void, cdbr_close, struct __sanitizer_cdbr *cdbr) { 9075344779Sdim void *ctx; 9076344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbr_close, cdbr); 9077344779Sdim if (cdbr) 9078344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr)); 9079344779Sdim REAL(cdbr_close)(cdbr); 9080344779Sdim} 9081344779Sdim 9082344779SdimINTERCEPTOR(struct __sanitizer_cdbw *, cdbw_open) { 9083344779Sdim void *ctx; 9084344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbw_open); 9085344779Sdim struct __sanitizer_cdbw *ret = REAL(cdbw_open)(); 9086344779Sdim if (ret) 9087344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); 9088344779Sdim return ret; 9089344779Sdim} 9090344779Sdim 9091344779SdimINTERCEPTOR(int, cdbw_put, struct __sanitizer_cdbw *cdbw, const void *key, 9092344779Sdim SIZE_T keylen, const void *data, SIZE_T datalen) { 9093344779Sdim void *ctx; 9094344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put, cdbw, key, keylen, data, datalen); 9095344779Sdim if (cdbw) 9096344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw)); 9097344779Sdim if (data && datalen) 9098344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen); 9099344779Sdim if (key && keylen) 9100344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen); 9101344779Sdim int ret = REAL(cdbw_put)(cdbw, key, keylen, data, datalen); 9102344779Sdim if (!ret && cdbw) 9103344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw)); 9104344779Sdim return ret; 9105344779Sdim} 9106344779Sdim 9107344779SdimINTERCEPTOR(int, cdbw_put_data, struct __sanitizer_cdbw *cdbw, const void *data, 9108344779Sdim SIZE_T datalen, u32 *index) { 9109344779Sdim void *ctx; 9110344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_data, cdbw, data, datalen, index); 9111344779Sdim if (cdbw) 9112344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw)); 9113344779Sdim if (data && datalen) 9114344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen); 9115344779Sdim int ret = REAL(cdbw_put_data)(cdbw, data, datalen, index); 9116344779Sdim if (!ret) { 9117344779Sdim if (index) 9118344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, index, sizeof(*index)); 9119344779Sdim if (cdbw) 9120344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw)); 9121344779Sdim } 9122344779Sdim return ret; 9123344779Sdim} 9124344779Sdim 9125344779SdimINTERCEPTOR(int, cdbw_put_key, struct __sanitizer_cdbw *cdbw, const void *key, 9126344779Sdim SIZE_T keylen, u32 index) { 9127344779Sdim void *ctx; 9128344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_key, cdbw, key, keylen, index); 9129344779Sdim if (cdbw) 9130344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw)); 9131344779Sdim if (key && keylen) 9132344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen); 9133344779Sdim int ret = REAL(cdbw_put_key)(cdbw, key, keylen, index); 9134344779Sdim if (!ret && cdbw) 9135344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw)); 9136344779Sdim return ret; 9137344779Sdim} 9138344779Sdim 9139344779SdimINTERCEPTOR(int, cdbw_output, struct __sanitizer_cdbw *cdbw, int output, 9140344779Sdim const char descr[16], u32 (*seedgen)(void)) { 9141344779Sdim void *ctx; 9142344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbw_output, cdbw, output, descr, seedgen); 9143344779Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, output); 9144344779Sdim if (cdbw) 9145344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw)); 9146344779Sdim if (descr) 9147344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, descr, internal_strnlen(descr, 16)); 9148344779Sdim if (seedgen) 9149344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)seedgen, sizeof(seedgen)); 9150344779Sdim int ret = REAL(cdbw_output)(cdbw, output, descr, seedgen); 9151344779Sdim if (!ret) { 9152344779Sdim if (cdbw) 9153344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw)); 9154344779Sdim if (output >= 0) 9155344779Sdim COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, output); 9156344779Sdim } 9157344779Sdim return ret; 9158344779Sdim} 9159344779Sdim 9160344779SdimINTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) { 9161344779Sdim void *ctx; 9162344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, cdbw_close, cdbw); 9163344779Sdim if (cdbw) 9164344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw)); 9165344779Sdim REAL(cdbw_close)(cdbw); 9166344779Sdim} 9167344779Sdim 9168344779Sdim#define INIT_CDB \ 9169344779Sdim COMMON_INTERCEPT_FUNCTION(cdbr_open); \ 9170344779Sdim COMMON_INTERCEPT_FUNCTION(cdbr_open_mem); \ 9171344779Sdim COMMON_INTERCEPT_FUNCTION(cdbr_entries); \ 9172344779Sdim COMMON_INTERCEPT_FUNCTION(cdbr_get); \ 9173344779Sdim COMMON_INTERCEPT_FUNCTION(cdbr_find); \ 9174344779Sdim COMMON_INTERCEPT_FUNCTION(cdbr_close); \ 9175344779Sdim COMMON_INTERCEPT_FUNCTION(cdbw_open); \ 9176344779Sdim COMMON_INTERCEPT_FUNCTION(cdbw_put); \ 9177344779Sdim COMMON_INTERCEPT_FUNCTION(cdbw_put_data); \ 9178344779Sdim COMMON_INTERCEPT_FUNCTION(cdbw_put_key); \ 9179344779Sdim COMMON_INTERCEPT_FUNCTION(cdbw_output); \ 9180344779Sdim COMMON_INTERCEPT_FUNCTION(cdbw_close) 9181344779Sdim#else 9182344779Sdim#define INIT_CDB 9183344779Sdim#endif 9184344779Sdim 9185344779Sdim#if SANITIZER_INTERCEPT_GETFSENT 9186344779SdimINTERCEPTOR(void *, getfsent) { 9187344779Sdim void *ctx; 9188344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, getfsent); 9189344779Sdim void *ret = REAL(getfsent)(); 9190344779Sdim if (ret) 9191344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz); 9192344779Sdim return ret; 9193344779Sdim} 9194344779Sdim 9195344779SdimINTERCEPTOR(void *, getfsspec, const char *spec) { 9196344779Sdim void *ctx; 9197344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec); 9198344779Sdim if (spec) 9199344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, REAL(strlen)(spec) + 1); 9200344779Sdim void *ret = REAL(getfsspec)(spec); 9201344779Sdim if (ret) 9202344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz); 9203344779Sdim return ret; 9204344779Sdim} 9205344779Sdim 9206344779SdimINTERCEPTOR(void *, getfsfile, const char *file) { 9207344779Sdim void *ctx; 9208344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file); 9209344779Sdim if (file) 9210344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1); 9211344779Sdim void *ret = REAL(getfsfile)(file); 9212344779Sdim if (ret) 9213344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz); 9214344779Sdim return ret; 9215344779Sdim} 9216344779Sdim 9217344779Sdim#define INIT_GETFSENT \ 9218344779Sdim COMMON_INTERCEPT_FUNCTION(getfsent); \ 9219344779Sdim COMMON_INTERCEPT_FUNCTION(getfsspec); \ 9220344779Sdim COMMON_INTERCEPT_FUNCTION(getfsfile); 9221344779Sdim#else 9222344779Sdim#define INIT_GETFSENT 9223344779Sdim#endif 9224344779Sdim 9225344779Sdim#if SANITIZER_INTERCEPT_ARC4RANDOM 9226344779SdimINTERCEPTOR(void, arc4random_buf, void *buf, SIZE_T len) { 9227344779Sdim void *ctx; 9228344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, arc4random_buf, buf, len); 9229344779Sdim REAL(arc4random_buf)(buf, len); 9230344779Sdim if (buf && len) 9231344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len); 9232344779Sdim} 9233344779Sdim 9234344779SdimINTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) { 9235344779Sdim void *ctx; 9236344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, arc4random_addrandom, dat, datlen); 9237344779Sdim if (dat && datlen) 9238344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, dat, datlen); 9239344779Sdim REAL(arc4random_addrandom)(dat, datlen); 9240344779Sdim} 9241344779Sdim 9242344779Sdim#define INIT_ARC4RANDOM \ 9243344779Sdim COMMON_INTERCEPT_FUNCTION(arc4random_buf); \ 9244344779Sdim COMMON_INTERCEPT_FUNCTION(arc4random_addrandom); 9245344779Sdim#else 9246344779Sdim#define INIT_ARC4RANDOM 9247344779Sdim#endif 9248344779Sdim 9249344779Sdim#if SANITIZER_INTERCEPT_POPEN 9250344779SdimINTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) { 9251344779Sdim void *ctx; 9252344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type); 9253344779Sdim if (command) 9254344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1); 9255344779Sdim if (type) 9256344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1); 9257344779Sdim __sanitizer_FILE *res = REAL(popen)(command, type); 9258344779Sdim COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr); 9259344779Sdim if (res) unpoison_file(res); 9260344779Sdim return res; 9261344779Sdim} 9262344779Sdim#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen) 9263344779Sdim#else 9264344779Sdim#define INIT_POPEN 9265344779Sdim#endif 9266344779Sdim 9267344779Sdim#if SANITIZER_INTERCEPT_POPENVE 9268344779SdimINTERCEPTOR(__sanitizer_FILE *, popenve, const char *path, 9269344779Sdim char *const *argv, char *const *envp, const char *type) { 9270344779Sdim void *ctx; 9271344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type); 9272344779Sdim if (path) 9273344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); 9274344779Sdim if (argv) { 9275344779Sdim for (char *const *pa = argv; ; ++pa) { 9276344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **)); 9277344779Sdim if (!*pa) 9278344779Sdim break; 9279344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1); 9280344779Sdim } 9281344779Sdim } 9282344779Sdim if (envp) { 9283344779Sdim for (char *const *pa = envp; ; ++pa) { 9284344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **)); 9285344779Sdim if (!*pa) 9286344779Sdim break; 9287344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1); 9288344779Sdim } 9289344779Sdim } 9290344779Sdim if (type) 9291344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1); 9292344779Sdim __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type); 9293344779Sdim COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr); 9294344779Sdim if (res) unpoison_file(res); 9295344779Sdim return res; 9296344779Sdim} 9297344779Sdim#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve) 9298344779Sdim#else 9299344779Sdim#define INIT_POPENVE 9300344779Sdim#endif 9301344779Sdim 9302344779Sdim#if SANITIZER_INTERCEPT_PCLOSE 9303344779SdimINTERCEPTOR(int, pclose, __sanitizer_FILE *fp) { 9304344779Sdim void *ctx; 9305344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp); 9306344779Sdim COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp); 9307344779Sdim const FileMetadata *m = GetInterceptorMetadata(fp); 9308344779Sdim int res = REAL(pclose)(fp); 9309344779Sdim if (m) { 9310344779Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size); 9311344779Sdim DeleteInterceptorMetadata(fp); 9312344779Sdim } 9313344779Sdim return res; 9314344779Sdim} 9315344779Sdim#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose); 9316344779Sdim#else 9317344779Sdim#define INIT_PCLOSE 9318344779Sdim#endif 9319344779Sdim 9320344779Sdim#if SANITIZER_INTERCEPT_FUNOPEN 9321344779Sdimtypedef int (*funopen_readfn)(void *cookie, char *buf, int len); 9322344779Sdimtypedef int (*funopen_writefn)(void *cookie, const char *buf, int len); 9323344779Sdimtypedef OFF_T (*funopen_seekfn)(void *cookie, OFF_T offset, int whence); 9324344779Sdimtypedef int (*funopen_closefn)(void *cookie); 9325344779Sdim 9326344779Sdimstruct WrappedFunopenCookie { 9327344779Sdim void *real_cookie; 9328344779Sdim funopen_readfn real_read; 9329344779Sdim funopen_writefn real_write; 9330344779Sdim funopen_seekfn real_seek; 9331344779Sdim funopen_closefn real_close; 9332344779Sdim}; 9333344779Sdim 9334344779Sdimstatic int wrapped_funopen_read(void *cookie, char *buf, int len) { 9335344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 9336344779Sdim WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie; 9337344779Sdim funopen_readfn real_read = wrapped_cookie->real_read; 9338344779Sdim return real_read(wrapped_cookie->real_cookie, buf, len); 9339344779Sdim} 9340344779Sdim 9341344779Sdimstatic int wrapped_funopen_write(void *cookie, const char *buf, int len) { 9342344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 9343344779Sdim WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie; 9344344779Sdim funopen_writefn real_write = wrapped_cookie->real_write; 9345344779Sdim return real_write(wrapped_cookie->real_cookie, buf, len); 9346344779Sdim} 9347344779Sdim 9348344779Sdimstatic OFF_T wrapped_funopen_seek(void *cookie, OFF_T offset, int whence) { 9349344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 9350344779Sdim WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie; 9351344779Sdim funopen_seekfn real_seek = wrapped_cookie->real_seek; 9352344779Sdim return real_seek(wrapped_cookie->real_cookie, offset, whence); 9353344779Sdim} 9354344779Sdim 9355344779Sdimstatic int wrapped_funopen_close(void *cookie) { 9356344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 9357344779Sdim WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie; 9358344779Sdim funopen_closefn real_close = wrapped_cookie->real_close; 9359344779Sdim int res = real_close(wrapped_cookie->real_cookie); 9360344779Sdim InternalFree(wrapped_cookie); 9361344779Sdim return res; 9362344779Sdim} 9363344779Sdim 9364344779SdimINTERCEPTOR(__sanitizer_FILE *, funopen, void *cookie, funopen_readfn readfn, 9365344779Sdim funopen_writefn writefn, funopen_seekfn seekfn, 9366344779Sdim funopen_closefn closefn) { 9367344779Sdim void *ctx; 9368344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, funopen, cookie, readfn, writefn, seekfn, 9369344779Sdim closefn); 9370344779Sdim 9371344779Sdim WrappedFunopenCookie *wrapped_cookie = 9372344779Sdim (WrappedFunopenCookie *)InternalAlloc(sizeof(WrappedFunopenCookie)); 9373344779Sdim wrapped_cookie->real_cookie = cookie; 9374344779Sdim wrapped_cookie->real_read = readfn; 9375344779Sdim wrapped_cookie->real_write = writefn; 9376344779Sdim wrapped_cookie->real_seek = seekfn; 9377344779Sdim wrapped_cookie->real_close = closefn; 9378344779Sdim 9379344779Sdim __sanitizer_FILE *res = 9380344779Sdim REAL(funopen)(wrapped_cookie, 9381344779Sdim readfn ? wrapped_funopen_read : nullptr, 9382344779Sdim writefn ? wrapped_funopen_write : nullptr, 9383344779Sdim seekfn ? wrapped_funopen_seek : nullptr, 9384344779Sdim closefn ? wrapped_funopen_close : nullptr); 9385344779Sdim if (res) 9386344779Sdim unpoison_file(res); 9387344779Sdim return res; 9388344779Sdim} 9389344779Sdim#define INIT_FUNOPEN COMMON_INTERCEPT_FUNCTION(funopen) 9390344779Sdim#else 9391344779Sdim#define INIT_FUNOPEN 9392344779Sdim#endif 9393344779Sdim 9394344779Sdim#if SANITIZER_INTERCEPT_FUNOPEN2 9395344779Sdimtypedef SSIZE_T (*funopen2_readfn)(void *cookie, void *buf, SIZE_T len); 9396344779Sdimtypedef SSIZE_T (*funopen2_writefn)(void *cookie, const void *buf, SIZE_T len); 9397344779Sdimtypedef OFF_T (*funopen2_seekfn)(void *cookie, OFF_T offset, int whence); 9398344779Sdimtypedef int (*funopen2_flushfn)(void *cookie); 9399344779Sdimtypedef int (*funopen2_closefn)(void *cookie); 9400344779Sdim 9401344779Sdimstruct WrappedFunopen2Cookie { 9402344779Sdim void *real_cookie; 9403344779Sdim funopen2_readfn real_read; 9404344779Sdim funopen2_writefn real_write; 9405344779Sdim funopen2_seekfn real_seek; 9406344779Sdim funopen2_flushfn real_flush; 9407344779Sdim funopen2_closefn real_close; 9408344779Sdim}; 9409344779Sdim 9410344779Sdimstatic SSIZE_T wrapped_funopen2_read(void *cookie, void *buf, SIZE_T len) { 9411344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 9412344779Sdim WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; 9413344779Sdim funopen2_readfn real_read = wrapped_cookie->real_read; 9414344779Sdim return real_read(wrapped_cookie->real_cookie, buf, len); 9415344779Sdim} 9416344779Sdim 9417344779Sdimstatic SSIZE_T wrapped_funopen2_write(void *cookie, const void *buf, 9418344779Sdim SIZE_T len) { 9419344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 9420344779Sdim WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; 9421344779Sdim funopen2_writefn real_write = wrapped_cookie->real_write; 9422344779Sdim return real_write(wrapped_cookie->real_cookie, buf, len); 9423344779Sdim} 9424344779Sdim 9425344779Sdimstatic OFF_T wrapped_funopen2_seek(void *cookie, OFF_T offset, int whence) { 9426344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 9427344779Sdim WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; 9428344779Sdim funopen2_seekfn real_seek = wrapped_cookie->real_seek; 9429344779Sdim return real_seek(wrapped_cookie->real_cookie, offset, whence); 9430344779Sdim} 9431344779Sdim 9432344779Sdimstatic int wrapped_funopen2_flush(void *cookie) { 9433344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 9434344779Sdim WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; 9435344779Sdim funopen2_flushfn real_flush = wrapped_cookie->real_flush; 9436344779Sdim return real_flush(wrapped_cookie->real_cookie); 9437344779Sdim} 9438344779Sdim 9439344779Sdimstatic int wrapped_funopen2_close(void *cookie) { 9440344779Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(1); 9441344779Sdim WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; 9442344779Sdim funopen2_closefn real_close = wrapped_cookie->real_close; 9443344779Sdim int res = real_close(wrapped_cookie->real_cookie); 9444344779Sdim InternalFree(wrapped_cookie); 9445344779Sdim return res; 9446344779Sdim} 9447344779Sdim 9448344779SdimINTERCEPTOR(__sanitizer_FILE *, funopen2, void *cookie, funopen2_readfn readfn, 9449344779Sdim funopen2_writefn writefn, funopen2_seekfn seekfn, 9450344779Sdim funopen2_flushfn flushfn, funopen2_closefn closefn) { 9451344779Sdim void *ctx; 9452344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, funopen2, cookie, readfn, writefn, seekfn, 9453344779Sdim flushfn, closefn); 9454344779Sdim 9455344779Sdim WrappedFunopen2Cookie *wrapped_cookie = 9456344779Sdim (WrappedFunopen2Cookie *)InternalAlloc(sizeof(WrappedFunopen2Cookie)); 9457344779Sdim wrapped_cookie->real_cookie = cookie; 9458344779Sdim wrapped_cookie->real_read = readfn; 9459344779Sdim wrapped_cookie->real_write = writefn; 9460344779Sdim wrapped_cookie->real_seek = seekfn; 9461344779Sdim wrapped_cookie->real_flush = flushfn; 9462344779Sdim wrapped_cookie->real_close = closefn; 9463344779Sdim 9464344779Sdim __sanitizer_FILE *res = 9465344779Sdim REAL(funopen2)(wrapped_cookie, 9466344779Sdim readfn ? wrapped_funopen2_read : nullptr, 9467344779Sdim writefn ? wrapped_funopen2_write : nullptr, 9468344779Sdim seekfn ? wrapped_funopen2_seek : nullptr, 9469344779Sdim flushfn ? wrapped_funopen2_flush : nullptr, 9470344779Sdim closefn ? wrapped_funopen2_close : nullptr); 9471344779Sdim if (res) 9472344779Sdim unpoison_file(res); 9473344779Sdim return res; 9474344779Sdim} 9475344779Sdim#define INIT_FUNOPEN2 COMMON_INTERCEPT_FUNCTION(funopen2) 9476344779Sdim#else 9477344779Sdim#define INIT_FUNOPEN2 9478344779Sdim#endif 9479344779Sdim 9480344779Sdim#if SANITIZER_INTERCEPT_FDEVNAME 9481344779SdimINTERCEPTOR(char *, fdevname, int fd) { 9482344779Sdim void *ctx; 9483344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fdevname, fd); 9484344779Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 9485344779Sdim char *name = REAL(fdevname)(fd); 9486344779Sdim if (name) { 9487344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1); 9488344779Sdim if (fd > 0) 9489344779Sdim COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 9490344779Sdim } 9491344779Sdim return name; 9492344779Sdim} 9493344779Sdim 9494344779SdimINTERCEPTOR(char *, fdevname_r, int fd, char *buf, SIZE_T len) { 9495344779Sdim void *ctx; 9496344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, fdevname_r, fd, buf, len); 9497344779Sdim COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); 9498344779Sdim char *name = REAL(fdevname_r)(fd, buf, len); 9499344779Sdim if (name && buf && len > 0) { 9500344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1); 9501344779Sdim if (fd > 0) 9502344779Sdim COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); 9503344779Sdim } 9504344779Sdim return name; 9505344779Sdim} 9506344779Sdim 9507344779Sdim#define INIT_FDEVNAME \ 9508344779Sdim COMMON_INTERCEPT_FUNCTION(fdevname); \ 9509344779Sdim COMMON_INTERCEPT_FUNCTION(fdevname_r); 9510344779Sdim#else 9511344779Sdim#define INIT_FDEVNAME 9512344779Sdim#endif 9513344779Sdim 9514344779Sdim#if SANITIZER_INTERCEPT_GETUSERSHELL 9515344779SdimINTERCEPTOR(char *, getusershell) { 9516344779Sdim void *ctx; 9517344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, getusershell); 9518344779Sdim char *res = REAL(getusershell)(); 9519344779Sdim if (res) 9520344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 9521344779Sdim return res; 9522344779Sdim} 9523344779Sdim 9524344779Sdim#define INIT_GETUSERSHELL COMMON_INTERCEPT_FUNCTION(getusershell); 9525344779Sdim#else 9526344779Sdim#define INIT_GETUSERSHELL 9527344779Sdim#endif 9528344779Sdim 9529344779Sdim#if SANITIZER_INTERCEPT_SL_INIT 9530344779SdimINTERCEPTOR(void *, sl_init) { 9531344779Sdim void *ctx; 9532344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, sl_init); 9533344779Sdim void *res = REAL(sl_init)(); 9534344779Sdim if (res) 9535344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_StringList_sz); 9536344779Sdim return res; 9537344779Sdim} 9538344779Sdim 9539344779SdimINTERCEPTOR(int, sl_add, void *sl, char *item) { 9540344779Sdim void *ctx; 9541344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, sl_add, sl, item); 9542344779Sdim if (sl) 9543344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz); 9544344779Sdim if (item) 9545344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1); 9546344779Sdim int res = REAL(sl_add)(sl, item); 9547344779Sdim if (!res) 9548344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz); 9549344779Sdim return res; 9550344779Sdim} 9551344779Sdim 9552344779SdimINTERCEPTOR(char *, sl_find, void *sl, const char *item) { 9553344779Sdim void *ctx; 9554344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, sl_find, sl, item); 9555344779Sdim if (sl) 9556344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz); 9557344779Sdim if (item) 9558344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1); 9559344779Sdim char *res = REAL(sl_find)(sl, item); 9560344779Sdim if (res) 9561344779Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); 9562344779Sdim return res; 9563344779Sdim} 9564344779Sdim 9565344779SdimINTERCEPTOR(void, sl_free, void *sl, int freeall) { 9566344779Sdim void *ctx; 9567344779Sdim COMMON_INTERCEPTOR_ENTER(ctx, sl_free, sl, freeall); 9568344779Sdim if (sl) 9569344779Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz); 9570344779Sdim REAL(sl_free)(sl, freeall); 9571344779Sdim} 9572344779Sdim 9573344779Sdim#define INIT_SL_INIT \ 9574344779Sdim COMMON_INTERCEPT_FUNCTION(sl_init); \ 9575344779Sdim COMMON_INTERCEPT_FUNCTION(sl_add); \ 9576344779Sdim COMMON_INTERCEPT_FUNCTION(sl_find); \ 9577344779Sdim COMMON_INTERCEPT_FUNCTION(sl_free); 9578344779Sdim#else 9579344779Sdim#define INIT_SL_INIT 9580344779Sdim#endif 9581344779Sdim 9582360784Sdim#if SANITIZER_INTERCEPT_GETRANDOM 9583360784SdimINTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) { 9584360784Sdim void *ctx; 9585360784Sdim COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags); 9586360784Sdim SSIZE_T n = REAL(getrandom)(buf, buflen, flags); 9587360784Sdim if (n > 0) { 9588360784Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n); 9589360784Sdim } 9590360784Sdim return n; 9591360784Sdim} 9592360784Sdim#define INIT_GETRANDOM COMMON_INTERCEPT_FUNCTION(getrandom) 9593360784Sdim#else 9594360784Sdim#define INIT_GETRANDOM 9595360784Sdim#endif 9596360784Sdim 9597360784Sdim#if SANITIZER_INTERCEPT_CRYPT 9598360784SdimINTERCEPTOR(char *, crypt, char *key, char *salt) { 9599360784Sdim void *ctx; 9600360784Sdim COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt); 9601360784Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1); 9602360784Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1); 9603360784Sdim char *res = REAL(crypt)(key, salt); 9604360784Sdim if (res != nullptr) 9605360784Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1); 9606360784Sdim return res; 9607360784Sdim} 9608360784Sdim#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt); 9609360784Sdim#else 9610360784Sdim#define INIT_CRYPT 9611360784Sdim#endif 9612360784Sdim 9613360784Sdim#if SANITIZER_INTERCEPT_CRYPT_R 9614360784SdimINTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) { 9615360784Sdim void *ctx; 9616360784Sdim COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data); 9617360784Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1); 9618360784Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1); 9619360784Sdim char *res = REAL(crypt_r)(key, salt, data); 9620360784Sdim if (res != nullptr) { 9621360784Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, 9622360784Sdim __sanitizer::struct_crypt_data_sz); 9623360784Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1); 9624360784Sdim } 9625360784Sdim return res; 9626360784Sdim} 9627360784Sdim#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r); 9628360784Sdim#else 9629360784Sdim#define INIT_CRYPT_R 9630360784Sdim#endif 9631360784Sdim 9632360784Sdim#if SANITIZER_INTERCEPT_GETENTROPY 9633360784SdimINTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) { 9634360784Sdim void *ctx; 9635360784Sdim COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen); 9636360784Sdim int r = REAL(getentropy)(buf, buflen); 9637360784Sdim if (r == 0) { 9638360784Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); 9639360784Sdim } 9640360784Sdim return r; 9641360784Sdim} 9642360784Sdim#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy) 9643360784Sdim#else 9644360784Sdim#define INIT_GETENTROPY 9645360784Sdim#endif 9646360784Sdim 9647360784Sdim#if SANITIZER_INTERCEPT_QSORT 9648360784Sdim// Glibc qsort uses a temporary buffer allocated either on stack or on heap. 9649360784Sdim// Poisoned memory from there may get copied into the comparator arguments, 9650360784Sdim// where it needs to be dealt with. But even that is not enough - the results of 9651360784Sdim// the sort may be copied into the input/output array based on the results of 9652360784Sdim// the comparator calls, but directly from the temp memory, bypassing the 9653360784Sdim// unpoisoning done in wrapped_qsort_compar. We deal with this by, again, 9654360784Sdim// unpoisoning the entire array after the sort is done. 9655360784Sdim// 9656360784Sdim// We can not check that the entire array is initialized at the beginning. IMHO, 9657360784Sdim// it's fine for parts of the sorted objects to contain uninitialized memory, 9658360784Sdim// ex. as padding in structs. 9659360784Sdimtypedef int (*qsort_compar_f)(const void *, const void *); 9660360784Sdimstatic THREADLOCAL qsort_compar_f qsort_compar; 9661360784Sdimstatic THREADLOCAL SIZE_T qsort_size; 9662360784Sdimint wrapped_qsort_compar(const void *a, const void *b) { 9663360784Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(2); 9664360784Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size); 9665360784Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size); 9666360784Sdim return qsort_compar(a, b); 9667360784Sdim} 9668360784Sdim 9669360784SdimINTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size, 9670360784Sdim qsort_compar_f compar) { 9671360784Sdim void *ctx; 9672360784Sdim COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar); 9673360784Sdim // Run the comparator over all array elements to detect any memory issues. 9674360784Sdim if (nmemb > 1) { 9675360784Sdim for (SIZE_T i = 0; i < nmemb - 1; ++i) { 9676360784Sdim void *p = (void *)((char *)base + i * size); 9677360784Sdim void *q = (void *)((char *)base + (i + 1) * size); 9678360784Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(2); 9679360784Sdim compar(p, q); 9680360784Sdim } 9681360784Sdim } 9682360784Sdim qsort_compar_f old_compar = qsort_compar; 9683360784Sdim qsort_compar = compar; 9684360784Sdim SIZE_T old_size = qsort_size; 9685360784Sdim qsort_size = size; 9686360784Sdim REAL(qsort)(base, nmemb, size, wrapped_qsort_compar); 9687360784Sdim qsort_compar = old_compar; 9688360784Sdim qsort_size = old_size; 9689360784Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size); 9690360784Sdim} 9691360784Sdim#define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort) 9692360784Sdim#else 9693360784Sdim#define INIT_QSORT 9694360784Sdim#endif 9695360784Sdim 9696360784Sdim#if SANITIZER_INTERCEPT_QSORT_R 9697360784Sdimtypedef int (*qsort_r_compar_f)(const void *, const void *, void *); 9698360784Sdimstatic THREADLOCAL qsort_r_compar_f qsort_r_compar; 9699360784Sdimstatic THREADLOCAL SIZE_T qsort_r_size; 9700360784Sdimint wrapped_qsort_r_compar(const void *a, const void *b, void *arg) { 9701360784Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 9702360784Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_r_size); 9703360784Sdim COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_r_size); 9704360784Sdim return qsort_r_compar(a, b, arg); 9705360784Sdim} 9706360784Sdim 9707360784SdimINTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size, 9708360784Sdim qsort_r_compar_f compar, void *arg) { 9709360784Sdim void *ctx; 9710360784Sdim COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg); 9711360784Sdim // Run the comparator over all array elements to detect any memory issues. 9712360784Sdim if (nmemb > 1) { 9713360784Sdim for (SIZE_T i = 0; i < nmemb - 1; ++i) { 9714360784Sdim void *p = (void *)((char *)base + i * size); 9715360784Sdim void *q = (void *)((char *)base + (i + 1) * size); 9716360784Sdim COMMON_INTERCEPTOR_UNPOISON_PARAM(3); 9717360784Sdim compar(p, q, arg); 9718360784Sdim } 9719360784Sdim } 9720360784Sdim qsort_r_compar_f old_compar = qsort_r_compar; 9721360784Sdim qsort_r_compar = compar; 9722360784Sdim SIZE_T old_size = qsort_r_size; 9723360784Sdim qsort_r_size = size; 9724360784Sdim REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg); 9725360784Sdim qsort_r_compar = old_compar; 9726360784Sdim qsort_r_size = old_size; 9727360784Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size); 9728360784Sdim} 9729360784Sdim#define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r) 9730360784Sdim#else 9731360784Sdim#define INIT_QSORT_R 9732360784Sdim#endif 9733360784Sdim 9734360784Sdim#include "sanitizer_common_interceptors_netbsd_compat.inc" 9735360784Sdim 9736276789Sdimstatic void InitializeCommonInterceptors() { 9737360784Sdim#if SI_POSIX 9738276789Sdim static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; 9739360784Sdim interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap(); 9740360784Sdim#endif 9741276789Sdim 9742341825Sdim INIT_MMAP; 9743341825Sdim INIT_MMAP64; 9744276789Sdim INIT_TEXTDOMAIN; 9745309124Sdim INIT_STRLEN; 9746309124Sdim INIT_STRNLEN; 9747321369Sdim INIT_STRNDUP; 9748321369Sdim INIT___STRNDUP; 9749276789Sdim INIT_STRCMP; 9750276789Sdim INIT_STRNCMP; 9751276789Sdim INIT_STRCASECMP; 9752276789Sdim INIT_STRNCASECMP; 9753288943Sdim INIT_STRSTR; 9754288943Sdim INIT_STRCASESTR; 9755309124Sdim INIT_STRCHR; 9756309124Sdim INIT_STRCHRNUL; 9757309124Sdim INIT_STRRCHR; 9758288943Sdim INIT_STRSPN; 9759321369Sdim INIT_STRTOK; 9760288943Sdim INIT_STRPBRK; 9761341825Sdim INIT_STRXFRM; 9762341825Sdim INIT___STRXFRM_L; 9763309124Sdim INIT_MEMSET; 9764309124Sdim INIT_MEMMOVE; 9765309124Sdim INIT_MEMCPY; 9766276789Sdim INIT_MEMCHR; 9767296417Sdim INIT_MEMCMP; 9768353358Sdim INIT_BCMP; 9769276789Sdim INIT_MEMRCHR; 9770309124Sdim INIT_MEMMEM; 9771276789Sdim INIT_READ; 9772321369Sdim INIT_FREAD; 9773276789Sdim INIT_PREAD; 9774276789Sdim INIT_PREAD64; 9775276789Sdim INIT_READV; 9776276789Sdim INIT_PREADV; 9777276789Sdim INIT_PREADV64; 9778276789Sdim INIT_WRITE; 9779321369Sdim INIT_FWRITE; 9780276789Sdim INIT_PWRITE; 9781276789Sdim INIT_PWRITE64; 9782276789Sdim INIT_WRITEV; 9783276789Sdim INIT_PWRITEV; 9784276789Sdim INIT_PWRITEV64; 9785341825Sdim INIT_FGETS; 9786341825Sdim INIT_FPUTS; 9787341825Sdim INIT_PUTS; 9788276789Sdim INIT_PRCTL; 9789276789Sdim INIT_LOCALTIME_AND_FRIENDS; 9790276789Sdim INIT_STRPTIME; 9791276789Sdim INIT_SCANF; 9792276789Sdim INIT_ISOC99_SCANF; 9793276789Sdim INIT_PRINTF; 9794280031Sdim INIT_PRINTF_L; 9795276789Sdim INIT_ISOC99_PRINTF; 9796276789Sdim INIT_FREXP; 9797276789Sdim INIT_FREXPF_FREXPL; 9798276789Sdim INIT_GETPWNAM_AND_FRIENDS; 9799276789Sdim INIT_GETPWNAM_R_AND_FRIENDS; 9800276789Sdim INIT_GETPWENT; 9801276789Sdim INIT_FGETPWENT; 9802276789Sdim INIT_GETPWENT_R; 9803344779Sdim INIT_FGETPWENT_R; 9804344779Sdim INIT_FGETGRENT_R; 9805276789Sdim INIT_SETPWENT; 9806276789Sdim INIT_CLOCK_GETTIME; 9807276789Sdim INIT_GETITIMER; 9808276789Sdim INIT_TIME; 9809276789Sdim INIT_GLOB; 9810327952Sdim INIT_GLOB64; 9811276789Sdim INIT_WAIT; 9812276789Sdim INIT_WAIT4; 9813276789Sdim INIT_INET; 9814276789Sdim INIT_PTHREAD_GETSCHEDPARAM; 9815276789Sdim INIT_GETADDRINFO; 9816276789Sdim INIT_GETNAMEINFO; 9817276789Sdim INIT_GETSOCKNAME; 9818276789Sdim INIT_GETHOSTBYNAME; 9819327952Sdim INIT_GETHOSTBYNAME2; 9820276789Sdim INIT_GETHOSTBYNAME_R; 9821276789Sdim INIT_GETHOSTBYNAME2_R; 9822276789Sdim INIT_GETHOSTBYADDR_R; 9823276789Sdim INIT_GETHOSTENT_R; 9824276789Sdim INIT_GETSOCKOPT; 9825276789Sdim INIT_ACCEPT; 9826276789Sdim INIT_ACCEPT4; 9827341825Sdim INIT_PACCEPT; 9828276789Sdim INIT_MODF; 9829276789Sdim INIT_RECVMSG; 9830309124Sdim INIT_SENDMSG; 9831341825Sdim INIT_RECVMMSG; 9832341825Sdim INIT_SENDMMSG; 9833276789Sdim INIT_GETPEERNAME; 9834276789Sdim INIT_IOCTL; 9835276789Sdim INIT_INET_ATON; 9836276789Sdim INIT_SYSINFO; 9837276789Sdim INIT_READDIR; 9838276789Sdim INIT_READDIR64; 9839276789Sdim INIT_PTRACE; 9840276789Sdim INIT_SETLOCALE; 9841276789Sdim INIT_GETCWD; 9842276789Sdim INIT_GET_CURRENT_DIR_NAME; 9843276789Sdim INIT_STRTOIMAX; 9844276789Sdim INIT_MBSTOWCS; 9845276789Sdim INIT_MBSNRTOWCS; 9846276789Sdim INIT_WCSTOMBS; 9847276789Sdim INIT_WCSNRTOMBS; 9848296417Sdim INIT_WCRTOMB; 9849353358Sdim INIT_WCTOMB; 9850276789Sdim INIT_TCGETATTR; 9851276789Sdim INIT_REALPATH; 9852276789Sdim INIT_CANONICALIZE_FILE_NAME; 9853276789Sdim INIT_CONFSTR; 9854276789Sdim INIT_SCHED_GETAFFINITY; 9855280031Sdim INIT_SCHED_GETPARAM; 9856276789Sdim INIT_STRERROR; 9857276789Sdim INIT_STRERROR_R; 9858276789Sdim INIT_XPG_STRERROR_R; 9859276789Sdim INIT_SCANDIR; 9860276789Sdim INIT_SCANDIR64; 9861276789Sdim INIT_GETGROUPS; 9862276789Sdim INIT_POLL; 9863276789Sdim INIT_PPOLL; 9864276789Sdim INIT_WORDEXP; 9865276789Sdim INIT_SIGWAIT; 9866276789Sdim INIT_SIGWAITINFO; 9867276789Sdim INIT_SIGTIMEDWAIT; 9868276789Sdim INIT_SIGSETOPS; 9869276789Sdim INIT_SIGPENDING; 9870276789Sdim INIT_SIGPROCMASK; 9871353358Sdim INIT_PTHREAD_SIGMASK; 9872276789Sdim INIT_BACKTRACE; 9873276789Sdim INIT__EXIT; 9874276789Sdim INIT_PTHREAD_MUTEX_LOCK; 9875276789Sdim INIT_PTHREAD_MUTEX_UNLOCK; 9876341825Sdim INIT___PTHREAD_MUTEX_LOCK; 9877341825Sdim INIT___PTHREAD_MUTEX_UNLOCK; 9878341825Sdim INIT___LIBC_MUTEX_LOCK; 9879341825Sdim INIT___LIBC_MUTEX_UNLOCK; 9880341825Sdim INIT___LIBC_THR_SETCANCELSTATE; 9881276789Sdim INIT_GETMNTENT; 9882276789Sdim INIT_GETMNTENT_R; 9883276789Sdim INIT_STATFS; 9884276789Sdim INIT_STATFS64; 9885276789Sdim INIT_STATVFS; 9886276789Sdim INIT_STATVFS64; 9887276789Sdim INIT_INITGROUPS; 9888276789Sdim INIT_ETHER_NTOA_ATON; 9889276789Sdim INIT_ETHER_HOST; 9890276789Sdim INIT_ETHER_R; 9891276789Sdim INIT_SHMCTL; 9892276789Sdim INIT_RANDOM_R; 9893276789Sdim INIT_PTHREAD_ATTR_GET; 9894341825Sdim INIT_PTHREAD_ATTR_GET_SCHED; 9895276789Sdim INIT_PTHREAD_ATTR_GETINHERITSCHED; 9896276789Sdim INIT_PTHREAD_ATTR_GETAFFINITY_NP; 9897276789Sdim INIT_PTHREAD_MUTEXATTR_GETPSHARED; 9898276789Sdim INIT_PTHREAD_MUTEXATTR_GETTYPE; 9899276789Sdim INIT_PTHREAD_MUTEXATTR_GETPROTOCOL; 9900276789Sdim INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING; 9901276789Sdim INIT_PTHREAD_MUTEXATTR_GETROBUST; 9902276789Sdim INIT_PTHREAD_MUTEXATTR_GETROBUST_NP; 9903276789Sdim INIT_PTHREAD_RWLOCKATTR_GETPSHARED; 9904276789Sdim INIT_PTHREAD_RWLOCKATTR_GETKIND_NP; 9905276789Sdim INIT_PTHREAD_CONDATTR_GETPSHARED; 9906276789Sdim INIT_PTHREAD_CONDATTR_GETCLOCK; 9907276789Sdim INIT_PTHREAD_BARRIERATTR_GETPSHARED; 9908276789Sdim INIT_TMPNAM; 9909276789Sdim INIT_TMPNAM_R; 9910353358Sdim INIT_TTYNAME; 9911314564Sdim INIT_TTYNAME_R; 9912276789Sdim INIT_TEMPNAM; 9913276789Sdim INIT_PTHREAD_SETNAME_NP; 9914327952Sdim INIT_PTHREAD_GETNAME_NP; 9915276789Sdim INIT_SINCOS; 9916276789Sdim INIT_REMQUO; 9917344779Sdim INIT_REMQUOL; 9918276789Sdim INIT_LGAMMA; 9919344779Sdim INIT_LGAMMAL; 9920276789Sdim INIT_LGAMMA_R; 9921276789Sdim INIT_LGAMMAL_R; 9922276789Sdim INIT_DRAND48_R; 9923276789Sdim INIT_RAND_R; 9924276789Sdim INIT_GETLINE; 9925276789Sdim INIT_ICONV; 9926276789Sdim INIT_TIMES; 9927276789Sdim INIT_TLS_GET_ADDR; 9928276789Sdim INIT_LISTXATTR; 9929276789Sdim INIT_GETXATTR; 9930276789Sdim INIT_GETRESID; 9931276789Sdim INIT_GETIFADDRS; 9932276789Sdim INIT_IF_INDEXTONAME; 9933276789Sdim INIT_CAPGET; 9934276789Sdim INIT_AEABI_MEM; 9935276789Sdim INIT___BZERO; 9936353358Sdim INIT_BZERO; 9937276789Sdim INIT_FTIME; 9938276789Sdim INIT_XDR; 9939276789Sdim INIT_TSEARCH; 9940276789Sdim INIT_LIBIO_INTERNALS; 9941276789Sdim INIT_FOPEN; 9942276789Sdim INIT_FOPEN64; 9943276789Sdim INIT_OPEN_MEMSTREAM; 9944276789Sdim INIT_OBSTACK; 9945276789Sdim INIT_FFLUSH; 9946276789Sdim INIT_FCLOSE; 9947276789Sdim INIT_DLOPEN_DLCLOSE; 9948276789Sdim INIT_GETPASS; 9949276789Sdim INIT_TIMERFD; 9950276789Sdim INIT_MLOCKX; 9951288943Sdim INIT_FOPENCOOKIE; 9952296417Sdim INIT_SEM; 9953296417Sdim INIT_PTHREAD_SETCANCEL; 9954296417Sdim INIT_MINCORE; 9955296417Sdim INIT_PROCESS_VM_READV; 9956296417Sdim INIT_CTERMID; 9957296417Sdim INIT_CTERMID_R; 9958309124Sdim INIT_RECV_RECVFROM; 9959309124Sdim INIT_SEND_SENDTO; 9960309124Sdim INIT_STAT; 9961309124Sdim INIT_EVENTFD_READ_WRITE; 9962341825Sdim INIT_LSTAT; 9963309124Sdim INIT___XSTAT; 9964309124Sdim INIT___XSTAT64; 9965309124Sdim INIT___LXSTAT; 9966309124Sdim INIT___LXSTAT64; 9967309124Sdim // FIXME: add other *stat interceptors. 9968314564Sdim INIT_UTMP; 9969314564Sdim INIT_UTMPX; 9970321369Sdim INIT_GETLOADAVG; 9971321369Sdim INIT_WCSLEN; 9972321369Sdim INIT_WCSCAT; 9973353358Sdim INIT_WCSDUP; 9974341825Sdim INIT_WCSXFRM; 9975341825Sdim INIT___WCSXFRM_L; 9976341825Sdim INIT_ACCT; 9977341825Sdim INIT_USER_FROM_UID; 9978341825Sdim INIT_UID_FROM_USER; 9979341825Sdim INIT_GROUP_FROM_GID; 9980341825Sdim INIT_GID_FROM_GROUP; 9981341825Sdim INIT_ACCESS; 9982341825Sdim INIT_FACCESSAT; 9983341825Sdim INIT_GETGROUPLIST; 9984341825Sdim INIT_GETGROUPMEMBERSHIP; 9985341825Sdim INIT_READLINK; 9986341825Sdim INIT_READLINKAT; 9987341825Sdim INIT_NAME_TO_HANDLE_AT; 9988341825Sdim INIT_OPEN_BY_HANDLE_AT; 9989341825Sdim INIT_STRLCPY; 9990341825Sdim INIT_DEVNAME; 9991341825Sdim INIT_DEVNAME_R; 9992341825Sdim INIT_FGETLN; 9993341825Sdim INIT_STRMODE; 9994341825Sdim INIT_TTYENT; 9995341825Sdim INIT_PROTOENT; 9996341825Sdim INIT_NETENT; 9997344779Sdim INIT_GETMNTINFO; 9998344779Sdim INIT_MI_VECTOR_HASH; 9999344779Sdim INIT_SETVBUF; 10000344779Sdim INIT_GETVFSSTAT; 10001344779Sdim INIT_REGEX; 10002344779Sdim INIT_REGEXSUB; 10003344779Sdim INIT_FTS; 10004344779Sdim INIT_SYSCTL; 10005344779Sdim INIT_ASYSCTL; 10006344779Sdim INIT_SYSCTLGETMIBINFO; 10007344779Sdim INIT_NL_LANGINFO; 10008344779Sdim INIT_MODCTL; 10009344779Sdim INIT_STRTONUM; 10010344779Sdim INIT_FPARSELN; 10011344779Sdim INIT_STATVFS1; 10012344779Sdim INIT_STRTOI; 10013344779Sdim INIT_CAPSICUM; 10014344779Sdim INIT_SHA1; 10015344779Sdim INIT_MD4; 10016344779Sdim INIT_RMD160; 10017344779Sdim INIT_MD5; 10018344779Sdim INIT_FSEEK; 10019344779Sdim INIT_MD2; 10020344779Sdim INIT_SHA2; 10021344779Sdim INIT_VIS; 10022344779Sdim INIT_CDB; 10023344779Sdim INIT_GETFSENT; 10024344779Sdim INIT_ARC4RANDOM; 10025344779Sdim INIT_POPEN; 10026344779Sdim INIT_POPENVE; 10027344779Sdim INIT_PCLOSE; 10028344779Sdim INIT_FUNOPEN; 10029344779Sdim INIT_FUNOPEN2; 10030344779Sdim INIT_FDEVNAME; 10031344779Sdim INIT_GETUSERSHELL; 10032344779Sdim INIT_SL_INIT; 10033360784Sdim INIT_GETRANDOM; 10034360784Sdim INIT_CRYPT; 10035360784Sdim INIT_CRYPT_R; 10036360784Sdim INIT_GETENTROPY; 10037360784Sdim INIT_QSORT; 10038360784Sdim INIT_QSORT_R; 10039327952Sdim 10040327952Sdim INIT___PRINTF_CHK; 10041276789Sdim} 10042