Leak/Address sanitizer in a shared library without LD_PRELOAD - shared-libraries

I'm looking to use Clang's leak/address sanitizer on my shared library, which is loaded from JVM or dotnet (Linux) at runtime, so I can't recompile the binary.
Using LD_PRELOAD makes for a very noisy output, a lot (presumably false positive?) leaks get reported from the JVM itself. The sanitizer outright crashes when LD_PRELOADing for dotnet.
Is there any way to statically link the sanitizer into the shared library (or dynamically without LD_PRELOAD)?

First thing first, you can not statically link sanitizer runtime libs into your library. It has to be preloaded to intercept std allocator (malloc, etc.) and would malfunction otherwise (there's a special check at Asan startup that ensures that libasan was preloaded).
Noisy output in JVM may well be legitimate errors.
Using LD_PRELOAD makes for a very noisy output, a lot (presumably false positive?) leaks get reported from the JVM itself.
The sanitizer outright crashes when LD_PRELOADing
for dotnet.
Is it a real crash or diagnosed memory error? Crash can be reported in Asan tracker.
Memory error should be reported to dotnet project but you can still continue execution after it using continue-after-error mode (grep for "continue-after-error" in Asan FAQ).

Related

What is determing which `malloc` will be called for an injected code?

I'm using frida to hook various functions of the Firefox web browser running atop of Windows. One of the symbols I hooked was mozglue::malloc() which calls for the jemalloc allocator.
In the process address-space there are three malloc() symbols:
In msvcrt.lib (static linking)
In ucrtbase.dll for dynamic linking
The already mentioned in mozglue.dll
I was expecting that all memory allocations that made by the Firefox processes will be allocated by the mozglue::malloc() and of course this truely happens.
I didn't expect that memory allocations that made by the frida JS agent which was injected to the target process will also be allocated using jemalloc, and honestly I still can't figure out why.
frida couldn't possibly know that there is a mozglue::malloc() symbol when its first attaching to a process, from the frida point of view there is a simple call for malloc(), so how and why this call is redirected from the default CRT symbols to the Mozila dll? This probably have something to do with the PE design, but I can't put the finger on it...
Thank for any help / insight / answer
mozglue::malloc shouldn't even be the only function called inside Firefox, because some system functions called by Firefox will use system malloc.
I see only one explanation: Firefox replaces original malloc calls in memory with its own version of malloc. Having a check at the source code supports this idea: https://searchfox.org/mozilla-central/source/memory/build/replace_malloc.h

Valgrind is not detecting HDF5 leaked resources

I have noticed that Valgrind is not detecting resources created with the C API of HDF5 and that are not closed before the end of the program, though I launched it with the option --leak-check=full. Is that normal ?
I often rely on Valgrind before shipping the code, but today I was surprised and frustrated when reviewing the code that it was not detected by it.
valgrind memcheck tool detects memory allocated/released by the 'standard' allocators, such as malloc/free/new/delete/...
If the C API of HDF5 is not using (internally) the above standard allocators,
then there is no way that valgrind could guess by itself what to monitor.
If HDF5 is implementing its own heap management (e.g.based on mmap, and cutting
these blocks in smaller allocated blocks),
then valgrind provides 'client requests' allowing to have some valgrind support
for such non standard allocators. But that all implies some work in the HDF5
sources.
See e.g. http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.mempools
for more information about how to describe such non standard allocators.
Some libraries/tools that are implementing their own non standard allocators
have sometime a way (e.g. an environment variable) to indicate to bypass
these non standard allocators, and still use malloc/free/...
Again, up to HDF5 to provide this.
If now HDF5 really uses the standard allocators and valgrind cannot track
what it does, then file a bug on valgrind bugzilla.

Gulp/Node: error while loading shared libraries: cannot allocate memory in static TLS block

Trying to run gulp and getting this output
$ gulp
node: error while loading shared libraries: cannot allocate memory in static TLS block
From what I have found, this seems to relate to gcc or g++, not sure how it pertains to node or gulp. Either way I can't seem to run gulp anymore. Should also mention, this just popped up today. It was running fine yesterday.
EDIT: seems like it's for all node commands. Just tried running npm -v to get the version number and it has the same output. Same with node -v
Running CentOS 6.9
The GNU toolchain supports various kinds of TLS, and one of them (the initial-exec model) involves what is essentially a fixed offset from the thread control block. At program startup, the dynamic linker computes all the offsets and makes sure that all threads have sufficient space for all the required thread local variables.
However, with dlopen, this does not work in general because it is not possible to move the thread control block around to make room for more thread-local variables. The current glibc dynamic linker has a heuristic which reserves some space for future dlopen calls, but if you load a number of shared objects, each wither their own thread-local variables, this is not enough.
The usual workaround is to use the LD_DEBUG=files environment variable (or strace) to find relevant shared objects loaded with dlopen (unfortunately, the error message you quoted does not provide this information). After that, you can use the LD_PRELOAD environment variable to tell the dynamic linker to load them early. (It is sufficient to do this for the shared object which is dlopened, its dependencies are processed automatically.) This has the side effect that the computation at program startup takes into account their TLS needs, and when the dlopen call happens later at run time, no additional TLS variables have to be allocated. However, this approach does not work for all shared objects because it affects symbol lookup and the order in which ELF constructors run.
In the general case, it may be necessary to switch some shared objects to the global-dynamic TLS model (which requires recompiling them), or use a glibc build with an increased TLS reserve. Unfortunately, the reserve cannot currently be set at run time.

Static Analysis Tools for GLib and GDBus

Does anyone know of any tools or techniques for detecting memory leaks when using GLib and GDBus? I am relatively new to using both libraries and believe I am using the API's correctly, but it would be great if there was a tool that I could use to confirm that I am cleaning up my resources correctly. I have ran my code through various lint-type programs, but these likely do not detect anything abstracted away into a library.
I am looking for either a tool aimed specifically at GLib or GDBus or a tool that I could instrument so target these libraries? Maybe there are even some compile time flags that I can set for GLib or GDBus?
I just recently did some voodoo with glib/gdbus/libsoup and from my experience valgrind and valgrind/massif do a very good job (though not really static analysis but runtime analysis).
valgrind (use malloc even for g_slice_alloc/g_slice_new, makes valgrind less confused, gc-friendly nullifies all glib internal pointers)
G_DEBUG=gc-friendly G_SLICE=always-malloc valgrind ./yourapp
There will be still false positives in the output – use a supression file to hide them.
massif (use resident modules to prevent a lot of noise)
G_DEBUG=resident-modules valgrind --tool=massif --depth=10 --max-snapshots=1000 --alloc-fn=g_malloc --alloc-fn=g_realloc --alloc-fn=g_try_malloc --alloc-fn=g_malloc0 --alloc-fn=g_mem_chunk_alloc --threshold=0.01 ./yourapp --your --app --options
Use some visualization tool to make massifs output readable (couple of MB logs) massif-visualizer does a good job
Keep in mind that glib has a couple of MB of static allocated stuff (all the GObject type classes)
If you need to debug the libraries themself, there is no way around compiling them with debug flags (-g)

valgrind - Find memory leak in a shared library

I need to know ways to find out the memory leaks in a shared library which will be loaded to a release binary. I mean shared library I built with -g option but the binary that loads the shared library is not built with -g option.
I get the leak report as follows.
==739== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==739== by 0x84781B1: ???
==739== by 0x87507F5: ???
==739== by 0x874CF47: ???
==739== by 0x874E657: ???
==739== by 0x874F7C2: ???
==739== by 0x8779C0C: ???
Please let me know how to get the stack trace of the leak from the shared library?
Assuming that the leak really is coming from your shared library then I don't think the problem is the lack of debugging in the main executable.
More likely your problem is that the executable is unloading the shared library by calling dlclose before it finishes. That means that when valgrind comes to check for leaks all the symbol information for the library is gone as the library is no longer loaded.
If you can rebuild the executable then the easiest solution may be to temporarily stop it calling dlclose so that the library stays loaded until the end.
If you can't do that, then try using LD_PRELOAD to keep the library loaded, like this:
LD_PRELOAD="/path/to/library.so" valgrind my-executable
which will hopefully trick the dynamic linker into keeping the library loaded even after it has been closed.
As the previous answer suggests, this is because you have closed your libraries before the program terminates and therefore symbol information is not available to valgrind.
Using LD_PRELOAD didn't work for me; I now have two builds; one that explicitly does not call dlclose(); on this build, valgrind correctly reports line number information as you would expect with dynamic linking.

Resources