Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if a linux shared library has been preloaded using LD_PRELOAD

I'm familiar with using dlopen() to check if a shared library has been loaded into a process using a prior call to dlopen() without triggering a load if it isn't present, like so:

 void* lib = dlopen(lib_name, RTLD_NOLOAD);
 if (lib != NULL) {
   ...
 }

I've recently tried to apply the same pattern to determine if one of a handful of shared libraries have been loaded into a process space using LD_PRELOAD. However in all the cases, the above mentioned call to dlopen() returns NULL.

So basically, if I start the process using this command line

LD_PRELOAD=libawesome.so ./mycoolprocess

and then run the following check in the code in mycoolprocess.c

void* has_awesome = dlopen("libawesome.so", RTLD_NOLOAD);
if (has_awesome != NULL) {
  printf("libawesome is available\n");
}

the call to dlopen() always returns NULL no matter if the shared library has been loaded using LD_PRELOAD or not. Based on Andrew Henle's comment below I also tried calling dlopen with the absolute path to one of the reloaded shared objects, but dlopen in this case still returns NULL despite the shared object being preloaded.

So my question is twofold:

  1. Should the above pattern work for a library that's been loaded using LD_PRELOAD?
  2. Is there another way to have a process determine if a specific shared library has been preloaded?
like image 641
Timo Geusch Avatar asked Jun 09 '16 00:06

Timo Geusch


1 Answers

No and yes, respectively.

dlopen() and the LD_PRELOAD trick, although they both deal with shared libraries, operate in fundamentally different ways.

The LD_PRELOAD environment variable is handled by the dynamic linker/loader (ld-linux.so), and affects the resolution of relocation records in the executable binary itself. In a nutshell, at every point in your code where there's a call to a function that's defined in a dynamic library, the linker (at build time) will insert a placeholder for the memory address to jump to. At runtime, those placeholders are replaced by real addresses based on the shared libraries loaded into memory, which are themselves named in the executable, but may be overridden if LD_PRELOAD is used.

So once the executable is loaded into memory and all those placeholders have been filled in with real addresses, there's no simple (or portable) way of telling what came from where. However...

You could examine the running process' memory map. On Linux, this would mean parsing through /proc/<pid>/maps. The file contents are fairly self-explanatory, so just pick one at random and take a look.

No idea how you'd do it on other systems, but I believe most modern unixen have a /proc filesystem of some sort.

like image 60
nephtes Avatar answered Sep 29 '22 11:09

nephtes