【问题标题】:Dynamically load library from chroot with glibc dependency使用 glibc 依赖从 chroot 动态加载库
【发布时间】:2018-08-12 04:17:50
【问题描述】:

我正在尝试从 chroot 中动态加载库。 上述库依赖于 glibc,其版本与我的主机不同(主机有 2.26,chroot 有 2.23)。

有没有办法做到这一点?

这是我尝试过的:

$ curl http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04-core-amd64.tar.gz | tar -C ubuntu -xz

#include <unistd.h>                                                                                                                                                                                                 
#include <dlfcn.h>

int main(int argc, char *argv[])
{
        chdir("ubuntu");
        chroot(".");

        // 1. This will fail
        dlopen("libpthread.so.0", RTLD_NOW);

        // 2. This will crash
        dlmopen(LM_ID_NEWLM, "libpthread.so.0", RTLD_NOW);

        return 0;
}
  1. 显然失败是因为 glibc 不匹配:

    /lib/x86_64-linux-gnu/libpthread.so.0: symbol __libc_dl_error_tsd, version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference
    
  2. valgrind 的以下输出导致崩溃:

    ==19923== Process terminating with default action of signal 4 (SIGILL): dumping core
    ==19923==  Illegal opcode at address 0x401D41C
    ==19923==    at 0x401D41C: ??? (in /usr/lib/ld-2.26.so)
    ==19923==    by 0x4013932: dl_open_worker (in /usr/lib/ld-2.26.so)
    ==19923==    by 0x516EB63: _dl_catch_error (in /usr/lib/libc-2.26.so)
    ==19923==    by 0x4013279: _dl_open (in /usr/lib/ld-2.26.so)
    ==19923==    by 0x4E3A8CF: ??? (in /usr/lib/libdl-2.26.so)
    ==19923==    by 0x516EB63: _dl_catch_error (in /usr/lib/libc-2.26.so)
    ==19923==    by 0x4E3A586: ??? (in /usr/lib/libdl-2.26.so)
    ==19923==    by 0x4E3A9B6: dlmopen (in /usr/lib/libdl-2.26.so)
    

【问题讨论】:

  • 你为什么要dlopen()ing libpthread?而且我认为没有办法,但我几乎可以肯定你有一个X Y Problem,所以请解释一下你的真正目标是什么。
  • 您的可执行文件需要您的环境没有的库版本。尝试按原样运行它没有什么意义。此外,dlopen'ing libpthread 并在一开始就没有使用 -pthread 构建的程序中使用它并不是最好的主意,而且无论 glibc 的版本如何,都很有可能使您的程序崩溃。
  • 如果有帮助,请将其视为您希望加载的插件包,并且可能具有冲突的依赖项。libpthread 只是为了示例,它确实与任何库都失败。至于环境,chroot下所有的需求和依赖都满足了,问题是如何安全的把它们带入进程的地址空间。

标签: c ld glibc dynamic-loading


【解决方案1】:

您正试图将 两个 不同版本的 GLIBC 合并到一个进程中。

这不起作用的原因解释here

您需要知道 glibc 由许多必须匹配的部分(200 多个共享库)组成。其中之一是ld-linux.so.2,它必须与libc.so.6 匹配,否则您将看到您所看到的错误。

在您的情况下,不匹配介于 /usr/lib/ld-2.26.so(从 ld-linux-x86-64.so.2 符号链接并在您的程序执行自己的单个指令之前由内核加载到进程中)和 ubuntu/libpthread.so.0 之间。

如果您完全将您的测试程序与gcc -static ... 静态链接,它可能会起作用。但这不是 GLIBC 开发人员测试或支持的操作模式,并且不太可能适用于任何重要的程序。

要解决此问题,您需要重新execve chroot 中的程序。如果您无法将二进制文件复制到您的 chroot 中,您可以使用 fexecve 或使用 /proc/self/exe 来摆脱这种困难(这两者似乎都需要将 /proc 安装在 chroot 中)。

附言

上述库依赖于glibc,它的版本与我的主机不同(主机有2.26,chroot有2.23)。

由于 libc 向后兼容性,任何链接到 GLIBC-2.23 的库都应该继续正常工作针对 GLIBC-2.26。

所以也许你一开始就没有要解决的问题?

【讨论】:

  • 虽然我同意你所说的,但dlmopen 不应该能够处理吗? LD_DEBUG 表明 ld-linux-x86-64.so.2libc.so.6 正在从 chroot 中拉出,直到发生崩溃。如果我尝试dlmopen("ld-linux-x86-64.so.") 它可以工作,但它本身并没有真正有用。我确实可以依赖 glibc ABI,但我必须 chroot,使用 RTLD_NOLOAD/dlinfo uncroot 找到库路径,然后找到完整路径 dlopen。对于此示例,它可以工作,但如果解决可能存在其他依赖项冲突的一般用例会很好。
  • @3XX0 “dlmopen 不应该能够处理吗?” -- 不是真的:在这个过程中只能有一个ld-linux
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-07
  • 1970-01-01
  • 2020-06-12
  • 2015-12-13
  • 1970-01-01
相关资源
最近更新 更多