ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 为什么LD_PRELOAD不适用于其中一个已加载的共享库?

2019-07-25 20:52:34  阅读:207  来源: 互联网

标签:c linux apache2 shared-libraries coredump


我在RedHat Linux 5.0上有一个内部共享库,它提供免费的功能和malloc:

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

此共享库负责提供有关进程内存消耗的信息.
不幸的是,当它与Apache httpd一起使用时,这个共享库存在问题.
当使用这个库运行Apache httpd时,我得到一个libc :: free的coredump和一个指针无效的消息.
问题似乎是在http.so中,这是一个由libdp5.so加载的共享库,由httpd加载.

实际上,当我没有加载http.so一切都没关系,没有coredump.
(加载或不加载http.so由配置文件中的指令管理:extension = http.so)
当我加载http.so httpd进程coredumps.

httpd以这种方式推出:

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

和退出时的coredumps.

当我设置LD_BIND_NOW = 1并加载http.so时,我看到(在gdb下)http.so有免费@ plt指向libc :: free而在其他加载中
库(例如libphp5.so)free @ plt指向libmem_consumption.so::free.
怎么可能呢?

顺便说一下,当我导出LD_DEBUG = all并将输出保存到文件时,我看到这些行为libphp5.so(也加载了):

 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]

和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'

当查找free时,似乎LD_PRELOAD =./ libmem_consumption.so不用于http.so.为什么忽略LD_PRELOAD?

解决方法:

它看起来http.so加载了RTLD_DEEPBIND标志,这就是为什么LD_PRELOAD被其他一个共享库忽略的原因.

这是从http://linux.die.net/man/3/dlopen

RTLD_DEEPBIND (since glibc 2.3.4)
Place the lookup scope of the symbols in this library ahead of the global scope. This means that a self-contained library will use its
own symbols in preference to global symbols with the same name
contained in libraries that have already been loaded. This flag is not
specified in 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时,程序coredumps.

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  

这是UNSET_RTLD_DEEPBIND为1的LD_DEBUG = all的输出:

 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'

标签:c,linux,apache2,shared-libraries,coredump
来源: https://codeday.me/bug/20190725/1536715.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有