1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifdef HOOK_ENABLE
17#include <unistd.h>
18#include <sys/types.h>
19#include "musl_malloc.h"
20#include <malloc.h>
21#include "musl_malloc_dispatch_table.h"
22#include "common_def.h"
23#include "musl_preinit_common.h"
24#include "signal.h"
25#ifdef OHOS_FDTRACK_HOOK_ENABLE
26#include "musl_fdtrack.h"
27#endif
28
29#define MALLOC_REPORT_LIMIT (300 * 1024 * 1024)
30
31#ifdef USE_GWP_ASAN
32extern void* libc_gwp_asan_malloc(size_t bytes);
33extern void libc_gwp_asan_free(void *mem);
34extern size_t libc_gwp_asan_malloc_usable_size(void *mem);
35extern void* libc_gwp_asan_realloc(void *ptr, size_t size);
36extern void* libc_gwp_asan_calloc(size_t nmemb, size_t size);
37#endif
38
39#ifdef OHOS_FDTRACK_HOOK_ENABLE
40struct timeval prevTime = {0, 0};
41static int KICK_ALLOCATE_MEMORY = 60;
42#endif
43
44void* malloc(size_t bytes)
45{
46	if (bytes >= MALLOC_REPORT_LIMIT) {
47#ifdef OHOS_FDTRACK_HOOK_ENABLE
48		if (check_before_memory_allocate(prevTime, KICK_ALLOCATE_MEMORY)) {
49			gettimeofday(&prevTime, NULL);
50			raise(MUSL_SIGNAL_LEAK_STACK);
51		}
52#endif
53	}
54	volatile const struct MallocDispatchType* dispatch_table = (struct MallocDispatchType *)atomic_load_explicit(
55		&__musl_libc_globals.current_dispatch_table, memory_order_acquire);
56	if (__predict_false(dispatch_table != NULL)) {
57		if (__get_memleak_hook_flag()) {
58			return dispatch_table->malloc(bytes);
59		}
60		if (!__get_global_hook_flag()) {
61#ifdef USE_GWP_ASAN
62			return libc_gwp_asan_malloc(bytes);
63#endif
64			return MuslFunc(malloc)(bytes);
65		}
66		else if (!__get_hook_flag()) {
67#ifdef USE_GWP_ASAN
68			return libc_gwp_asan_malloc(bytes);
69#endif
70			return MuslFunc(malloc)(bytes);
71		}
72		return dispatch_table->malloc(bytes);
73	}
74#ifdef USE_GWP_ASAN
75	return libc_gwp_asan_malloc(bytes);
76#endif
77	return  MuslFunc(malloc)(bytes);
78}
79
80void* aligned_alloc(size_t align, size_t len)
81{
82	volatile const struct MallocDispatchType* dispatch_table = (struct MallocDispatchType *)atomic_load_explicit(
83		&__musl_libc_globals.current_dispatch_table, memory_order_acquire);
84	if (__predict_false(dispatch_table != NULL)) {
85		if (__get_memleak_hook_flag()) {
86			return dispatch_table->aligned_alloc(align, len);
87		}
88		if (!__get_global_hook_flag()) {
89			return MuslMalloc(aligned_alloc)(align, len);
90		}
91		else if (!__get_hook_flag()) {
92			return MuslMalloc(aligned_alloc)(align, len);
93		}
94		return dispatch_table->aligned_alloc(align, len);
95	}
96	return  MuslMalloc(aligned_alloc)(align, len);
97}
98
99void free(void* mem)
100{
101	volatile const struct MallocDispatchType* dispatch_table = (struct MallocDispatchType *)atomic_load_explicit(
102		&__musl_libc_globals.current_dispatch_table, memory_order_acquire);
103	if (__predict_false(dispatch_table != NULL)) {
104		if (__get_memleak_hook_flag()) {
105			dispatch_table->free(mem);
106			return;
107		}
108		if (!__get_global_hook_flag()) {
109#ifdef USE_GWP_ASAN
110			return libc_gwp_asan_free(mem);
111#endif
112			MuslFunc(free)(mem);
113			return;
114		}
115		else if (!__get_hook_flag()) {
116#ifdef USE_GWP_ASAN
117			return libc_gwp_asan_free(mem);
118#endif
119			MuslFunc(free)(mem);
120			return;
121		}
122		dispatch_table->free(mem);
123		return;
124	}
125#ifdef USE_GWP_ASAN
126	return libc_gwp_asan_free(mem);
127#endif
128	MuslFunc(free)(mem);
129}
130
131void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset)
132{
133	volatile const struct MallocDispatchType* dispatch_table = get_current_dispatch_table();
134	if (__predict_false(dispatch_table != NULL)) {
135		return dispatch_table->mmap(addr, length, prot, flags, fd, offset);
136	} else {
137		return MuslMalloc(mmap)(addr, length, prot, flags, fd, offset);
138	}
139}
140
141int munmap(void* addr, size_t length)
142{
143	volatile const struct MallocDispatchType* dispatch_table = get_current_dispatch_table();
144	if (__predict_false(dispatch_table != NULL)) {
145		return dispatch_table->munmap(addr, length);
146	} else {
147		return MuslMalloc(munmap)(addr, length);
148	}
149}
150
151void* calloc(size_t m, size_t n)
152{
153	if ((m <= (UINT32_MAX / n)) && ((m * n) >= MALLOC_REPORT_LIMIT)) {
154#ifdef OHOS_FDTRACK_HOOK_ENABLE
155		if (check_before_memory_allocate(prevTime, KICK_ALLOCATE_MEMORY)) {
156			gettimeofday(&prevTime, NULL);
157			raise(MUSL_SIGNAL_LEAK_STACK);
158		}
159#endif
160	}
161	volatile const struct MallocDispatchType* dispatch_table = get_current_dispatch_table();
162	if (__predict_false(dispatch_table != NULL)) {
163		return dispatch_table->calloc(m, n);
164	} else {
165#ifdef USE_GWP_ASAN
166		return libc_gwp_asan_calloc(m, n);
167#endif
168		return MuslFunc(calloc)(m, n);
169	}
170}
171
172void* realloc(void *p, size_t n)
173{
174	if (n >= MALLOC_REPORT_LIMIT) {
175#ifdef OHOS_FDTRACK_HOOK_ENABLE
176		if (check_before_memory_allocate(prevTime, KICK_ALLOCATE_MEMORY)) {
177			gettimeofday(&prevTime, NULL);
178			raise(MUSL_SIGNAL_LEAK_STACK);
179		}
180#endif
181	}
182	volatile const struct MallocDispatchType* dispatch_table = get_current_dispatch_table();
183	if (__predict_false(dispatch_table != NULL)) {
184		return dispatch_table->realloc(p, n);
185	} else {
186#ifdef USE_GWP_ASAN
187		return libc_gwp_asan_realloc(p, n);
188#endif
189		return MuslFunc(realloc)(p, n);
190	}
191}
192
193size_t malloc_usable_size(void* addr)
194{
195	volatile const struct MallocDispatchType* dispatch_table = get_current_dispatch_table();
196	if (__predict_false(dispatch_table != NULL)) {
197		return dispatch_table->malloc_usable_size(addr);
198	} else {
199#ifdef USE_GWP_ASAN
200		return libc_gwp_asan_malloc_usable_size(addr);
201#endif
202		return MuslMalloc(malloc_usable_size)(addr);
203	}
204}
205
206int prctl(int option, ...)
207{
208	unsigned long x[4];
209	int i;
210	va_list ap;
211	va_start(ap, option);
212	for (i=0; i<4; i++) x[i] = va_arg(ap, unsigned long);
213	va_end(ap);
214	volatile const struct MallocDispatchType* dispatch_table = get_current_dispatch_table();
215	if (__predict_false(dispatch_table != NULL)) {
216		return dispatch_table->prctl(option, x[0], x[1], x[2], x[3]);
217	} else {
218		return MuslMalloc(prctl)(option, x[0], x[1], x[2], x[3]);
219	}
220}
221
222#endif
223