6

openat()経由でロードできるカスタム共有ライブラリを使用して、Linuxでシステム コールをインターセプトしようとしていLD_PRELOADます。例intercept-openat.cには次の内容があります。

#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()...\n");
        return _original_openat(dirfd, pathname, flags, mode);
}

経由でコンパイルしgcc -fPIC -Wall -shared -o intercept-openat.so intercept-openat.c -ldlます。次に、この小さなサンプル プログラムを実行すると、次のようになります。

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()ライブラリを介して書き直されます。

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

ただし、GNU tar では、同じシステム コールを使用していても、同じことは起こりません。

$ 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

そのため、カスタムopenat()fromintercept-openat.soは呼び出されていません。何故ですか?

4

1 に答える 1

2

同じシステム コールを使用していますが、明らかに同じ C 関数を介して呼び出しているわけではありません。または、そうかもしれませんが、静的にリンクされています。

いずれにせよ、関数名「openat」を動的にリンクすることは決してないことを証明したと思います。それでもこのオプションを追求したい場合は、その関数の特定のバージョンにリンクしているかどうかを確認したいかもしれませんが、それはロングショットです.

を使用するようにプログラムを作成することで、システム コールをインターセプトすることができますptrace。これは、strace と gdb で使用されるインターフェイスと同じです。ただし、パフォーマンスのペナルティが大きくなります。

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

于 2012-02-06T16:23:48.883 に答える