【问题标题】:When will LD_PRELOAD be ignored什么时候会忽略 LD_PRELOAD
【发布时间】:2015-03-26 07:46:06
【问题描述】:

我正在尝试使用 LD_PRELOAD 在系统中包装一些函数,我首先导出环境变量LD_PRELOAD 指向我的.so 文件,然后我运行系统,我总是得到ERROR: ld.so: object '/full/path/to/wrap.so' from LD_PRELOAD cannot be preloaded: ignored. 所以我试图了解手册页上的 LD_PRELOAD:

附加的、用户指定的 ELF 共享库列表,在所有其他共享库之前加载。列表中的项目可以用空格或冒号分隔。这可用于选择性地覆盖其他共享库中的函数。使用描述下给出的规则搜索库。对于 set-user-ID/set-group-ID ELF 二进制文件,包含斜杠的预加载路径名将被忽略,并且只有在库文件上启用了 set-user-ID 权限位时才会加载标准搜索目录中的库。

我不是100%理解上面的文字,首先,它说

对于 set-user-ID/set-group-ID ELF 二进制文件,包含斜杠的预加载路径名将被忽略

如果不能使用斜线,如何设置LA_PRELOAD的完整路径?

第二个,它说

标准搜索目录中的库仅在以下情况下才会加载...

什么是标准搜索目录?

我的最后一个问题是了解何时会忽略 LD_PRELOAD?感谢您的帮助。

编辑:

当我像这样将 LD_PRELOAD 导出到/usr/lib/ 中的共享库时:export LD_PRELOAD=shared-lib.so,我摆脱了上述错误,但我没有 root 权限,所以我无法放入任何/usr/lib/ 下的文件,对此有什么建议吗?我想如果我可以设法在没有任何斜杠的情况下导出 LD_PRELOAD,它应该可以工作,但除非共享库文件在 /usr/lib/ 中,否则 LD_PRELOAD 需要完整路径。

【问题讨论】:

  • LD_PRELOAD 遵循标准库搜索路径。即您可以指定相对路径,例如/usr/lib,但不是绝对路径。不过,这只适用于 setuid/setgid 二进制文件。请注意,此行为高度依赖于系统,后者仅适用于 Linux。在其他系统上,LD_PRELOAD 未设置为 setuid/setgid。
  • 您是否正在运行具有 set-user-ID 或 set-group-ID 标志的程序?
  • @immibis 这也是另一个问题,如何识别二进制文件是否为set-user-ID
  • @user4016367 令人惊讶的是,有人刚刚在unix.stackexchange.com/questions/192588/… 上发布了这个消息(是你吗?)
  • 此外,大多数二进制文件不是 set-user-ID,这意味着您可以使用斜杠。

标签: c linux


【解决方案1】:

您可能希望导出 LD_DEBUG=files 以了解正在发生的事情,尽管输出会非常冗长,并且您可能需要一段时间才能找到相关行。

编辑:因为这没有帮助,您可能想尝试其他 LD_DEBUG 选项:

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
all         all previous options combined
statistics  display relocation statistics
unused      determined unused DSOs
help        display this help message and exit

all 看起来有点矫枉过正,但也许libssymbols 会显示一些有用的东西。

【讨论】:

  • 嗨,它只是打印ERROR: ld.so: object '/full/path/to/wrap.so' from LD_PRELOAD cannot be preloaded: ignored,如何知道它为什么被忽略。
  • 同一消息的另一个原因,就是让我感到震惊:可执行文件(令我惊讶)是 i386 的,而共享库是 amd64 的,即 32 位与 64 位。有问题的系统在一个过程中支持两者但不支持混合匹配。 “为什么 LD_DEBUG=all 一直提到 i386?”让我直截了当-谢谢。
【解决方案2】:

这意味着两件事:

  1. “/full/path/to/wrap.so”不是共享库(与file '/full/path/to/wrap.so' 核对),
  2. 或者“/full/path/to/wrap.so”缺少(本身)一个共享库(使用ldd '/full/path/to/wrap.so'检查)

如果上面没有用,那么尝试一个非常低级的工具:

$ strace /path/to/your/exe/which/load/wrap.so 2>&1 | grep '/full/path/to/wrap.so'

如果您想了解一些上下文,请尝试在 grep(或任何更大的数字)中使用 -3

$ strace /path/to/your/exe/which/load/wrap.so 2>&1 | grep -3 '/full/path/to/wrap.so'

【讨论】:

  • 我创建了 wrap.so,我认为它与用户 ID 相关。
  • @user4016367 malat 询问的 2 个命令(fileldd)的输出是什么?
  • @nos 1 号:wrap.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped,2 号:linux-gate.so.1 => (0xffffe000) libdl.so.2 => /lib/libdl.so.2 (0xf7713000) libc.so.6 => /lib/libc.so.6 (0xf75a6000) /lib/ld-linux.so.2 (0xf7780000)
  • @user4016367 你为什么要标记c++,你的共享库没有使用libstdc++.so.6
【解决方案3】:

除了malat所说的,可能至少还有另外两个原因:

  1. 您的预加载库不可访问。如果您只能访问系统上的一个非 root 用户,则可能不是这种情况。
  2. 您在放置预加载库的文件系统上设置了noexec 标志。

要检查第一种情况,请以您尝试运行程序的用户身份登录并运行nm /path/to/preload/library.so——您必须将一些符号打印到控制台。

在第二种情况下,mmap 的手册页说明了可能的错误:

EPERM prot 参数要求 PROT_EXEC 但映射区域属于文件系统上的文件,该文件以非执行方式挂载。

要检查这一点,您可以将/bin/ls 复制到与预加载库相同的目录并尝试运行它。如果ls -l ./ls 显示x 标志,但尝试执行./ls 却显示Permission denied,那么您可能设置了noexec。当然,您可以检查mount 命令的输出是否存在noexec,但您可能需要考虑在某些Ubuntu 安装中嵌套安装的伪文件系统,例如~/Private。

【讨论】:

    猜你喜欢
    • 2021-07-25
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    相关资源
    最近更新 更多