linux查看进程加载了哪些dll,LINUX动态链接库加载初探

在基于GNU

glibc的系统里,包括所有的linux系统,启动一个ELF格式的二进制可执行文件会自动启动和运行一个program

loader。对于Linux系统,这个loader的名字是/lib/ld-linux.so.X(X是版本号)。这个loader启动后,反过来就会load所有的其他本程序要使用的共享函数库。

到底在哪些目录里查找共享函数库呢?这些定义缺省的是放在/etc/ld.so.conf文件里面。我们可以修改这个文件,加入我们自己的一些特殊的路径要求。大多数RedHat系列的发行包的/etc/ld.so.conf文件里面不包括/usr/local/lib这个目录,如果没有这个目录的话,我们可以修改/etc/ld.so.conf,自己手动加上这个条目。

如果你想覆盖某个库中的一些函数,用自己的函数替换它们,同时保留该库中其他的函数的话,你可以在/etc/ld.so.preload中加入你想要替换的库(.o结尾的文件),这些preloading的库函数将有优先加载的权利。

当程序启动的时候搜索所有的目录显然会效率很低,于是Linux系统实际上用的是一个高速缓冲的做法。Ldconfig缺省情况下读出/etc/ld.so.conf相关信息,然后设置适当地符号链接,然后写一个cache到/etc/ld.so.cache这个文件中,而这个/etc/ld.so.cache则可以被其他程序有效的使用了。这样的做法可以大大提高访问函数库的速度。这就要求每次新增加一个动态加载的函数库的时候,就要运行ldconfig来更新这个cache,如果要删除某个函数库,或者某个函数库的路径修改了,都要重新运行ldconfig来更新这个cache。通常的一些包管理器在安装一个新的函数库的时候就要运行ldconfig。

----------------------------------------------------------------

关于Linux和Unix动态连接库的安全ZT

实际上所有程序执行都依赖于库。在包括Linux的大多数现代类Unix系统中,程序缺省使

用动态连接库(DLL)进行编译。这样就可以更新某个库,所有使用该库的程序如果可能

的话,都将使用新的(希望有所改进的)版本。

动态连接库通常被放在若干特殊目录下。通常这些目录包括/lib、/usr/lib、有关PAM模

块的/lib/security、有关X-windows的/usr/X11R6/lib和/usr/local/lib。

对于库的命名和进行库的符号连接有些特殊约定,这样就可以更新库,同时继续支持需

要使用不具有反向兼容的老版本库的程序。在执行特定程序时可以覆盖某个指定库,甚

至只覆盖某个库里的指定函数。这是类Unix系统相对于类Windows系统的一个实际优点;

我相信类Unix系统有一个更好的系统来处理库的更新,这也是Unix和Linux系统被认为比

基于Windows的系统更稳定的原因。

在包括所有Linux系统的基于GNU glibc的系统中,程序启动时自动寻找的目录列表存储

在文件/etc/ld.so.conf中。很多源于Red Hat的发行版一般在文件/etc/ld.so.conf中不

包含/usr/local/lib。我认为这是个Bug,要在源于Red Hat的系统里运行很多程序都需

要进行一个通用的“修复”,把/usr/local/lib加入/etc/ld.so.conf。如果只是想覆盖

某个库里的若干函数,而想保留该库的其它部分,可以在/etc/ld.so.preload中输入要

覆盖的库名(.o文件);这些“预载入”的库会优先于标准库使用。通常这种预载入文

件是用于紧急补丁的;发行版在发行时一般不会包含这样的文件。在程序启动时寻找所

有这些目录太花时间,所以实际上使用了一个cache管理方法。程序ldconfig(8)缺省读

入文件/etc/ld.so.conf,在动态连接目录里建立相应的符号连接(这样就遵循了标准约

定),然后把cache写入/etc/ld.so.cache,这样就可以被其它程序使用了。所以一旦增

加一个DLL,或删除一个DLL,或者DLL目录集发生改变,ldconfig就要运行一次;在安装

库时,运行ldconfig通常是软件包管理程序需要执行的一个步骤。在启动时,程序使用

动态加载程序来读入文件/etc/ld.so.cache,然后载入其所需的库。

各种环境变量可以控制这一过程,而且事实上也有允许覆盖此过程的环境变量(所以可

以在某次特别的执行过程中临时替换某个不同的库)。在Linux下,环境变量LD_LIBRAR

Y_PATH是一组用逗号隔开的目录,在查找标准目录集之前先查找这些库;这在调试新库

或为特殊目的使用非标准库时很有用。变量LD_PRELOAD列出了覆盖标准集的函数所在的

目标文件,就像/etc/ld.so.preload一样。

如果不采取特别的措施,允许用户控制动态连接库会对setuid/setgid程序造成灾难性的

后果。因此在实现GNU glibc时,如果是setuid或setgid程序,将忽略这些变量(和其它

类似的变量),或者严格限制这些变量所起的作用。GNU的glibc库通过检查程序的证明

来确定其是否为setuid或setgid程序;如果uid和euid不同,或者gid和egid不同,则库

就假设该程序为setuid/setgid程序(或者为其子程序),然后严格限制它控制连接的能

力。如果载入GNU的glibc库,就可以看到这种情况;请特别阅读一下文件elf/rtld.c和

sysdeps/generic/dl-sysdep.c。这就意味着如果使uid和gid等于euid和egid,再调用程

序,这些变量就具有完全的效力。其它类Unix系统处理这些情况有所不同,但原因相同

:一个setuid/setgid程序不应受到环境变量集的过分影响。

阅读(2846) | 评论(0) | 转发(0) |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值