6

I am trying to provide memory wrappers on CentOS and using clang compiler/linker. I wrote wrappers for the allocation functions (malloc et al) and rerouted the calls using -Wl,-wrap,malloc.

This all works fine and I can see it in action. void* mem = malloc(10); // routes to __wrap_malloc free(mem);// routes to __wrap_free

However, the problem I am seeing is that any memory allocated within libc is not being routed to my wrapper but the application is making the free call that gets intercepted (and crash as a result). For example,

char* newStr = strdup("foo"); // The internal malloc in libcdoes not come to wrapper free(newStr); // The free call makes it to the wrapper

My program is in C++. I created a mallocimpl.cpp and did something like

extern "C"{ void* __wrap_malloc(size_t size) { // Route memory via custom memory allocator } //Similarly, __wrap_calloc, __wrap_realloc, __wrap_memalign and __wrap_free

Any ideas what I am doing wrong? Do I need any special compiler/linker flags?

Thanks in advance.

3 Answers3

6

The recommended way to replace the glibc malloc implementation is ELF symbol interposition:

This way, you do not have to recompile everything, including glibc, and your malloc replacement will still be called once glibc removes the malloc hooks.

The __wrap approach does not work without recompiling (or at least rewriting) everything because all other libraries (including glibc) will use non-wrapped symbols.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
Florian Weimer
  • 32,022
  • 3
  • 48
  • 92
  • While I was hoping to avoid stuff like LD_PRELOAD which brings additional complexity in the application and it's execution, I'll go ahead and accept this answer. At the moment, I'll not integrate this solution and just rely on deprecated hooks. It does not seem like they are going anywhere. The original commit said they'll be removed in next release but they are still around after 6 years (probably due to lack of a good equivalent replacement). – mast3r_of_univ3rs3 Mar 20 '18 at 22:03
  • Symbol interposition does not need `LD_PRELOAD`, you can just define the functions in the main program and export them (say, using `-Wl,-E`). The hooks will likely go away with the next glibc release. – Florian Weimer Mar 21 '18 at 07:54
1

There were some special "hooks" in glibc (__malloc_hook, __realloc_hook, __free_hook, __memalign_hook) to catch all mallocs of glibc: https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html

The GNU C Library lets you modify the behavior of malloc, realloc, and free by specifying appropriate hook functions. You can use these hooks to help you debug programs that use dynamic memory allocation, for example.

Hooks are unsafe and marked as deprecated in the man pages. Some variants are listed at An alternative for the deprecated __malloc_hook functionality of glibc

Also, check how alternative mallocs like jemalloc, tcmalloc and other implements their "preloading/linking of special library" to replace glibc malloc.

osgx
  • 90,338
  • 53
  • 357
  • 513
  • My current program actually uses hooks and I am trying to replace them with the wrappers for precisely the reason that they are deprecated :). – mast3r_of_univ3rs3 Mar 16 '18 at 01:41
  • @mast3r_of_univ3rs3, your wrappers (-Wl,-wrap,...) don't change code inside glibc... – osgx Mar 16 '18 at 01:58
0

The only way to guarantee matching malloc / free would be to recompile everything, including libc. This is probably not practical for you, so your best option is to somehow track the memory allocated by your malloc wrapper and then appropriately either deallocate it yourself or invoke __real_free in your free wrapper based on how the memory was allocated.

mnistic
  • 10,866
  • 2
  • 19
  • 33
  • Thanks for the suggestion. While I can track the mem allocator, I'd think there is a better solution for it. After all, the wrappers should be applied to the entire application. Also, I don't think I need to recompile everything. I have pre-built libraries like curl in my application whose allocations are getting re-routed correctly. The problem is unique to allocations made internally by libc. – mast3r_of_univ3rs3 Mar 16 '18 at 01:31
  • @mast3r_of_univ3rs3, LD_PRELOAD will work to replace all mallocs (library should replace every function of malloc family). Check how `jemalloc`, `tcmalloc` and other alternative malloc works with relinking to their library or ld_preloading it: JEMALLOC_OVERRIDE___LIBC_MALLOC etc – osgx Mar 16 '18 at 01:35
  • @mast3r_of_univ3rs3 Try the `LD_PRELOAD` trick suggested by osgx. Never used it myself before, but looks like it works! – mnistic Mar 16 '18 at 01:53