13cab2bb3Spatrick //===-- asan_malloc_linux.cpp ---------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker.
103cab2bb3Spatrick //
113cab2bb3Spatrick // Linux-specific malloc interception.
123cab2bb3Spatrick // We simply define functions like malloc, free, realloc, etc.
133cab2bb3Spatrick // They will replace the corresponding libc functions automagically.
143cab2bb3Spatrick //===----------------------------------------------------------------------===//
153cab2bb3Spatrick
163cab2bb3Spatrick #include "sanitizer_common/sanitizer_platform.h"
173cab2bb3Spatrick #if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \
18d89ec533Spatrick SANITIZER_NETBSD || SANITIZER_SOLARIS
193cab2bb3Spatrick
203cab2bb3Spatrick # include "asan_allocator.h"
213cab2bb3Spatrick # include "asan_interceptors.h"
223cab2bb3Spatrick # include "asan_internal.h"
233cab2bb3Spatrick # include "asan_stack.h"
24*810390e3Srobert # include "lsan/lsan_common.h"
25d89ec533Spatrick # include "sanitizer_common/sanitizer_allocator_checks.h"
26*810390e3Srobert # include "sanitizer_common/sanitizer_allocator_dlsym.h"
27d89ec533Spatrick # include "sanitizer_common/sanitizer_errno.h"
28d89ec533Spatrick # include "sanitizer_common/sanitizer_tls_get_addr.h"
293cab2bb3Spatrick
303cab2bb3Spatrick // ---------------------- Replacement functions ---------------- {{{1
313cab2bb3Spatrick using namespace __asan;
323cab2bb3Spatrick
33*810390e3Srobert struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
UseImplDlsymAlloc34*810390e3Srobert static bool UseImpl() { return asan_init_is_running; }
OnAllocateDlsymAlloc35*810390e3Srobert static void OnAllocate(const void *ptr, uptr size) {
36*810390e3Srobert # if CAN_SANITIZE_LEAKS
37*810390e3Srobert // Suppress leaks from dlerror(). Previously dlsym hack on global array was
38*810390e3Srobert // used by leak sanitizer as a root region.
39*810390e3Srobert __lsan_register_root_region(ptr, size);
40*810390e3Srobert # endif
413cab2bb3Spatrick }
OnFreeDlsymAlloc42*810390e3Srobert static void OnFree(const void *ptr, uptr size) {
43*810390e3Srobert # if CAN_SANITIZE_LEAKS
44*810390e3Srobert __lsan_unregister_root_region(ptr, size);
45*810390e3Srobert # endif
463cab2bb3Spatrick }
47*810390e3Srobert };
483cab2bb3Spatrick
INTERCEPTOR(void,free,void * ptr)493cab2bb3Spatrick INTERCEPTOR(void, free, void *ptr) {
50*810390e3Srobert if (DlsymAlloc::PointerIsMine(ptr))
51*810390e3Srobert return DlsymAlloc::Free(ptr);
52d89ec533Spatrick GET_STACK_TRACE_FREE;
533cab2bb3Spatrick asan_free(ptr, &stack, FROM_MALLOC);
543cab2bb3Spatrick }
553cab2bb3Spatrick
563cab2bb3Spatrick #if SANITIZER_INTERCEPT_CFREE
INTERCEPTOR(void,cfree,void * ptr)573cab2bb3Spatrick INTERCEPTOR(void, cfree, void *ptr) {
58*810390e3Srobert if (DlsymAlloc::PointerIsMine(ptr))
59*810390e3Srobert return DlsymAlloc::Free(ptr);
60d89ec533Spatrick GET_STACK_TRACE_FREE;
613cab2bb3Spatrick asan_free(ptr, &stack, FROM_MALLOC);
623cab2bb3Spatrick }
633cab2bb3Spatrick #endif // SANITIZER_INTERCEPT_CFREE
643cab2bb3Spatrick
INTERCEPTOR(void *,malloc,uptr size)653cab2bb3Spatrick INTERCEPTOR(void*, malloc, uptr size) {
66*810390e3Srobert if (DlsymAlloc::Use())
67*810390e3Srobert return DlsymAlloc::Allocate(size);
683cab2bb3Spatrick ENSURE_ASAN_INITED();
693cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
703cab2bb3Spatrick return asan_malloc(size, &stack);
713cab2bb3Spatrick }
723cab2bb3Spatrick
INTERCEPTOR(void *,calloc,uptr nmemb,uptr size)733cab2bb3Spatrick INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
74*810390e3Srobert if (DlsymAlloc::Use())
75*810390e3Srobert return DlsymAlloc::Callocate(nmemb, size);
763cab2bb3Spatrick ENSURE_ASAN_INITED();
773cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
783cab2bb3Spatrick return asan_calloc(nmemb, size, &stack);
793cab2bb3Spatrick }
803cab2bb3Spatrick
INTERCEPTOR(void *,realloc,void * ptr,uptr size)813cab2bb3Spatrick INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
82*810390e3Srobert if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
83*810390e3Srobert return DlsymAlloc::Realloc(ptr, size);
843cab2bb3Spatrick ENSURE_ASAN_INITED();
853cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
863cab2bb3Spatrick return asan_realloc(ptr, size, &stack);
873cab2bb3Spatrick }
883cab2bb3Spatrick
893cab2bb3Spatrick #if SANITIZER_INTERCEPT_REALLOCARRAY
INTERCEPTOR(void *,reallocarray,void * ptr,uptr nmemb,uptr size)903cab2bb3Spatrick INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) {
913cab2bb3Spatrick ENSURE_ASAN_INITED();
923cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
933cab2bb3Spatrick return asan_reallocarray(ptr, nmemb, size, &stack);
943cab2bb3Spatrick }
953cab2bb3Spatrick #endif // SANITIZER_INTERCEPT_REALLOCARRAY
963cab2bb3Spatrick
973cab2bb3Spatrick #if SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void *,memalign,uptr boundary,uptr size)983cab2bb3Spatrick INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
993cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
1003cab2bb3Spatrick return asan_memalign(boundary, size, &stack, FROM_MALLOC);
1013cab2bb3Spatrick }
1023cab2bb3Spatrick
INTERCEPTOR(void *,__libc_memalign,uptr boundary,uptr size)1033cab2bb3Spatrick INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
1043cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
1053cab2bb3Spatrick void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC);
1063cab2bb3Spatrick DTLS_on_libc_memalign(res, size);
1073cab2bb3Spatrick return res;
1083cab2bb3Spatrick }
1093cab2bb3Spatrick #endif // SANITIZER_INTERCEPT_MEMALIGN
1103cab2bb3Spatrick
1113cab2bb3Spatrick #if SANITIZER_INTERCEPT_ALIGNED_ALLOC
INTERCEPTOR(void *,aligned_alloc,uptr boundary,uptr size)1123cab2bb3Spatrick INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {
1133cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
1143cab2bb3Spatrick return asan_aligned_alloc(boundary, size, &stack);
1153cab2bb3Spatrick }
1163cab2bb3Spatrick #endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC
1173cab2bb3Spatrick
INTERCEPTOR(uptr,malloc_usable_size,void * ptr)1183cab2bb3Spatrick INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
1193cab2bb3Spatrick GET_CURRENT_PC_BP_SP;
1203cab2bb3Spatrick (void)sp;
1213cab2bb3Spatrick return asan_malloc_usable_size(ptr, pc, bp);
1223cab2bb3Spatrick }
1233cab2bb3Spatrick
1243cab2bb3Spatrick #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
1253cab2bb3Spatrick // We avoid including malloc.h for portability reasons.
1263cab2bb3Spatrick // man mallinfo says the fields are "long", but the implementation uses int.
1273cab2bb3Spatrick // It doesn't matter much -- we just need to make sure that the libc's mallinfo
1283cab2bb3Spatrick // is not called.
1293cab2bb3Spatrick struct fake_mallinfo {
1303cab2bb3Spatrick int x[10];
1313cab2bb3Spatrick };
1323cab2bb3Spatrick
INTERCEPTOR(struct fake_mallinfo,mallinfo,void)1333cab2bb3Spatrick INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
1343cab2bb3Spatrick struct fake_mallinfo res;
1353cab2bb3Spatrick REAL(memset)(&res, 0, sizeof(res));
1363cab2bb3Spatrick return res;
1373cab2bb3Spatrick }
1383cab2bb3Spatrick
INTERCEPTOR(int,mallopt,int cmd,int value)1393cab2bb3Spatrick INTERCEPTOR(int, mallopt, int cmd, int value) {
1403cab2bb3Spatrick return 0;
1413cab2bb3Spatrick }
1423cab2bb3Spatrick #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
1433cab2bb3Spatrick
INTERCEPTOR(int,posix_memalign,void ** memptr,uptr alignment,uptr size)1443cab2bb3Spatrick INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
1453cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
1463cab2bb3Spatrick return asan_posix_memalign(memptr, alignment, size, &stack);
1473cab2bb3Spatrick }
1483cab2bb3Spatrick
INTERCEPTOR(void *,valloc,uptr size)1493cab2bb3Spatrick INTERCEPTOR(void*, valloc, uptr size) {
1503cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
1513cab2bb3Spatrick return asan_valloc(size, &stack);
1523cab2bb3Spatrick }
1533cab2bb3Spatrick
1543cab2bb3Spatrick #if SANITIZER_INTERCEPT_PVALLOC
INTERCEPTOR(void *,pvalloc,uptr size)1553cab2bb3Spatrick INTERCEPTOR(void*, pvalloc, uptr size) {
1563cab2bb3Spatrick GET_STACK_TRACE_MALLOC;
1573cab2bb3Spatrick return asan_pvalloc(size, &stack);
1583cab2bb3Spatrick }
1593cab2bb3Spatrick #endif // SANITIZER_INTERCEPT_PVALLOC
1603cab2bb3Spatrick
INTERCEPTOR(void,malloc_stats,void)1613cab2bb3Spatrick INTERCEPTOR(void, malloc_stats, void) {
1623cab2bb3Spatrick __asan_print_accumulated_stats();
1633cab2bb3Spatrick }
1643cab2bb3Spatrick
1653cab2bb3Spatrick #if SANITIZER_ANDROID
1663cab2bb3Spatrick // Format of __libc_malloc_dispatch has changed in Android L.
1673cab2bb3Spatrick // While we are moving towards a solution that does not depend on bionic
1683cab2bb3Spatrick // internals, here is something to support both K* and L releases.
1693cab2bb3Spatrick struct MallocDebugK {
1703cab2bb3Spatrick void *(*malloc)(uptr bytes);
1713cab2bb3Spatrick void (*free)(void *mem);
1723cab2bb3Spatrick void *(*calloc)(uptr n_elements, uptr elem_size);
1733cab2bb3Spatrick void *(*realloc)(void *oldMem, uptr bytes);
1743cab2bb3Spatrick void *(*memalign)(uptr alignment, uptr bytes);
1753cab2bb3Spatrick uptr (*malloc_usable_size)(void *mem);
1763cab2bb3Spatrick };
1773cab2bb3Spatrick
1783cab2bb3Spatrick struct MallocDebugL {
1793cab2bb3Spatrick void *(*calloc)(uptr n_elements, uptr elem_size);
1803cab2bb3Spatrick void (*free)(void *mem);
1813cab2bb3Spatrick fake_mallinfo (*mallinfo)(void);
1823cab2bb3Spatrick void *(*malloc)(uptr bytes);
1833cab2bb3Spatrick uptr (*malloc_usable_size)(void *mem);
1843cab2bb3Spatrick void *(*memalign)(uptr alignment, uptr bytes);
1853cab2bb3Spatrick int (*posix_memalign)(void **memptr, uptr alignment, uptr size);
1863cab2bb3Spatrick void* (*pvalloc)(uptr size);
1873cab2bb3Spatrick void *(*realloc)(void *oldMem, uptr bytes);
1883cab2bb3Spatrick void* (*valloc)(uptr size);
1893cab2bb3Spatrick };
1903cab2bb3Spatrick
1913cab2bb3Spatrick ALIGNED(32) const MallocDebugK asan_malloc_dispatch_k = {
1923cab2bb3Spatrick WRAP(malloc), WRAP(free), WRAP(calloc),
1933cab2bb3Spatrick WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)};
1943cab2bb3Spatrick
1953cab2bb3Spatrick ALIGNED(32) const MallocDebugL asan_malloc_dispatch_l = {
1963cab2bb3Spatrick WRAP(calloc), WRAP(free), WRAP(mallinfo),
1973cab2bb3Spatrick WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign),
1983cab2bb3Spatrick WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc),
1993cab2bb3Spatrick WRAP(valloc)};
2003cab2bb3Spatrick
2013cab2bb3Spatrick namespace __asan {
ReplaceSystemMalloc()2023cab2bb3Spatrick void ReplaceSystemMalloc() {
2033cab2bb3Spatrick void **__libc_malloc_dispatch_p =
2043cab2bb3Spatrick (void **)AsanDlSymNext("__libc_malloc_dispatch");
2053cab2bb3Spatrick if (__libc_malloc_dispatch_p) {
2063cab2bb3Spatrick // Decide on K vs L dispatch format by the presence of
2073cab2bb3Spatrick // __libc_malloc_default_dispatch export in libc.
2083cab2bb3Spatrick void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch");
2093cab2bb3Spatrick if (default_dispatch_p)
2103cab2bb3Spatrick *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k;
2113cab2bb3Spatrick else
2123cab2bb3Spatrick *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l;
2133cab2bb3Spatrick }
2143cab2bb3Spatrick }
2153cab2bb3Spatrick } // namespace __asan
2163cab2bb3Spatrick
2173cab2bb3Spatrick #else // SANITIZER_ANDROID
2183cab2bb3Spatrick
2193cab2bb3Spatrick namespace __asan {
ReplaceSystemMalloc()2203cab2bb3Spatrick void ReplaceSystemMalloc() {
2213cab2bb3Spatrick }
2223cab2bb3Spatrick } // namespace __asan
2233cab2bb3Spatrick #endif // SANITIZER_ANDROID
2243cab2bb3Spatrick
2253cab2bb3Spatrick #endif // SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX ||
2263cab2bb3Spatrick // SANITIZER_NETBSD || SANITIZER_SOLARIS
227