我用来LD_PRELOAD
覆盖该read
函数。对于最小的测试应用程序,它工作得很好,但如果我用更大的应用程序测试它,它就不再工作了。也LD_DEBUG=all
根本不显示任何内容:
LD_DEBUG=all LD_PRELOAD=./lib.so ./big_app
这只是运行./big_app
并LD_PRELOAD
没有任何效果。有办法调试吗?
答案1
这个答案仅对 GNU/Linux 环境有效。
从评论来看,OP 的二进制文件添加了特权功能:功能。这切换ld.so(8)
成安全执行模式哪个默认情况下禁用大多数动态链接器相关的环境变量,包括LD_PRELOAD
和LD_DEBUG
。
出于安全原因,如果动态链接器确定应在以下位置运行二进制文件:安全执行模式,部分环境变量的影响被作废或修改[...]
如果 [...] 包含以下内容,则二进制文件将以安全执行模式执行:
进程真实有效的用户ID不同,或者真实有效的组ID不同。 [...]
具有非 root 用户 ID 的进程执行了赋予功能的二进制文件到这个过程。
[...]
然而,随着根访问系统,可以对其进行配置以满足以下先决条件安全执行模式对于以非 root 身份运行时的这两个参数,仍然如中所述ld.so(8)
:
[...]
在安全执行模式下,包含斜杠的预加载路径名将被忽略。此外,共享对象仅从标准搜索目录预加载和仅当它们启用了设置用户 ID 模式位时(这不是典型情况)。
标准搜索目录是什么?它们提供了 的输出ld.so --help
。例如在 Debian amd64/x86_64 上:
$ ld.so --help
[...]
Shared library search path:
(libraries located via /etc/ld.so.cache)
/lib/x86_64-linux-gnu (system search path)
/usr/lib/x86_64-linux-gnu (system search path)
/lib (system search path)
/usr/lib (system search path)
[...]
最后,共享对象文件必须位于这些位置之一。从测试来看:
- 不必由 root 拥有,只要它
u+s
设置了模式即可。 - 可以是指向
u+s
任何位置的实际文件的符号链接,只要符号链接位于正确的位置即可。 - 中不应存在任何路径
LD_PRELOAD
,仅应存在(一个)文件名,而不应存在/
任何位置。 - 如果二进制文件的功能未授予其读取文件的任意访问权限,则共享对象可以设置其模式,以便仅允许单个用户或组(通常
chmod o-rwx
应应用并设置正确的所有权,然后u+s
恢复)。对于 setuid-root 或CAP_DAC_OVERRIDE
/CAP_DAC_READ_SEARCH
这可能不会阻止任何执行此类特权二进制文件的用户使用该库。
[...]自 glibc 2.3.4 起,
LD_DEBUG
在安全执行模式下被忽略,除非文件/etc/suid-debug
存在(文件内容无关)。
我没有找到一种方法将其限制为仅适用于用户或组。
示例(使用 root 访问sudo
):
$ sudo touch /etc/suid-debug
$ sudo cp -aiL ./lib.so /usr/lib/lib.so
$ sudo chmod u+s /usr/lib/lib.so
现在允许以普通用户身份运行,并考虑两个变量:
LD_DEBUG=all LD_PRELOAD=lib.so ./big_app
答案2
您应该检查您的可执行文件是否是静态构建的。如果是,LD 环境变量将不会产生任何影响。
您可以使用 来检查这一点ldd
,这是一个向您显示共享对象依赖关系的实用程序。
如果您的可执行文件是静态的,它应该打印如下内容:
ldd ./big_app
not a dynamic executable