Skip to content

Commit 8bfade2

Browse files
committed
Add threshold to proxy lib to call system allocator
Add threshold to proxy lib to call system allocator when a size is less than the given threshold. Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
1 parent afbab27 commit 8bfade2

File tree

3 files changed

+108
-15
lines changed

3 files changed

+108
-15
lines changed

src/libumf.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
#include "base_alloc_global.h"
1313
#include "memspace_internal.h"
1414
#include "provider_tracking.h"
15+
#include "utils_common.h"
1516
#include "utils_log.h"
17+
1618
#if !defined(UMF_NO_HWLOC)
1719
#include "topology.h"
1820
#endif
@@ -39,6 +41,15 @@ void umfTearDown(void) {
3941
umfMemspaceLowestLatencyDestroy();
4042
umfDestroyTopology();
4143
#endif
44+
45+
if (utils_is_running_in_proxy_lib()) {
46+
// We cannot destroy the TRACKER nor the base allocator
47+
// when we are running in the proxy library,
48+
// because it could lead to use-after-free in the program's unloader
49+
// (for example _dl_fini() on Linux).
50+
return;
51+
}
52+
4253
// make sure TRACKER is not used after being destroyed
4354
umf_memory_tracker_handle_t t = TRACKER;
4455
TRACKER = NULL;

src/provider/provider_tracking.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,19 @@ umf_memory_pool_handle_t umfMemoryTrackerGetPool(const void *ptr) {
103103

104104
umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
105105
umf_alloc_info_t *pAllocInfo) {
106-
assert(ptr);
107106
assert(pAllocInfo);
108107

108+
if (ptr == NULL) {
109+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
110+
}
111+
109112
if (TRACKER == NULL) {
110-
LOG_ERR("tracker is not created");
113+
LOG_ERR("tracker does not exist");
111114
return UMF_RESULT_ERROR_NOT_SUPPORTED;
112115
}
113116

114117
if (TRACKER->map == NULL) {
115-
LOG_ERR("tracker's map is not created");
118+
LOG_ERR("tracker's map does not exist");
116119
return UMF_RESULT_ERROR_NOT_SUPPORTED;
117120
}
118121

@@ -121,9 +124,8 @@ umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
121124
int found = critnib_find(TRACKER->map, (uintptr_t)ptr, FIND_LE,
122125
(void *)&rkey, (void **)&rvalue);
123126
if (!found || (uintptr_t)ptr >= rkey + rvalue->size) {
124-
LOG_WARN("pointer %p not found in the "
125-
"tracker, TRACKER=%p",
126-
ptr, (void *)TRACKER);
127+
LOG_DEBUG("pointer %p not found in the tracker, TRACKER=%p", ptr,
128+
(void *)TRACKER);
127129
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
128130
}
129131

src/proxy_lib/proxy_lib.c

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
* - _aligned_offset_recalloc()
2828
*/
2929

30+
#ifndef _WIN32
31+
#define _GNU_SOURCE
32+
#include <dlfcn.h>
33+
#undef _GNU_SOURCE
34+
#endif /* _WIN32 */
35+
3036
#if (defined PROXY_LIB_USES_JEMALLOC_POOL)
3137
#include <umf/pools/pool_jemalloc.h>
3238
#define umfPoolManagerOps umfJemallocPoolOps
@@ -103,6 +109,21 @@ static umf_memory_pool_handle_t Proxy_pool = NULL;
103109
// it protects us from recursion in umfPool*()
104110
static __TLS int was_called_from_umfPool = 0;
105111

112+
typedef void *(*system_aligned_alloc_t)(size_t alignment, size_t size);
113+
typedef void *(*system_calloc_t)(size_t nmemb, size_t size);
114+
typedef void (*system_free_t)(void *ptr);
115+
typedef void *(*system_malloc_t)(size_t size);
116+
typedef size_t (*system_malloc_usable_size_t)(void *ptr);
117+
typedef void *(*system_realloc_t)(void *ptr, size_t size);
118+
119+
static system_aligned_alloc_t system_aligned_alloc;
120+
static system_calloc_t system_calloc;
121+
static system_free_t system_free;
122+
static system_malloc_t system_malloc;
123+
static system_malloc_usable_size_t system_malloc_usable_size;
124+
static system_realloc_t system_realloc;
125+
static size_t threshold_value = 0;
126+
106127
/*****************************************************************************/
107128
/*** The constructor and destructor of the proxy library *********************/
108129
/*****************************************************************************/
@@ -149,16 +170,40 @@ void proxy_lib_create_common(void) {
149170
LOG_ERR("creating UMF pool manager failed");
150171
exit(-1);
151172
}
173+
174+
LOG_DEBUG("proxy pool created");
175+
176+
#ifndef _WIN32
177+
*((void **)(&system_aligned_alloc)) = dlsym(RTLD_NEXT, "aligned_alloc");
178+
*((void **)(&system_calloc)) = dlsym(RTLD_NEXT, "calloc");
179+
*((void **)(&system_free)) = dlsym(RTLD_NEXT, "free");
180+
*((void **)(&system_malloc)) = dlsym(RTLD_NEXT, "malloc");
181+
*((void **)(&system_malloc_usable_size)) =
182+
dlsym(RTLD_NEXT, "malloc_usable_size");
183+
*((void **)(&system_realloc)) = dlsym(RTLD_NEXT, "realloc");
184+
185+
if (system_aligned_alloc && system_calloc && system_free && system_malloc &&
186+
system_malloc_usable_size && system_realloc) {
187+
// TODO threshold_value will be read from the environment variable
188+
threshold_value = 128;
189+
LOG_DEBUG("all system hooks found, threshold_value = %zu",
190+
threshold_value);
191+
} else {
192+
LOG_WARN("system hooks NOT found");
193+
}
194+
#endif
195+
152196
// The UMF pool has just been created (Proxy_pool != NULL). Stop using
153197
// the linear allocator and start using the UMF pool allocator from now on.
198+
LOG_DEBUG("proxy library initialized");
154199
}
155200

156201
void proxy_lib_destroy_common(void) {
157202
if (utils_is_running_in_proxy_lib()) {
158203
// We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159204
// because it could lead to use-after-free in the program's unloader
160205
// (for example _dl_fini() on Linux).
161-
return;
206+
goto fini_proxy_lib_destroy_common;
162207
}
163208

164209
umf_memory_pool_handle_t pool = Proxy_pool;
@@ -168,6 +213,10 @@ void proxy_lib_destroy_common(void) {
168213
umf_memory_provider_handle_t provider = OS_memory_provider;
169214
OS_memory_provider = NULL;
170215
umfMemoryProviderDestroy(provider);
216+
LOG_DEBUG("proxy library destroyed");
217+
218+
fini_proxy_lib_destroy_common:
219+
LOG_DEBUG("proxy library finalized");
171220
}
172221

173222
/*****************************************************************************/
@@ -246,6 +295,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246295
/*****************************************************************************/
247296

248297
void *malloc(size_t size) {
298+
if (size < threshold_value) {
299+
return system_malloc(size);
300+
}
301+
249302
if (!was_called_from_umfPool && Proxy_pool) {
250303
was_called_from_umfPool = 1;
251304
void *ptr = umfPoolMalloc(Proxy_pool, size);
@@ -257,6 +310,10 @@ void *malloc(size_t size) {
257310
}
258311

259312
void *calloc(size_t nmemb, size_t size) {
313+
if ((nmemb * size) < threshold_value) {
314+
return system_calloc(nmemb, size);
315+
}
316+
260317
if (!was_called_from_umfPool && Proxy_pool) {
261318
was_called_from_umfPool = 1;
262319
void *ptr = umfPoolCalloc(Proxy_pool, nmemb, size);
@@ -276,15 +333,20 @@ void free(void *ptr) {
276333
return;
277334
}
278335

279-
if (Proxy_pool) {
336+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
280337
if (umfPoolFree(Proxy_pool, ptr) != UMF_RESULT_SUCCESS) {
281338
LOG_ERR("umfPoolFree() failed");
282-
assert(0);
283339
}
284340
return;
285341
}
286342

287-
assert(0);
343+
if (threshold_value) {
344+
system_free(ptr);
345+
return;
346+
}
347+
348+
LOG_ERR("free() failed: %p", ptr);
349+
288350
return;
289351
}
290352

@@ -303,18 +365,27 @@ void *realloc(void *ptr, size_t size) {
303365
return ba_leak_realloc(ptr, size, leak_pool_contains_pointer);
304366
}
305367

306-
if (Proxy_pool) {
368+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
307369
was_called_from_umfPool = 1;
308370
void *new_ptr = umfPoolRealloc(Proxy_pool, ptr, size);
309371
was_called_from_umfPool = 0;
310372
return new_ptr;
311373
}
312374

313-
assert(0);
375+
if (threshold_value) {
376+
return system_realloc(ptr, size);
377+
}
378+
379+
LOG_ERR("realloc() failed: %p", ptr);
380+
314381
return NULL;
315382
}
316383

317384
void *aligned_alloc(size_t alignment, size_t size) {
385+
if (size < threshold_value) {
386+
return system_aligned_alloc(alignment, size);
387+
}
388+
318389
if (!was_called_from_umfPool && Proxy_pool) {
319390
was_called_from_umfPool = 1;
320391
void *ptr = umfPoolAlignedMalloc(Proxy_pool, size, alignment);
@@ -330,19 +401,28 @@ size_t _msize(void *ptr) {
330401
#else
331402
size_t malloc_usable_size(void *ptr) {
332403
#endif
333-
334-
// a check to verify we are running the proxy library
404+
// a check to verify if we are running the proxy library
335405
if (ptr == (void *)0x01) {
336406
return 0xDEADBEEF;
337407
}
338408

339-
if (!was_called_from_umfPool && Proxy_pool) {
409+
if (ba_leak_pool_contains_pointer(ptr)) {
410+
return 0; // unsupported in case of the ba_leak allocator
411+
}
412+
413+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
340414
was_called_from_umfPool = 1;
341415
size_t size = umfPoolMallocUsableSize(Proxy_pool, ptr);
342416
was_called_from_umfPool = 0;
343417
return size;
344418
}
345419

420+
if (threshold_value) {
421+
return system_malloc_usable_size(ptr);
422+
}
423+
424+
LOG_ERR("malloc_usable_size() failed: %p", ptr);
425+
346426
return 0; // unsupported in this case
347427
}
348428

0 commit comments

Comments
 (0)