brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · add5731 Raw
221 lines · cpp
1//===-- asan_malloc_linux.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of AddressSanitizer, an address sanity checker.10//11// Linux-specific malloc interception.12// We simply define functions like malloc, free, realloc, etc.13// They will replace the corresponding libc functions automagically.14//===----------------------------------------------------------------------===//15 16#include "sanitizer_common/sanitizer_platform.h"17#if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \18    SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU19 20#  include "asan_allocator.h"21#  include "asan_interceptors.h"22#  include "asan_internal.h"23#  include "asan_stack.h"24#  include "lsan/lsan_common.h"25#  include "sanitizer_common/sanitizer_allocator_checks.h"26#  include "sanitizer_common/sanitizer_allocator_dlsym.h"27#  include "sanitizer_common/sanitizer_errno.h"28 29// ---------------------- Replacement functions ---------------- {{{130using namespace __asan;31 32struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {33  static bool UseImpl() { return !TryAsanInitFromRtl(); }34  static void OnAllocate(const void *ptr, uptr size) {35#  if CAN_SANITIZE_LEAKS36    // Suppress leaks from dlerror(). Previously dlsym hack on global array was37    // used by leak sanitizer as a root region.38    __lsan_register_root_region(ptr, size);39#  endif40  }41  static void OnFree(const void *ptr, uptr size) {42#  if CAN_SANITIZE_LEAKS43    __lsan_unregister_root_region(ptr, size);44#  endif45  }46};47 48INTERCEPTOR(void, free, void *ptr) {49  if (DlsymAlloc::PointerIsMine(ptr))50    return DlsymAlloc::Free(ptr);51  GET_STACK_TRACE_FREE;52  asan_free(ptr, &stack);53}54 55#if SANITIZER_INTERCEPT_CFREE56INTERCEPTOR(void, cfree, void *ptr) {57  if (DlsymAlloc::PointerIsMine(ptr))58    return DlsymAlloc::Free(ptr);59  GET_STACK_TRACE_FREE;60  asan_free(ptr, &stack);61}62#endif // SANITIZER_INTERCEPT_CFREE63 64INTERCEPTOR(void*, malloc, uptr size) {65  if (DlsymAlloc::Use())66    return DlsymAlloc::Allocate(size);67  GET_STACK_TRACE_MALLOC;68  return asan_malloc(size, &stack);69}70 71INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {72  if (DlsymAlloc::Use())73    return DlsymAlloc::Callocate(nmemb, size);74  GET_STACK_TRACE_MALLOC;75  return asan_calloc(nmemb, size, &stack);76}77 78INTERCEPTOR(void*, realloc, void *ptr, uptr size) {79  if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))80    return DlsymAlloc::Realloc(ptr, size);81  GET_STACK_TRACE_MALLOC;82  return asan_realloc(ptr, size, &stack);83}84 85#if SANITIZER_INTERCEPT_REALLOCARRAY86INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) {87  AsanInitFromRtl();88  GET_STACK_TRACE_MALLOC;89  return asan_reallocarray(ptr, nmemb, size, &stack);90}91#endif  // SANITIZER_INTERCEPT_REALLOCARRAY92 93#if SANITIZER_INTERCEPT_MEMALIGN94INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {95  GET_STACK_TRACE_MALLOC;96  return asan_memalign(boundary, size, &stack);97}98 99INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {100  GET_STACK_TRACE_MALLOC;101  return asan_memalign(boundary, size, &stack);102}103#endif // SANITIZER_INTERCEPT_MEMALIGN104 105#if SANITIZER_INTERCEPT_ALIGNED_ALLOC106INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {107  GET_STACK_TRACE_MALLOC;108  return asan_aligned_alloc(boundary, size, &stack);109}110#endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC111 112INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {113  GET_CURRENT_PC_BP_SP;114  (void)sp;115  return asan_malloc_usable_size(ptr, pc, bp);116}117 118#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO119// We avoid including malloc.h for portability reasons.120// man mallinfo says the fields are "long", but the implementation uses int.121// It doesn't matter much -- we just need to make sure that the libc's mallinfo122// is not called.123struct fake_mallinfo {124  int x[10];125};126 127INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {128  struct fake_mallinfo res;129  REAL(memset)(&res, 0, sizeof(res));130  return res;131}132 133INTERCEPTOR(int, mallopt, int cmd, int value) {134  return 0;135}136#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO137 138INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {139  GET_STACK_TRACE_MALLOC;140  return asan_posix_memalign(memptr, alignment, size, &stack);141}142 143INTERCEPTOR(void*, valloc, uptr size) {144  GET_STACK_TRACE_MALLOC;145  return asan_valloc(size, &stack);146}147 148#if SANITIZER_INTERCEPT_PVALLOC149INTERCEPTOR(void*, pvalloc, uptr size) {150  GET_STACK_TRACE_MALLOC;151  return asan_pvalloc(size, &stack);152}153#endif // SANITIZER_INTERCEPT_PVALLOC154 155INTERCEPTOR(void, malloc_stats, void) {156  __asan_print_accumulated_stats();157}158 159#if SANITIZER_ANDROID160// Format of __libc_malloc_dispatch has changed in Android L.161// While we are moving towards a solution that does not depend on bionic162// internals, here is something to support both K* and L releases.163struct MallocDebugK {164  void *(*malloc)(uptr bytes);165  void (*free)(void *mem);166  void *(*calloc)(uptr n_elements, uptr elem_size);167  void *(*realloc)(void *oldMem, uptr bytes);168  void *(*memalign)(uptr alignment, uptr bytes);169  uptr (*malloc_usable_size)(void *mem);170};171 172struct MallocDebugL {173  void *(*calloc)(uptr n_elements, uptr elem_size);174  void (*free)(void *mem);175  fake_mallinfo (*mallinfo)(void);176  void *(*malloc)(uptr bytes);177  uptr (*malloc_usable_size)(void *mem);178  void *(*memalign)(uptr alignment, uptr bytes);179  int (*posix_memalign)(void **memptr, uptr alignment, uptr size);180  void* (*pvalloc)(uptr size);181  void *(*realloc)(void *oldMem, uptr bytes);182  void* (*valloc)(uptr size);183};184 185alignas(32) const MallocDebugK asan_malloc_dispatch_k = {186    WRAP(malloc),  WRAP(free),     WRAP(calloc),187    WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)};188 189alignas(32) const MallocDebugL asan_malloc_dispatch_l = {190    WRAP(calloc),         WRAP(free),               WRAP(mallinfo),191    WRAP(malloc),         WRAP(malloc_usable_size), WRAP(memalign),192    WRAP(posix_memalign), WRAP(pvalloc),            WRAP(realloc),193    WRAP(valloc)};194 195namespace __asan {196void ReplaceSystemMalloc() {197  void **__libc_malloc_dispatch_p =198      (void **)AsanDlSymNext("__libc_malloc_dispatch");199  if (__libc_malloc_dispatch_p) {200    // Decide on K vs L dispatch format by the presence of201    // __libc_malloc_default_dispatch export in libc.202    void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch");203    if (default_dispatch_p)204      *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k;205    else206      *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l;207  }208}209}  // namespace __asan210 211#else  // SANITIZER_ANDROID212 213namespace __asan {214void ReplaceSystemMalloc() {215}216}  // namespace __asan217#endif  // SANITIZER_ANDROID218 219#endif  // SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX ||220        // SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU221