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