I am creating an ebpf program that has a tracepoint on the syscall read().
The purpose of the program is to count how many times a file is read.
My current method to trace this is as follows:
- When the tracepoint for read() hits, it has access to the file descriptor (fd) and process id (pid). My c callback code gets executed with this information.
- The code gets the inode from each file in /proc/{pid}/fd. If the inode matches the specific file(s) to monitor I increment the count. This all happens before the read() syscall finishes.
This works fine and dandy sometimes... However I noticed something odd...
- Smaller files (e.g. 2 lines total) don't typically get picked up this way, but larger files do.
For instance:
cat small.txt = Missed
cat big.txt = Seen
- If I add the strace command before the cat call it works
For instance:
strace -q cat small.txt = Seen
The ebpf code that handles this can be seen here:
void handle_event(void *ctx, void *data, unsigned int data_sz)
{
//struct that holds data like pid, and fd
struct data_t *m = data;
//get /proc/pid/fd as string
char path_str[100];
sprintf(path_str, "/proc/%d/fd", m->pid);
//for traversing the proc dir
DIR *mydir;
struct dirent *myfile;
struct stat mystat;
//traverse /proc/pid/fd
char buf[512];
mydir = opendir(path_str);
if(mydir != NULL){
while((myfile = readdir(mydir)) != NULL)
{
//stat each file
sprintf(buf, "%s/%s", path_str, myfile->d_name);
stat(buf, &mystat);
//check if inode matches from list
if(mystat.st_ino == 1396301 || mystat.st_ino == 1319264 || mystat.st_ino == 5768513 || mystat.st_ino == 1318781){
//alert message to signify file was read
printf("Read file!\n");
printf("inode = %d \n", mystat.st_ino);
}
}
}
//close the dir
if(mydir != NULL){
closedir(mydir);
}
}
What I noticed is that cat big.txt always has an fd in /proc/pid/fd for big.txt, as does strace -q small.txt for small.txt.
However for cat small.txt it never seems to have an fd.
I am presuming this has something to do with caching, but I can't seem to figure out how the file is being accessed in the case of cat small.txt, because even if it accesses the file through a cache wouldn't it also produce an fd, and update /proc/pid/fd?
If not, why not? And what mechanism would be used to access the file contents instead?
Any help would be much appreciated.