zoukankan      html  css  js  c++  java
  • man ld.so 的翻译(转)linux动态库加载方式

    动态库加载器可以通过运行一些动态链接的程序来间接调用(在这种情况中,不需要向动态库加载器指定任何命令行参数,对于 ELF 文件,动态库链接器的路径存储在将被执行的程序的 .interp section 中)或直接通过 /lib/ld-linux-so.* xx 来调用。

    ld.so 与 ld-linux.so* 查找并加载程序依赖的动态库,为程序正常运行准备动态库环境,然后再运行程序。

    Linux 中的二进制程序默认都是动态链接的,除非在编译时向 ld 命令指定 -static 选项。

    ld.so 处理 a.out 格式的二进制,ld-linux.so*(libc5 中为 /lib/ld-linux.so.1,glibc2 中为 /lib/ld-linux.so.2 ) 处理 ELF 格式(一种每个人都使用了很多年的文件格式)的文件。

    这两个加载器有相同的行为,他们都支持文件与 ldd 程序、ldconfig 与 /etc/ld.so.conf.

    程序依赖的共享库按照如下路径顺序进行查找:

    针对 ELF 格式文件,当 DT_RUNPATH 属性不存在的情况下,使用二进制程序 dynamic section 中存在的 DT_RPATH 属性指定的路径来搜索 。DT_RPATH 已经被弃用。

    使用环境变量 LD_LIBRARY_PATH 中指定的路径来搜索。如果可执行程序设定了 setuid/setgid,这一步将被跳过。

    从缓存文件 /etc/ld.so.cache 中查找。如果程序在链接时使用了 -z nodeflib 选项,默认库路径中的库及那个会被跳过。安装到硬件兼容目录中的库将会比其它库优先查找。

    在默认的 /lib 然后时 /usr/lib 中寻找,如果程序在链接时使用了 -z nodeflib 选项,这一步将被跳过。

    $ORIGIN and rpath

    ld.so 将在 rpath 中指定的 $ORIGIN 字符串作为包含可执行程序的目录。因此一个位于 somedir/app 的程序可以使用 gcc -Wl,-rpath,'$ORIGIN/../lib'来编译,这样他竟会在 somedir/lib 路径中来查找相关的动态库而不用关心 somedir 在目录层次中的位置。

    这方便了创建一个可以“交钥匙”的程序,这种程序不需要被安装到特定的目录中,可以被解压到任一目录中并且仍然能够找到它们自己的共享库。

    OPTIONS
          
           --list 列出所有的依赖,和解决依赖的结果
    
           --verify 验证程序是动态链接的并且该动态库链接器能够处理它
    
           --library-path PATH 使用 PATH 代替 LD_LIBRARY_PATH 环境变量的设定。
           
           --inhibit-rpath LIST
                忽略目标对象 LIST 中的 RPATH 和 RUNPATH 信息,如果 ld.so 谁当了 setuid 或 setgid 这个参数将被忽略。
                
           --audit LIST
                使用目标文件中的 LIST 作为审核员。

    HARDWARE CAPABILITIES

    一些库使用特定的硬件指令编译,这些指令并不一定在每个 cpu 上都存在。这些库应该被安装路径名中包括需要的硬件特性的目录中,例如 /usr/lib/sse2.

    当前不同架构能够识别的硬件特性名称如下:

    Alpha  ev4, ev5, ev56, ev6, ev67
    
           MIPS   loongson2e, loongson2f, octeon, octeon2
    
           PowerPC
                  4xxmac,  altivec, arch_2_05, arch_2_06, booke, cellbe, dfp, efp‐
                  double, efpsingle,  fpu,  ic_snoop,  mmu,  notb,  pa6t,  power4,
                  power5,  power5+,  power6x,  ppc32,  ppc601,  ppc64,  smt,  spe,
                  ucache, vsx
    
           SPARC  flush, muldiv, stbar, swap, ultra3, v9, v9v, v9v2
    
           s390   dfp, eimm, esan3, etf3enh,  g5,  highgprs,  hpage,  ldisp,  msa,
                  stfle, z900, z990, z9-109, z10, zarch
    
    
           x86 (32-bit only)
                  acpi,  apic,  clflush,  cmov,  cx8,  dts, fxsr, ht, i386,
                  i486, i586, i686, mca, mmx,  mtrr,  pat,  pbe,  pge,  pn,
                  pse36, sep, ss, sse, sse2, tm

    ENVIRONMENT

    There are four important environment variables.
    
       LD_BIND_NOW
              (libc5;  glibc  since 2.1.1) 当这个变量被设定为非空值时,动态库加载器将会在程序启动
              的时候解决所有依赖的符号,而不是在符号被第一次引用到的
              时才处理符号,这对于调试器非常有用。
              
       LD_LIBRARY_PATH
              一个以冒号分隔的目录表,这个目录表在 ELF 程序执行时用来搜索动态库。与 PATH 环境变行为类似。
              
       LD_PRELOAD
              一个以空白字符分割的额外的、用户指定的、需要在其它动态
              库加载前加载的动态库。
              
              设定这个变量能够选择性的覆盖其它动态库中的函数。对于 setuid、setgid 的 ELF 
              程序,只有在标准搜索路径中也设定了 setuid 
              的动态库才会被加载。
              
       LD_TRACE_LOADED_OBJECTS
       
            只针对 ELF 
            格式文件。当该变量被设定为非空值时,程序将会输出它依赖的
            动态库,像运行 ldd 一样的结果,而不会真正运行。
    
        除了这四个变量,还有一些内部使用的变量。我只列举几个有趣的变量。
        
       LD_AUDIT
       
            glibc 2.4 及之后的版本能够使用这个变量。能够设定审计点,例如在加载一个新的动态库、处理一个符号、调用一个符号时调用 audit 动态库重的函数来通知审计程序。
            
       LD_BIND_NOT
              (glibc since 2.1.95) Do not update the GOT (global offset
              table) and PLT (procedure linkage table) after  resolving
              a symbol.
    
       LD_DEBUG
            glibc 2.1 之后的版本能够使用该变量。能够输出调试信息。
            
       LD_DEBUG_OUTPUT
       
            LD_DEBUG 开启后,输出信息输出位置,默认为 stdout.
            
       LD_DYNAMIC_WEAK
       
            glibc 2.1.91 及之后的版本。运行弱符号被覆盖。
            
       LD_HWCAP_MASK
              (glibc since 2.1) Mask for hardware capabilities..
    
       LD_ORIGIN_PATH
       
            glibc 2.1 及之后的版本。指定访问可执行程序的路径。
            
       LD_POINTER_GUARD
       
            gligc 2.4 之后。设定为 0 关闭 pointer guarding,其它值均表示开启 pointer guarding 功能,默认开启。
            
            这是个安全机制,对于一些存储在可写程序内存的指针(setjmp 
            保存的返回地址、不同 glibc 
            内部使用的函数指针)以半随机方式分隔以提供攻击者利用缓冲
            区溢出或堆栈溢出来劫持指针。
            
        
       LD_PROFILE
            
            profile 的动态库路径名,结果写入到
            
            "$LD_PROFILE_OUT‐
              PUT/$LD_PROFILE.profile" 中。
    
       LD_PROFILE_OUTPUT
       
            glibc 2.1 及之后的版本。LD_PROFILE 输出的目录位置。默认值为 /var/tmp 目录
            
       LD_SHOW_AUXV
            glibc 2.1 输出从内内核传出的辅助性数组内容
        
    
       LD_USE_LOAD_BIAS
            默认情况下,可执行目标文件与预链接的动态库文件将指明它们
            依赖的动态库的基地址,(非预链接、位置无关的可执行程序)、其它共享库则不会指明。当 
            LD_USER_LOAD_BIAS 变量被定义,可执行程序与 
            PIE(位置无关的可执行部分) 也会指明这个基地址。如果 LD_USER_LOAD_BIAS 值为 
            0,可执行文件与位置无关的可执行文件都不会指明这个及地址。
    
       LD_VERBOSE
       
            glibc 2.1 
            如果该变量被设定为一个非空字符串,当请求检索程序的信息时
            (LD_TRACE_LOADED_OBJECTS 被设定或 --list 或 --verfiy 
            选项传递给动态库链接器)将会输出符号的详细信息。
            
       LD_WARN
            只针对 ELF 格式文件。glibc 2.1.3 如果被设定为非空字符串,将会在未找到符号时报警。
            
       LDD_ARGV0
       
            libc5 中 ldd 使用的 argv[0] 的值,当没有一个可用时。

    FILES

    /lib/ld.so
    a.out 格式的动态库链接、加载器
    /lib/ld-linux.so.{1,2}
    ELF 格式的动态库链接、加载器
    /etc/ld.so.cache
    这个文件中包含了编译的动态库目录列表用于检索动态库以及一个排序的候选动态库列表。
    /etc/ld.so.preload
    这个文件中包含了以空白字符分割的将在程序执行之前加载的动态库。
    lib*.so*
    动态库
    NOTES

    ld.so 功能在使用 ligc 4.4.3 及之后的版本上可用。ELF 功能在 linux 1.1.52 与 libc5 及之后的版本都可使用。

    LD_DEBUG 变量中的子命令:

    LD_DEBUG=help ls
    Valid options for the LD_DEBUG environment variable are:
    
      libs        display library search paths
      reloc       display relocation processing
      files       display progress for input file
      symbols     display symbol table processing
      bindings    display information about symbol binding
      versions    display version dependencies
      scopes      display scope information
      all         all previous options combined
      statistics  display relocation statistics
      unused      determined unused DSOs
      help        display this help message and exit

    在解决动态库依赖问题时可能要用到。

    对 setuid 与 setgid 程序的限定
    对 setuid 与 setgid 的程序,使用上面一些内部的环境变量可能会带来一些安全问题。如果不对 setuid 与 setgid 的程序的动态库加载相关功能进行限制,那么可能会出现非法的提权操作。

    举个简单的例子,linux 中的 passwd 命令就是一个设定了 setuid 的程序,设定此权限的目的在于让所有人都能够修改自己的密码,而 passwd 命令的属主与属组都是 root,当不同的用户在执行时将获得限制的 root 权限。如果使用动态库链接器 hook 某些函数,就可能会打破这种限制,达到提权的目的。

    基于这样的问题,动态库链接器对内部一些可能修改正常程序执行行为的功能进行了严格限定,一些环境变量将不会对具有 setuid 与 setgid 的程序生效。

    原文链接:https://blog.csdn.net/Longyu_wlz/article/details/108511931

    联系方式:emhhbmdfbGlhbmcxOTkxQDEyNi5jb20=
  • 相关阅读:
    树莓派安装parrot linux记录
    Arch linux(UEFI+GPT)安装及后续优化教程
    VS部分安全函数用法
    C语言博客作业06--结构体&文件
    C语言博客作业05--指针
    C语言博客作业04--数组
    C语言博客作业03--函数
    C语言博客作业02--循环结构
    DS博客作业08--课程总结
    DS博客作业07--查找
  • 原文地址:https://www.cnblogs.com/zl1991/p/14717320.html
Copyright © 2011-2022 走看看