Skip to content

Instantly share code, notes, and snippets.

@larytet
Last active December 10, 2021 02:39
Show Gist options
  • Save larytet/f870e2ca5607876e24b529705e9cdb1b to your computer and use it in GitHub Desktop.
Save larytet/f870e2ca5607876e24b529705e9cdb1b to your computer and use it in GitHub Desktop.
Get inode and file given FD in the Linux kernel
static void get_inode(u64 fd, struct file **p_file, struct inode **p_inode)
{
struct file *file = NULL;
struct inode *f_inode = NULL;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,7,0))
file = fget_raw(fd); // do not forget to fput(file)
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,255))
{
struct files_struct *files = current->files;
if (files) // This is always the case, but I am not taking chances
{
int lock_result = spin_trylock(&files->file_lock); // Can I run lockless? What files_fdtable() does?
if (lock_result)
{
struct fdtable *fdt;
fdt = files_fdtable(files); // fdt is never NULL
if (fdt)
{
if (fd < fdt->max_fds) // This can not be wrong in syscall open
{
file = fdt->fd[fd];
}
}
spin_unlock(&files->file_lock); // This is a bug - I continue to use 'file' after giving up the lock
}
}
}
#else
#error Driver lacks support of the kernel in get_inode(). The agent will have to use stat() to get the file creation time of a file.
#endif
if (file)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
f_inode = file->f_inode;
#else
f_inode = file->f_path.dentry->d_inode;
#endif
}
else
{
DEBUG_COUNTERS_BUMP(DEBUG_SYSCALL_OPEN_CREATED_ERR1);
}
*p_inode = f_inode;
*p_file = file;
return ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment