关于gcc:拦截对GNU tar的openat()系统调用

intercepting the openat() system call for GNU tar

我正在尝试使用可通过LD_PRELOAD加载的自定义共享库在Linux上拦截openat()系统调用。示例intercept-openat.c具有以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <dlfcn.h>

int (*_original_openat)(int dirfd, const char *pathname, int flags, mode_t mode);

void init(void) __attribute__((constructor));
int openat(int dirfd, const char *pathname, int flags, mode_t mode);

void init(void)
{
        _original_openat = (int (*)(int, const char *, int, mode_t))
                dlsym(RTLD_NEXT,"openat");
}

int openat(int dirfd, const char *pathname, int flags, mode_t mode)
{
        fprintf(stderr,"intercepting openat()...\
");
        return _original_openat(dirfd, pathname, flags, mode);
}

我通过gcc -fPIC -Wall -shared -o intercept-openat.so intercept-openat.c -ldl进行编译。然后,当我运行这个小示例程序时:

1
2
3
4
5
6
7
8
9
int main(int argc, char *argv[])
{
    int fd;
    fd = openat(AT_FDCWD,"/home/feh/.vimrc", O_RDONLY);
    if(fd == -1)
        return -1;
    close(fd);
    return 0;
}

openat()调用通过库重新编写:

1
2
$ LD_PRELOAD=./intercept-openat.so ./openat
intercepting openat()...

但是,即使GNU tar使用相同的系统调用,也不会发生同样的事情:

1
2
3
$ strace -e openat tar cf /tmp/t.tgz .vimrc  
openat(AT_FDCWD,".vimrc", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC) = 4
$ LD_PRELOAD=./intercept-openat.so tar cf /tmp/t.tgz .vimrc

因此未调用intercept-openat.so中的自定义openat()。为什么会这样?


它使用相同的系统调用,但显然不会通过相同的C函数进行调用。另外,也可能是这样,但是它是静态链接的。

无论哪种方式,我认为您都证明了它从来没有动态链接过一个名为" openat"的函数。如果您仍然想使用此选项,则可能希望查看它是否与该函数的特定版本相关联,但这是一个漫长的尝试。

您仍然可以通过编写程序以使用ptrace来拦截系统调用。这是strace和gdb使用的相同接口。但是,它会带来更高的性能损失。

http://linux.die.net/man/2/ptrace