强制ELF二进制文件使用另一个libc.so

3
我需要制作ELF二进制文件以便于科学目的使用另一个版本的libc.so。我尝试使用LD_PRELOADpatchelf工具来实现,但是二进制文件运行时出现错误,例如:./a.out: error while loading shared libraries: libc-2.15.so: cannot open shared object file: No such file or directorySegmentation fault (core dumped)。我认为这是因为我需要另一个版本的ld.so
最有效的方法是什么,可以使二进制文件使用我所需的libc版本? 编辑:我没有二进制文件的源代码。 编辑:错误消息已编辑。没有SELinux,没有AppArmor。

1
如果你真的替换了系统范围内的libc,那么如果新的libc破坏了你系统上的某些程序,你可以期望这是你在系统上做的最后一件事情...祝你好运 :-) - Klaus
1
你尝试设置LD_LIBRARY_PATH环境变量了吗?你能重新编译那个二进制文件的源代码吗?考虑编辑你的问题以改进它。 - Basile Starynkevitch
手头的代码是基于哪个具体版本构建的?你现在想要运行它的是哪个具体版本? - Charles Duffy
此外,你为什么觉得你需要一个不同的 ld.so 呢?许多情况下,你无法使用相同的动态加载器,这也意味着你的 libc 差异足够大(例如架构或 ABI),因此你不能在不重新编译的情况下进行替换。 - Charles Duffy
...还有,希望你的LD_PRELOAD给出了一个完全限定的路径...对吧?如果没有,请修复它并重试。 - Charles Duffy
显示剩余2条评论
2个回答

3

在我看来,你好像没有完整地升级到新的libc变体。

我做了以下操作:

ldd example

linux-vdso.so.1 (0x00007ffe9c087000)
libstdc++.so.6 => /opt/linux-gnu_6.1.0/lib64/libstdc++.so.6 (0x00007f0cef872000)
libm.so.6 => /lib64/libm.so.6 (0x00007f0cef56f000)
libgcc_s.so.1 => /opt/linux-gnu_6.1.0/lib64/libgcc_s.so.1 (0x00007f0cef359000)
libc.so.6 => /lib64/libc.so.6 (0x00007f0ceef98000)
/lib64/ld-linux-x86-64.so.2 (0x000055ca3cb92000)

LD_PRELOAD=/tmp/bug_libc.so ldd example

linux-vdso.so.1 (0x00007ffc2cff8000)
/tmp/bug_libc.so (0x00007f56a1358000)
libstdc++.so.6 => /opt/linux-gnu_6.1.0/lib64/libstdc++.so.6 (0x00007f56a0f9a000)
libm.so.6 => /lib64/libm.so.6 (0x00007f56a0c98000)
libgcc_s.so.1 => /opt/linux-gnu_6.1.0/lib64/libgcc_s.so.1 (0x00007f56a0a82000)
/lib64/ld-linux-x86-64.so.2 (0x00005605c8a7a000)

如果我替换为一个无效的libc,那么我会收到不同的错误信息。只有当我提供了错误的路径时才会出现这种情况,例如:
LD_PRELOAD=/tmp/bug_libc.so2 ldd go

ERROR: ld.so: object '/tmp/bug_libc.so2' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object '/tmp/bug_libc.so2' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
linux-vdso.so.1 (0x00007ffedcde4000)
libstdc++.so.6 => /opt/linux-gnu_6.1.0/lib64/libstdc++.so.6 (0x00007f3ae2188000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3ae1e85000)
libgcc_s.so.1 => /opt/linux-gnu_6.1.0/lib64/libgcc_s.so.1 (0x00007f3ae1c6f000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3ae18ae000)
/lib64/ld-linux-x86-64.so.2 (0x000055df54aae000)

也许您在访问替换的libc文件时遇到了其他问题。请检查文件的访问标志,还要检查SELinux或AppArmor或其他保护是否阻止在您的环境中加载libc。因为替换libc会打开一个安全漏洞,所以它是SELinux和其他保护机制的候选者!
同时,您应该始终先使用“ldd”进行检查。也许您的新libc需要一些更多(旧版本)的其他库变体,这些库在您的系统上找不到。通常libc不需要其他库,但我不知道您正在玩什么游戏。无论如何,“ldd”都可以更详细地回答库加载阶段发生的事情。
编辑:段错误
如果您收到段错误,则通常是使用不兼容的头文件编译应用程序。您必须使用与您想要使用的libc版本一起提供的头文件进行编译。如果使用系统头文件为系统libc编译并运行任何不兼容的预编译libc版本,那么访问错误的数据结构将导致任何类型的内存错误。

如果你遇到了段错误,通常是因为你使用了不兼容的头文件编译了应用程序。但是你错了。当使用非默认的libc.so.6时,导致段错误最常见的原因是它与ld-linux.so之间存在不匹配。https://dev59.com/VHRA5IYBdhLWcg3wvQhh#851229 - Employed Russian

2

这个答案解释了为什么LD_PRELOAD无法工作,并提出了解决方案。

我尝试使用LD_PRELOAD和patchelf实用程序来实现它。

不清楚您对patchelf的使用是否只涉及DT_RPATH、只涉及PT_INTERP还是两者都有。您需要同时进行这两种操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接