I would like to override getdirentries (and others, like lstat) libc syscalls. I can override -for example- lstat and chmod, but I can't override getdirentries (and amongst others fstatfs).
Example code is:
#include <errno.h>
#include <dlfcn.h>
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <sys/_timespec.h>
#include <sys/stat.h>
#include <sys/mount.h>
#ifndef RTLD_NEXT
#define RTLD_NEXT ((void *) -1l)
#endif
int (*getdirentries_orig)(int fd, char *buf, int nbytes, long *basep);
int (*lstat_orig)(const char *path, struct stat *sb);
int (*fstatfs_orig)(int fd, struct statfs *buf);
int (*chmod_orig)(const char *path, mode_t mode);
#define HOOK(func) func##_##orig = dlsym(RTLD_NEXT,#func)
int getdirentries(int fd, char *buf, int nbytes, long *basep) {
HOOK(getdirentries);
printf("getdirentries\n");
return getdirentries_orig(fd, buf, nbytes, basep);
}
int lstat(const char *path, struct stat *sb) {
HOOK(lstat);
printf("lstat\n");
return (lstat_orig(path, sb));
}
int fstatfs(int fd, struct statfs *buf) {
HOOK(fstatfs);
printf("fstatfs\n");
return fstatfs_orig(fd, buf);
}
int chmod(const char *path, mode_t mode) {
HOOK(chmod);
printf("chmod\n");
return chmod_orig(path, mode);
}
I compile this on FreeBSD with:
cc -Wall -g -O2 -fPIC -shared -o preload.so preload.c
(on Linux, adding -ldl may be needed) and use it with LD_PRELOAD=./preload.so bash.
If I then issue an ls -l, I get "lstat" printed multiple times, that's good. But ls calls multiple getdirentries too, according to ktrace, and its override function does not get called. fstatfs also doesn't work.
How can I override getdirentries, fstatfs and possibly other syscalls, and why they aren't working in this case?
Thanks,
As it turns out, readdir() in libc/readdir.c (readdir is what ls calls and that should call getdirentries) calls _getdirentries, not getdirentries. If I override _getdirentries, it works. The same for fstatfs, so this is why my program did not work.