GNU tarのopenat()システムコールをインターセプトする

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

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 

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

したがって、 intercept-openat.so のカスタム openat()が呼び出されていません。何故ですか?

4

1 答え

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

いずれにしても、関数名 "openat"を動的に決してリンクしていないことを証明したと思います。それでもなおこのオプションを追求したいのであれば、その関数の特定のバージョンとリンクしているかどうかを確認したいかもしれませんが、それは長いことです。

ptrace を使用するようにプログラムを書くことによって、システムコールを傍受することはできます。これはstraceとgdbで使用されるのと同じインタフェースです。それはしかし、より高いパフォーマンスのペナルティを持っています。

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

2
追加された
正しい方向に私を指してくれてありがとう。 tar は、ライブラリ関数 openat()を決して呼び出すことはありません。代わりに、 __ openat_2()を使用します。したがって、上記のコードは、この行を追加すると、サンプルプログラムとGNU tarの両方で動作します: int __openat_2(int dirfd、const char * pathname、int flags、mode_t mode)__attribute __((別名( "openat")) ); openat openat のエイリアスであるような
追加された 著者 Julius Plenz,
また、ジョブを実行するための適切なツールは、(ライブラリ呼び出しトレースのように) ltrace のようです。
追加された 著者 Julius Plenz,