Why does LD_PRELOAD not work for one of the loaded shared libraries?

I have my own shared library RedHat Linux 5.0, which provides functions freeand malloc:

>nm ./libmem_consumption.so | grep -P -e "\bfree\b|\bmalloc\b"
0000000000006540 T free
00000000000088a0 T malloc

This shared library is responsible for providing information about process memory consumption. Unfortunately, there is a problem with this shared library when it is used with Apache httpd. When Apache httpd starts with this library, I get coredump in libc::freeand a message stating that the pointer is invalid. The problem seems to be in http.so, which is a shared library loaded by libphp5.so, loading httpd.

Actually, when I do not load http.so, everything is in order, and there is no coredump. (Download or no download is http.socontrolled by a directive in the configuration file: extension = http.so) When I download http.so, the httpd process processes the command.

httpd stands out in this way:

LD_PRELOAD=./libmem_consumption.so ./bin/httpd -f config

and coredumps on exit.

When I set LD_BIND_NOW = 1 and it http.soloads, I see (under gdb) that http.so has a pointer free@pltto libc::free, and in another loaded library (for example libphp5.so) free@pltpoints to libmem_consumption.so::free. How is this possible?

By the way, when I export LD_DEBUG = all and save the output to a file, I see these lines for libphp5.so (which is also loaded):

 25788: symbol=free;  lookup in file=/apache2/bin/httpd [0]
 25788: symbol=free;  lookup in file=/apache2/ps/lib/libmem_consumption.so [0]
 25788: binding file /apache2/modules/libphp5.so [0] to /apache2/ps/lib/libmem_consumption.so [0]: normal symbol `free' [GLIBC_2.2.5]

And quite another for http.so:

 25825: symbol=free;  lookup in file=/apache2/ext/http.so [0]
 25825: symbol=free;  lookup in file=/apache2/ps/lib/libz.so.1 [0]
 25825: symbol=free;  lookup in file=/apache2/ps/lib/libcurl.so.4 [0]
 25825: symbol=free;  lookup in file=/lib64/libc.so.6 [0]
 25825: binding file /apache2/ext/http.so [0] to /lib64/libc.so.6 [0]: normal symbol `free'

It LD_PRELOAD=./libmem_consumption.sodoes not seem to be used for http.sowhen searching free. Why is LD_PRELOAD ignored?

+3
1

, http.so RTLD_DEEPBIND, LD_PRELOAD .

http://linux.die.net/man/3/dlopen:

RTLD_DEEPBIND ( glibc 2.3.4)      . , . POSIX.1-2001.

:

  #include <dlfcn.h>
  #include <unistd.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  static void initialize_my_dlopen(void) __attribute__((constructor));

  void* (*real_dlopen)(const char *, int flag);
  static int unset_RTLD_DEEPBIND=0;
  static int _initialized = 0;

  static void initialize_my_dlopen(void)
  {
    if (_initialized)
        return;
    real_dlopen  = (void *(*)(const char *,int))dlsym(RTLD_NEXT, "dlopen");
    unset_RTLD_DEEPBIND = atoi(getenv("UNSET_RTLD_DEEPBIND") ? getenv("UNSET_RTLD_DEEPBIND") : "0");
    printf("unset_RTLD_DEEPBIND: %d\n", unset_RTLD_DEEPBIND);
    _initialized = 1;
  }

  extern "C" {

    void *dlopen(const char *filename, int flag)
    {
      int new_flag = unset_RTLD_DEEPBIND == 0 ? flag : flag & (~RTLD_DEEPBIND);
      return (*real_dlopen)(filename, new_flag);
    }
  }

:

  gcc -shared -fPIC -g -m64 my_dlopen.cpp -o libmy_dlopen.so -ldl

UNSET_RTLD_DEEPBIND 0 httpd .

export UNSET_RTLD_DEEPBIND=0
LD_PRELOAD=./libmy_dlopen.so:./ps/lib/libmem_consumption.so ./bin/httpd -f config  

UNSET_RTLD_DEEPBIND 1 httpd, .

export UNSET_RTLD_DEEPBIND=1
LD_PRELOAD=./libmy_dlopen.so:./ps/lib/libmem_consumption.so ./bin/httpd -f config  

LD_DEBUG = all UNSET_RTLD_DEEPBIND: 1:

 10678: symbol=free;  lookup in file=/apache2/bin/httpd [0]
 10678: symbol=free;  lookup in file=/apache2/libmy_dlopen.so [0]
 10678: symbol=free;  lookup in file=/apache2/ps/lib/libmem_consumption.so [0]
 10678: binding file /apache2/ext/http.so [0] to /apache2/ps/lib/libmem_consumption.so [0]: normal symbol `free'
+8

All Articles