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" 182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_tls_get_addr.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2683cb7877f608eb9b3d65981095216842f686c527Evgeniy Stepanov#if SANITIZER_ANDROID 27c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size) 28c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) 29c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) 30c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size) 31c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size) 325d71de26cedae3dafc17449fe0182045c0bd20e8Stephen HinesDECLARE_REAL_AND_INTERCEPTOR(uptr, malloc_usable_size, void *mem) 336dd1dde531b8fb6cf7a3e1dcda86170f6ac3a988Alexey Samsonov 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystruct MallocDebug { 355d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines void *(*malloc)(uptr bytes); 365d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines void (*free)(void *mem); 375d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines void *(*calloc)(uptr n_elements, uptr elem_size); 385d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines void *(*realloc)(void *oldMem, uptr bytes); 395d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines void *(*memalign)(uptr alignment, uptr bytes); 405d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines uptr (*malloc_usable_size)(void *mem); 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 435d71de26cedae3dafc17449fe0182045c0bd20e8Stephen HinesALIGNED(32) const MallocDebug asan_malloc_dispatch = { 445d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines WRAP(malloc), WRAP(free), WRAP(calloc), 455d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)}; 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() { 495d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines const MallocDebug** __libc_malloc_dispatch_p; 505d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines __libc_malloc_dispatch_p = 515d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines (const MallocDebug **)AsanDlSymNext("__libc_malloc_dispatch"); 525d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines if (__libc_malloc_dispatch_p) 535d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines *__libc_malloc_dispatch_p = &asan_malloc_dispatch; 541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 575d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#else // SANITIZER_ANDROID 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() { 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 635d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#endif // SANITIZER_ANDROID 641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Replacement functions ---------------- {{{1 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 68f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, free, void *ptr) { 69a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_FREE; 70fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany asan_free(ptr, &stack, FROM_MALLOC); 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 73f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, cfree, void *ptr) { 74a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_FREE; 75fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany asan_free(ptr, &stack, FROM_MALLOC); 761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 78e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, malloc, uptr size) { 79a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 83e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (UNLIKELY(!asan_inited)) { 8509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 86e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany const uptr kCallocPoolSize = 1024; 873f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 88e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany static uptr allocated; 89e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany allocated += size_in_words; 921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(allocated < kCallocPoolSize); 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return mem; 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 95a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_calloc(nmemb, size, &stack); 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 99e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, realloc, void *ptr, uptr size) { 100a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_realloc(ptr, size, &stack); 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 104e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 105a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 106fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany return asan_memalign(boundary, size, &stack, FROM_MALLOC); 1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1095d71de26cedae3dafc17449fe0182045c0bd20e8Stephen HinesINTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) { 1105d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines GET_STACK_TRACE_MALLOC; 1115d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines return asan_memalign(boundary, size, &stack, FROM_MALLOC); 1125d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines} 1135d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) { 1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines GET_STACK_TRACE_MALLOC; 1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC); 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DTLS_on_libc_memalign(res, size * boundary); 1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return res; 1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 121e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 1221b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov GET_CURRENT_PC_BP_SP; 1231b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov (void)sp; 1241b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov return asan_malloc_usable_size(ptr, pc, bp); 1254fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov} 1264fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov 127e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// We avoid including malloc.h for portability reasons. 128e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// man mallinfo says the fields are "long", but the implementation uses int. 129e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// It doesn't matter much -- we just need to make sure that the libc's mallinfo 130e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// is not called. 131e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryanystruct fake_mallinfo { 132e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany int x[10]; 133e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany}; 134e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany 135e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 136e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany struct fake_mallinfo res; 13709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(memset)(&res, 0, sizeof(res)); 1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return res; 1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 141f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, mallopt, int cmd, int value) { 1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return -1; 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 145e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 146a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 147739eb7984139d457216623347ae3b7a706c0aadfEvgeniy Stepanov // Printf("posix_memalign: %zx %zu\n", alignment, size); 1481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_posix_memalign(memptr, alignment, size, &stack); 1491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 151e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, valloc, uptr size) { 152a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_valloc(size, &stack); 1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 156e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, pvalloc, uptr size) { 157a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_MALLOC; 1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_pvalloc(size, &stack); 1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 160d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 16173bad81febb2a872627c03e579beea1da4b49294Kostya SerebryanyINTERCEPTOR(void, malloc_stats, void) { 162709a33e1cf20eb7f00653fe32dc07714b3f2c633Kostya Serebryany __asan_print_accumulated_stats(); 16373bad81febb2a872627c03e579beea1da4b49294Kostya Serebryany} 16473bad81febb2a872627c03e579beea1da4b49294Kostya Serebryany 1652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // SANITIZER_FREEBSD || SANITIZER_LINUX 166