C语言 使用LD_PRELOAD拦截stat调用

jjhzyzn0  于 2023-01-25  发布在  其他
关注(0)|答案(1)|浏览(185)

我正在尝试编写一个共享对象来拦截来自应用程序的一些文件系统API调用,如open、close、read、write等。拦截是使用LD_PRELOAD完成的。我已经系统地使用strace来找出应用程序调用的API,并在LD_PRELOAD加载的共享库中实现它们。当涉及到stat时,我发现调用了__xstat和__xstat64而不是stat,我重写了这两个函数。我可以捕获这些API调用。但是,在一个特定的环境中,当我使用strace时,我看到直接调用stat()本身。如下所示

25083 03:11:28.424859 close(13)         = 0 <0.000045>
>> 25083 03:11:28.424966 stat("/somedir/somefile", 0x7ffe751d2430) = -1 ENOENT (No such file or directory) <0.000050>
25083 03:11:28.425067 clock_gettime(CLOCK_MONOTONIC, {786855, 130369007}) = 0 <0.000029>

我注意到的不同之处在于,stat是直接调用的,这在其他环境中是看不到的。应用程序可能调用stat(),但我看到stat内部调用__xstat或__xstat64。我注意到的另一件事是,stat()甚至没有在www.example.com库中实现libc.so。因此,此stat()看起来是stat()系统调用的直接调用。我如何确认这一点?应用程序如何直接调用stat()系统调用?

2vuwiymt

2vuwiymt1#

所以这个stat()看起来是stat()系统调用的直接调用,我该如何确认呢?
使用catch syscall statgdb中运行程序。当系统调用发生时,使用bt检查调用堆栈,并注意是否在libc.so中。
应用程序如何直接调用stat()系统调用?
使用内联汇编。下面是x86-64的一个例子:

#include <stdio.h>
#include <sys/stat.h>
#include <sys/syscall.h>

int main(int argc, char **argv) {
    if(argc < 2) return 1;
    struct stat s;
    long rv;
    __asm__ volatile(
        "syscall"
        : "=a"(rv)
        : "a"(SYS_stat), "D"(argv[1]), "S"(&s)
        : "rcx", "r11", "memory"
    );
    if(rv) return 1;
    printf("%zu\n", s.st_size);
}

相关问题