Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving inode struct given the path to a file

Tags:

linux-kernel

I've seen lots of questions about getting a file's path from it's inode, but almost none about doing the reverse. My kernel module needs to do this to get further information about the subjects of requests passed to open(), such as its file flags or whether or not it's a device. From what I was able to scrounge together from mailing lists, manual pages, and the Linux source code, I came up with this small function:

struct inode* get_inode_from_pathname(const char *pathname) {
    struct path path;
    kern_path(pathname, LOOKUP_FOLLOW, &path);
    return path.dentry->d_inode;
}

Trying to use it in my replacement system call makes kernel messages get printed to the console, though:

struct inode *current_inode;
...
asmlinkage int custom_open(char const *__user file_name, int flags, int mode) {
    current_inode = get_inode_from_pathname(file_name);
    printk(KERN_INFO "intercepted: open(\"%s\", %X, %X)\n", file_name, flags, mode);
    printk(KERN_INFO "i_mode of %s:%hu\n", file_name, current_inode->i_mode);
    return real_open(file_name, flags, mode);
}

Is there a better way to do this? I'm almost positive my way is wrong.

like image 210
Melab Avatar asked Jan 09 '15 21:01

Melab


1 Answers

You can use the kern_path kernel API to get the inode information from the path string. This function in turn calls the do_path_lookup() function which performs the path look up operation. You can verify the results of the kern_path function by printing the inode number (i_ino field of the inode structure) of the inode you get from your get_inode_from_pathname function and matching it with the inode number from an ls command (ls -i <path of the file>)

I made the following kernel module and it's not crashing the kernel. I am using 2.6.39 kernel.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h> 
#include <linux/mount.h>
#include <linux/path.h>
#include <linux/namei.h>
#include <linux/fs.h>
#include <linux/namei.h>

char *path_name = "/home/shubham/test_prgs/temp.c";

int myinit(void)
{
    struct inode *inode;
    struct path path;
    kern_path(path_name, LOOKUP_FOLLOW, &path);
    inode = path.dentry->d_inode;
    printk("Path name : %s, inode :%lu\n", path_name, inode->i_ino);
    return 0;
}


void myexit(void)
{
    return;
}

module_init(myinit); 
module_exit(myexit);

//MODULE_AUTHOR("Shubham");
//MODULE_DESCRIPTION("Module to get inode from path");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");

Can you send the crash stack trace?

like image 56
S_S Avatar answered Nov 17 '22 03:11

S_S