I am trying to intercept the openat() system call on Linux using a special shared library that I can load through LD_PRELOAD . The intercept-openat.c has this content:
#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); }
I will compile it through gcc -fPIC -Wall -shared -o intercept-openat.so intercept-openat.c -ldl . Then, when I run this small sample program:
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; }
The openat() call is rewritten through the library:
$ LD_PRELOAD=./intercept-openat.so ./openat intercepting openat()...
However, the same does not happen with GNU tar, although it uses the same system call:
$ 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
This way the custom openat() from intercept-openat.so not called. Why is this?