1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_malloc_linux.cc ----------------------------------------------===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Linux-specific malloc interception. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We simply define functions like malloc, free, realloc, etc. 141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// They will replace the corresponding libc functions automagically. 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov 1724e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_common/sanitizer_platform.h" 1824e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_LINUX 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2583cb7877f608eb9b3d65981095216842f686c527Evgeniy Stepanov#if SANITIZER_ANDROID 26c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size) 27c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) 28c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) 29c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size) 30c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size) 316dd1dde531b8fb6cf7a3e1dcda86170f6ac3a988Alexey Samsonov 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystruct MallocDebug { 33e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany void* (*malloc)(uptr bytes); 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void (*free)(void* mem); 35e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany void* (*calloc)(uptr n_elements, uptr elem_size); 36e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany void* (*realloc)(void* oldMem, uptr bytes); 37e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany void* (*memalign)(uptr alignment, uptr bytes); 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 40adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonovconst MallocDebug asan_malloc_dispatch ALIGNED(32) = { 416dd1dde531b8fb6cf7a3e1dcda86170f6ac3a988Alexey Samsonov WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign) 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" const MallocDebug* __libc_malloc_dispatch; 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() { 481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany __libc_malloc_dispatch = &asan_malloc_dispatch; 491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#else // ANDROID 531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() { 561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif // ANDROID 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Replacement functions ---------------- {{{1 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 63f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, free, void *ptr) { 64a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_FREE; 65fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany asan_free(ptr, &stack, FROM_MALLOC); 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 68f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, cfree, void *ptr) { 69a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_FREE; 70fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany asan_free(ptr, &stack, FROM_MALLOC); 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 73e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, malloc, uptr size) { 74a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 78e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 8009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 81e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany const uptr kCallocPoolSize = 1024; 823f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 83e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany static uptr allocated; 84e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany allocated += size_in_words; 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(allocated < kCallocPoolSize); 881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return mem; 891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 90a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_calloc(nmemb, size, &stack); 921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 94e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, realloc, void *ptr, uptr size) { 95a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_realloc(ptr, size, &stack); 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 99e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 100a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 101fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany return asan_memalign(boundary, size, &stack, FROM_MALLOC); 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 104e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, __libc_memalign, uptr align, uptr s) 105adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov ALIAS("memalign"); 1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 107e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 108a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 1094fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov return asan_malloc_usable_size(ptr, &stack); 1104fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov} 1114fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov 112e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// We avoid including malloc.h for portability reasons. 113e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// man mallinfo says the fields are "long", but the implementation uses int. 114e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// It doesn't matter much -- we just need to make sure that the libc's mallinfo 115e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// is not called. 116e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryanystruct fake_mallinfo { 117e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany int x[10]; 118e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany}; 119e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany 120e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 121e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany struct fake_mallinfo res; 12209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(memset)(&res, 0, sizeof(res)); 1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return res; 1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 126f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, mallopt, int cmd, int value) { 1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return -1; 1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 130e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 131a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 132739eb7984139d457216623347ae3b7a706c0aadfEvgeniy Stepanov // Printf("posix_memalign: %zx %zu\n", alignment, size); 1331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_posix_memalign(memptr, alignment, size, &stack); 1341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 136e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, valloc, uptr size) { 137a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_valloc(size, &stack); 1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 141e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, pvalloc, uptr size) { 142a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_pvalloc(size, &stack); 1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 145d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 14673bad81febb2a872627c03e579beea1da4b49294Kostya SerebryanyINTERCEPTOR(void, malloc_stats, void) { 147709a33e1cf20eb7f00653fe32dc07714b3f2c633Kostya Serebryany __asan_print_accumulated_stats(); 14873bad81febb2a872627c03e579beea1da4b49294Kostya Serebryany} 14973bad81febb2a872627c03e579beea1da4b49294Kostya Serebryany 150649a270f5341efe9c57f473dbb78706b0b2ed523Alexey Samsonov#endif // SANITIZER_LINUX 151