我使用LD_PRELOAD
技巧来捕获open64()
调用,我想我知道如何正确地做到这一点:使用从
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
open64("foobar.txt", 0);
return 0;
}
字符串
我得到了open64
,正如我所期望的:
>LD_PRELOAD=$PWD/catch.so ./foobar
open64 called
型
但是,当open64
替换为fopen64
时:
#include <stdio.h>
int main() {
fopen64("foobar.txt", "r");
return 0;
}
型
现在open64
没有被捕获。为什么?
如果fopen64
调用open
,我确实拦截了open
和open64
,但没有捕获到。
两个版本的foobar
程序,当与strace
一起执行时,显示open
被调用,这意味着fopen64
确实在内部调用open
或open64
。
我想也许有些东西是静态链接的,但似乎不是这样:
>ldd foobar
型
示出
libc.so.6 => /lib64/libc.so.6
型
这是一个共享库,
>nm /lib64/libc.so.6
型
显示了open64
和fopen64
的定义(但不是fopen
,这就是为什么在问题中,我使用“64”版本作为参数;也许fopen
是fopen64
的宏或类似的东西,没有关系,因为问题发生在64或没有64的情况下)。
3条答案
按热度按时间pftdvrlh1#
我认为它是这样工作的:用户空间程序调用libc中的库函数,libc调用内核中的系统调用。使用LD_PRELOAD可以拦截程序和libc之间的libc调用。你不能拦截系统调用。如果glibc内部调用另一个函数(例如fopen调用open),你不能拦截它。
在这种情况下,最好使用
ltrace
而不是strace
,因为它显示了哪些库调用已经完成。这些是您可以拦截的调用。的数据
qzlgjiam2#
你需要
ptrace
和PTRACE_SYSCALL
,这是一个blog on it。rjzwgtxy3#
我最近遇到了一个类似的问题,我认为答案可以归结为glibc的实现。
以下是所有AFAICT从看glibc-2.37源代码,并不被视为福音。
fopen()和fopen 64()最终调用内部函数__open()(或者,不太可能,__open_nocancel())(可能使用O_LARGEFILE),而不是open()或open 64()。这些低级函数执行内联系统调用,而不是调用open()系统调用 Package 器(您使用LD_PRELOAD覆盖)。
你可能会说,“好吧,让我们用LD_PRELOAD覆盖__open(),然后到此为止”。这是可行的,除了glibc还用__attribute__标记__open()和__open_nocancel()。((visibility(“hidden”)。这会导致这些符号对LD_PRELOAD不可见,因此尽管您可以定义自己版本的__open(),对原始__open()的调用将不会被正确拦截。
我看了Bionic(Android libc)的源代码进行比较,虽然我认为你可以像你想的那样拦截open(),但我认为你会在fclose()端遇到问题(因为它最终调用_close(),这是隐藏的,而不是close())。