xref: /aosp_15_r20/bionic/libc/malloc_hooks/malloc_hooks.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  * All rights reserved.
4*8d67ca89SAndroid Build Coastguard Worker  *
5*8d67ca89SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*8d67ca89SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
7*8d67ca89SAndroid Build Coastguard Worker  * are met:
8*8d67ca89SAndroid Build Coastguard Worker  *  * Redistributions of source code must retain the above copyright
9*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
10*8d67ca89SAndroid Build Coastguard Worker  *  * Redistributions in binary form must reproduce the above copyright
11*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in
12*8d67ca89SAndroid Build Coastguard Worker  *    the documentation and/or other materials provided with the
13*8d67ca89SAndroid Build Coastguard Worker  *    distribution.
14*8d67ca89SAndroid Build Coastguard Worker  *
15*8d67ca89SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*8d67ca89SAndroid Build Coastguard Worker  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*8d67ca89SAndroid Build Coastguard Worker  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*8d67ca89SAndroid Build Coastguard Worker  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*8d67ca89SAndroid Build Coastguard Worker  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*8d67ca89SAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*8d67ca89SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*8d67ca89SAndroid Build Coastguard Worker  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*8d67ca89SAndroid Build Coastguard Worker  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*8d67ca89SAndroid Build Coastguard Worker  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*8d67ca89SAndroid Build Coastguard Worker  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8d67ca89SAndroid Build Coastguard Worker  * SUCH DAMAGE.
27*8d67ca89SAndroid Build Coastguard Worker  */
28*8d67ca89SAndroid Build Coastguard Worker 
29*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
30*8d67ca89SAndroid Build Coastguard Worker #include <malloc.h>
31*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
32*8d67ca89SAndroid Build Coastguard Worker #include <stdio.h>
33*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
34*8d67ca89SAndroid Build Coastguard Worker #include <sys/param.h>
35*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
36*8d67ca89SAndroid Build Coastguard Worker 
37*8d67ca89SAndroid Build Coastguard Worker #include <private/bionic_malloc_dispatch.h>
38*8d67ca89SAndroid Build Coastguard Worker 
39*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
40*8d67ca89SAndroid Build Coastguard Worker // Global Data
41*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
42*8d67ca89SAndroid Build Coastguard Worker const MallocDispatch* g_dispatch;
43*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
44*8d67ca89SAndroid Build Coastguard Worker 
45*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
46*8d67ca89SAndroid Build Coastguard Worker // Use C style prototypes for all exported functions. This makes it easy
47*8d67ca89SAndroid Build Coastguard Worker // to do dlsym lookups during libc initialization when hooks are enabled.
48*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
49*8d67ca89SAndroid Build Coastguard Worker __BEGIN_DECLS
50*8d67ca89SAndroid Build Coastguard Worker 
51*8d67ca89SAndroid Build Coastguard Worker bool hooks_initialize(const MallocDispatch* malloc_dispatch, bool* zygote_child,
52*8d67ca89SAndroid Build Coastguard Worker     const char* options);
53*8d67ca89SAndroid Build Coastguard Worker void hooks_finalize();
54*8d67ca89SAndroid Build Coastguard Worker void hooks_get_malloc_leak_info(
55*8d67ca89SAndroid Build Coastguard Worker     uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory,
56*8d67ca89SAndroid Build Coastguard Worker     size_t* backtrace_size);
57*8d67ca89SAndroid Build Coastguard Worker ssize_t hooks_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
58*8d67ca89SAndroid Build Coastguard Worker void hooks_free_malloc_leak_info(uint8_t* info);
59*8d67ca89SAndroid Build Coastguard Worker size_t hooks_malloc_usable_size(void* pointer);
60*8d67ca89SAndroid Build Coastguard Worker void* hooks_malloc(size_t size);
61*8d67ca89SAndroid Build Coastguard Worker int hooks_malloc_info(int options, FILE* fp);
62*8d67ca89SAndroid Build Coastguard Worker void hooks_free(void* pointer);
63*8d67ca89SAndroid Build Coastguard Worker void* hooks_memalign(size_t alignment, size_t bytes);
64*8d67ca89SAndroid Build Coastguard Worker void* hooks_aligned_alloc(size_t alignment, size_t bytes);
65*8d67ca89SAndroid Build Coastguard Worker void* hooks_realloc(void* pointer, size_t bytes);
66*8d67ca89SAndroid Build Coastguard Worker void* hooks_calloc(size_t nmemb, size_t bytes);
67*8d67ca89SAndroid Build Coastguard Worker struct mallinfo hooks_mallinfo();
68*8d67ca89SAndroid Build Coastguard Worker int hooks_mallopt(int param, int value);
69*8d67ca89SAndroid Build Coastguard Worker int hooks_posix_memalign(void** memptr, size_t alignment, size_t size);
70*8d67ca89SAndroid Build Coastguard Worker int hooks_malloc_iterate(uintptr_t base, size_t size,
71*8d67ca89SAndroid Build Coastguard Worker     void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
72*8d67ca89SAndroid Build Coastguard Worker void hooks_malloc_disable();
73*8d67ca89SAndroid Build Coastguard Worker void hooks_malloc_enable();
74*8d67ca89SAndroid Build Coastguard Worker bool hooks_write_malloc_leak_info(FILE*);
75*8d67ca89SAndroid Build Coastguard Worker 
76*8d67ca89SAndroid Build Coastguard Worker #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
77*8d67ca89SAndroid Build Coastguard Worker void* hooks_pvalloc(size_t bytes);
78*8d67ca89SAndroid Build Coastguard Worker void* hooks_valloc(size_t size);
79*8d67ca89SAndroid Build Coastguard Worker #endif
80*8d67ca89SAndroid Build Coastguard Worker 
default_malloc_hook(size_t bytes,const void *)81*8d67ca89SAndroid Build Coastguard Worker static void* default_malloc_hook(size_t bytes, const void*) {
82*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->malloc(bytes);
83*8d67ca89SAndroid Build Coastguard Worker }
84*8d67ca89SAndroid Build Coastguard Worker 
default_realloc_hook(void * pointer,size_t bytes,const void *)85*8d67ca89SAndroid Build Coastguard Worker static void* default_realloc_hook(void* pointer, size_t bytes, const void*) {
86*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->realloc(pointer, bytes);
87*8d67ca89SAndroid Build Coastguard Worker }
88*8d67ca89SAndroid Build Coastguard Worker 
default_free_hook(void * pointer,const void *)89*8d67ca89SAndroid Build Coastguard Worker static void default_free_hook(void* pointer, const void*) {
90*8d67ca89SAndroid Build Coastguard Worker   g_dispatch->free(pointer);
91*8d67ca89SAndroid Build Coastguard Worker }
92*8d67ca89SAndroid Build Coastguard Worker 
default_memalign_hook(size_t alignment,size_t bytes,const void *)93*8d67ca89SAndroid Build Coastguard Worker static void* default_memalign_hook(size_t alignment, size_t bytes, const void*) {
94*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->memalign(alignment, bytes);
95*8d67ca89SAndroid Build Coastguard Worker }
96*8d67ca89SAndroid Build Coastguard Worker 
97*8d67ca89SAndroid Build Coastguard Worker __END_DECLS
98*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
99*8d67ca89SAndroid Build Coastguard Worker 
hooks_initialize(const MallocDispatch * malloc_dispatch,bool *,const char *)100*8d67ca89SAndroid Build Coastguard Worker bool hooks_initialize(const MallocDispatch* malloc_dispatch, bool*, const char*) {
101*8d67ca89SAndroid Build Coastguard Worker   g_dispatch = malloc_dispatch;
102*8d67ca89SAndroid Build Coastguard Worker   __malloc_hook = default_malloc_hook;
103*8d67ca89SAndroid Build Coastguard Worker   __realloc_hook = default_realloc_hook;
104*8d67ca89SAndroid Build Coastguard Worker   __free_hook = default_free_hook;
105*8d67ca89SAndroid Build Coastguard Worker   __memalign_hook = default_memalign_hook;
106*8d67ca89SAndroid Build Coastguard Worker   return true;
107*8d67ca89SAndroid Build Coastguard Worker }
108*8d67ca89SAndroid Build Coastguard Worker 
hooks_finalize()109*8d67ca89SAndroid Build Coastguard Worker void hooks_finalize() {
110*8d67ca89SAndroid Build Coastguard Worker }
111*8d67ca89SAndroid Build Coastguard Worker 
hooks_get_malloc_leak_info(uint8_t ** info,size_t * overall_size,size_t * info_size,size_t * total_memory,size_t * backtrace_size)112*8d67ca89SAndroid Build Coastguard Worker void hooks_get_malloc_leak_info(uint8_t** info, size_t* overall_size,
113*8d67ca89SAndroid Build Coastguard Worker     size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
114*8d67ca89SAndroid Build Coastguard Worker   *info = nullptr;
115*8d67ca89SAndroid Build Coastguard Worker   *overall_size = 0;
116*8d67ca89SAndroid Build Coastguard Worker   *info_size = 0;
117*8d67ca89SAndroid Build Coastguard Worker   *total_memory = 0;
118*8d67ca89SAndroid Build Coastguard Worker   *backtrace_size = 0;
119*8d67ca89SAndroid Build Coastguard Worker }
120*8d67ca89SAndroid Build Coastguard Worker 
hooks_free_malloc_leak_info(uint8_t *)121*8d67ca89SAndroid Build Coastguard Worker void hooks_free_malloc_leak_info(uint8_t*) {
122*8d67ca89SAndroid Build Coastguard Worker }
123*8d67ca89SAndroid Build Coastguard Worker 
hooks_malloc_usable_size(void * pointer)124*8d67ca89SAndroid Build Coastguard Worker size_t hooks_malloc_usable_size(void* pointer) {
125*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->malloc_usable_size(pointer);
126*8d67ca89SAndroid Build Coastguard Worker }
127*8d67ca89SAndroid Build Coastguard Worker 
hooks_malloc(size_t size)128*8d67ca89SAndroid Build Coastguard Worker void* hooks_malloc(size_t size) {
129*8d67ca89SAndroid Build Coastguard Worker   if (__malloc_hook != nullptr && __malloc_hook != default_malloc_hook) {
130*8d67ca89SAndroid Build Coastguard Worker     return __malloc_hook(size, __builtin_return_address(0));
131*8d67ca89SAndroid Build Coastguard Worker   }
132*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->malloc(size);
133*8d67ca89SAndroid Build Coastguard Worker }
134*8d67ca89SAndroid Build Coastguard Worker 
hooks_free(void * pointer)135*8d67ca89SAndroid Build Coastguard Worker void hooks_free(void* pointer) {
136*8d67ca89SAndroid Build Coastguard Worker   if (__free_hook != nullptr && __free_hook != default_free_hook) {
137*8d67ca89SAndroid Build Coastguard Worker     return __free_hook(pointer, __builtin_return_address(0));
138*8d67ca89SAndroid Build Coastguard Worker   }
139*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->free(pointer);
140*8d67ca89SAndroid Build Coastguard Worker }
141*8d67ca89SAndroid Build Coastguard Worker 
hooks_memalign(size_t alignment,size_t bytes)142*8d67ca89SAndroid Build Coastguard Worker void* hooks_memalign(size_t alignment, size_t bytes) {
143*8d67ca89SAndroid Build Coastguard Worker   if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
144*8d67ca89SAndroid Build Coastguard Worker     return __memalign_hook(alignment, bytes, __builtin_return_address(0));
145*8d67ca89SAndroid Build Coastguard Worker   }
146*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->memalign(alignment, bytes);
147*8d67ca89SAndroid Build Coastguard Worker }
148*8d67ca89SAndroid Build Coastguard Worker 
hooks_realloc(void * pointer,size_t bytes)149*8d67ca89SAndroid Build Coastguard Worker void* hooks_realloc(void* pointer, size_t bytes) {
150*8d67ca89SAndroid Build Coastguard Worker   if (__realloc_hook != nullptr && __realloc_hook != default_realloc_hook) {
151*8d67ca89SAndroid Build Coastguard Worker     return __realloc_hook(pointer, bytes, __builtin_return_address(0));
152*8d67ca89SAndroid Build Coastguard Worker   }
153*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->realloc(pointer, bytes);
154*8d67ca89SAndroid Build Coastguard Worker }
155*8d67ca89SAndroid Build Coastguard Worker 
hooks_calloc(size_t nmemb,size_t bytes)156*8d67ca89SAndroid Build Coastguard Worker void* hooks_calloc(size_t nmemb, size_t bytes) {
157*8d67ca89SAndroid Build Coastguard Worker   if (__malloc_hook != nullptr && __malloc_hook != default_malloc_hook) {
158*8d67ca89SAndroid Build Coastguard Worker     size_t size;
159*8d67ca89SAndroid Build Coastguard Worker     if (__builtin_mul_overflow(nmemb, bytes, &size)) {
160*8d67ca89SAndroid Build Coastguard Worker       return nullptr;
161*8d67ca89SAndroid Build Coastguard Worker     }
162*8d67ca89SAndroid Build Coastguard Worker     void* ptr = __malloc_hook(size, __builtin_return_address(0));
163*8d67ca89SAndroid Build Coastguard Worker     if (ptr != nullptr) {
164*8d67ca89SAndroid Build Coastguard Worker       memset(ptr, 0, size);
165*8d67ca89SAndroid Build Coastguard Worker     }
166*8d67ca89SAndroid Build Coastguard Worker     return ptr;
167*8d67ca89SAndroid Build Coastguard Worker   }
168*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->calloc(nmemb, bytes);
169*8d67ca89SAndroid Build Coastguard Worker }
170*8d67ca89SAndroid Build Coastguard Worker 
hooks_mallinfo()171*8d67ca89SAndroid Build Coastguard Worker struct mallinfo hooks_mallinfo() {
172*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->mallinfo();
173*8d67ca89SAndroid Build Coastguard Worker }
174*8d67ca89SAndroid Build Coastguard Worker 
hooks_mallopt(int param,int value)175*8d67ca89SAndroid Build Coastguard Worker int hooks_mallopt(int param, int value) {
176*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->mallopt(param, value);
177*8d67ca89SAndroid Build Coastguard Worker }
178*8d67ca89SAndroid Build Coastguard Worker 
hooks_malloc_info(int options,FILE * fp)179*8d67ca89SAndroid Build Coastguard Worker int hooks_malloc_info(int options, FILE* fp) {
180*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->malloc_info(options, fp);
181*8d67ca89SAndroid Build Coastguard Worker }
182*8d67ca89SAndroid Build Coastguard Worker 
hooks_aligned_alloc(size_t alignment,size_t size)183*8d67ca89SAndroid Build Coastguard Worker void* hooks_aligned_alloc(size_t alignment, size_t size) {
184*8d67ca89SAndroid Build Coastguard Worker   if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
185*8d67ca89SAndroid Build Coastguard Worker     if (!powerof2(alignment) || (size % alignment) != 0) {
186*8d67ca89SAndroid Build Coastguard Worker       errno = EINVAL;
187*8d67ca89SAndroid Build Coastguard Worker       return nullptr;
188*8d67ca89SAndroid Build Coastguard Worker     }
189*8d67ca89SAndroid Build Coastguard Worker     void* ptr = __memalign_hook(alignment, size, __builtin_return_address(0));
190*8d67ca89SAndroid Build Coastguard Worker     if (ptr == nullptr) {
191*8d67ca89SAndroid Build Coastguard Worker       errno = ENOMEM;
192*8d67ca89SAndroid Build Coastguard Worker     }
193*8d67ca89SAndroid Build Coastguard Worker     return ptr;
194*8d67ca89SAndroid Build Coastguard Worker   }
195*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->aligned_alloc(alignment, size);
196*8d67ca89SAndroid Build Coastguard Worker }
197*8d67ca89SAndroid Build Coastguard Worker 
hooks_posix_memalign(void ** memptr,size_t alignment,size_t size)198*8d67ca89SAndroid Build Coastguard Worker int hooks_posix_memalign(void** memptr, size_t alignment, size_t size) {
199*8d67ca89SAndroid Build Coastguard Worker   if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
200*8d67ca89SAndroid Build Coastguard Worker     if (alignment < sizeof(void*) || !powerof2(alignment)) {
201*8d67ca89SAndroid Build Coastguard Worker       return EINVAL;
202*8d67ca89SAndroid Build Coastguard Worker     }
203*8d67ca89SAndroid Build Coastguard Worker     *memptr = __memalign_hook(alignment, size, __builtin_return_address(0));
204*8d67ca89SAndroid Build Coastguard Worker     if (*memptr == nullptr) {
205*8d67ca89SAndroid Build Coastguard Worker       return ENOMEM;
206*8d67ca89SAndroid Build Coastguard Worker     }
207*8d67ca89SAndroid Build Coastguard Worker     return 0;
208*8d67ca89SAndroid Build Coastguard Worker   }
209*8d67ca89SAndroid Build Coastguard Worker   return g_dispatch->posix_memalign(memptr, alignment, size);
210*8d67ca89SAndroid Build Coastguard Worker }
211*8d67ca89SAndroid Build Coastguard Worker 
hooks_malloc_iterate(uintptr_t,size_t,void (*)(uintptr_t,size_t,void *),void *)212*8d67ca89SAndroid Build Coastguard Worker int hooks_malloc_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*) {
213*8d67ca89SAndroid Build Coastguard Worker   return 0;
214*8d67ca89SAndroid Build Coastguard Worker }
215*8d67ca89SAndroid Build Coastguard Worker 
hooks_malloc_disable()216*8d67ca89SAndroid Build Coastguard Worker void hooks_malloc_disable() {
217*8d67ca89SAndroid Build Coastguard Worker }
218*8d67ca89SAndroid Build Coastguard Worker 
hooks_malloc_enable()219*8d67ca89SAndroid Build Coastguard Worker void hooks_malloc_enable() {
220*8d67ca89SAndroid Build Coastguard Worker }
221*8d67ca89SAndroid Build Coastguard Worker 
hooks_malloc_backtrace(void *,uintptr_t *,size_t)222*8d67ca89SAndroid Build Coastguard Worker ssize_t hooks_malloc_backtrace(void*, uintptr_t*, size_t) {
223*8d67ca89SAndroid Build Coastguard Worker   return 0;
224*8d67ca89SAndroid Build Coastguard Worker }
225*8d67ca89SAndroid Build Coastguard Worker 
hooks_write_malloc_leak_info(FILE *)226*8d67ca89SAndroid Build Coastguard Worker bool hooks_write_malloc_leak_info(FILE*) {
227*8d67ca89SAndroid Build Coastguard Worker   return true;
228*8d67ca89SAndroid Build Coastguard Worker }
229*8d67ca89SAndroid Build Coastguard Worker 
230*8d67ca89SAndroid Build Coastguard Worker #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
hooks_pvalloc(size_t bytes)231*8d67ca89SAndroid Build Coastguard Worker void* hooks_pvalloc(size_t bytes) {
232*8d67ca89SAndroid Build Coastguard Worker   size_t pagesize = getpagesize();
233*8d67ca89SAndroid Build Coastguard Worker   size_t size = __BIONIC_ALIGN(bytes, pagesize);
234*8d67ca89SAndroid Build Coastguard Worker   if (size < bytes) {
235*8d67ca89SAndroid Build Coastguard Worker     // Overflow
236*8d67ca89SAndroid Build Coastguard Worker     errno = ENOMEM;
237*8d67ca89SAndroid Build Coastguard Worker     return nullptr;
238*8d67ca89SAndroid Build Coastguard Worker   }
239*8d67ca89SAndroid Build Coastguard Worker   return hooks_memalign(pagesize, size);
240*8d67ca89SAndroid Build Coastguard Worker }
241*8d67ca89SAndroid Build Coastguard Worker 
hooks_valloc(size_t size)242*8d67ca89SAndroid Build Coastguard Worker void* hooks_valloc(size_t size) {
243*8d67ca89SAndroid Build Coastguard Worker   return hooks_memalign(getpagesize(), size);
244*8d67ca89SAndroid Build Coastguard Worker }
245*8d67ca89SAndroid Build Coastguard Worker #endif
246