Перехватывает системный вызов openat() для GNU tar
Я пытаюсь перехватить 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()
от intercept-openat.so
не вызывается. Это почему?
1 ответ
Он использует тот же системный вызов, но, очевидно, не вызывает его через ту же функцию C. В качестве альтернативы, это может быть так, но это статически связано.
В любом случае, я думаю, вы доказали, что он никогда не динамически связывает имена функций "openat". Если вы все еще хотите использовать эту опцию, вы можете посмотреть, ссылается ли она на конкретную версию этой функции, но это еще не все.
Вы все еще можете перехватить системный вызов, написав свою программу для использования ptrace
, Это тот же интерфейс, который используется strace и gdb. Это будет иметь более высокую производительность, хотя.