Linux kernel 检索给定文件路径的inode结构

Linux kernel 检索给定文件路径的inode结构,linux-kernel,Linux Kernel,我见过很多关于从inode获取文件路径的问题,但几乎没有一个是关于反向操作的。我的内核模块需要这样做,以获得有关传递到open()的请求主题的进一步信息,例如它的文件标志或它是否是设备。根据我从邮件列表、手册页面和Linux源代码中搜集到的信息,我想出了这个小功能: struct inode* get_inode_from_pathname(const char *pathname) { struct path path; kern_path(pathname, LOOKUP_F

我见过很多关于从inode获取文件路径的问题,但几乎没有一个是关于反向操作的。我的内核模块需要这样做,以获得有关传递到
open()
的请求主题的进一步信息,例如它的文件标志或它是否是设备。根据我从邮件列表、手册页面和Linux源代码中搜集到的信息,我想出了这个小功能:

struct inode* get_inode_from_pathname(const char *pathname) {
    struct path path;
    kern_path(pathname, LOOKUP_FOLLOW, &path);
    return path.dentry->d_inode;
}
1010 long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
1011 {
1012         struct open_flags op;
1013         int fd = build_open_flags(flags, mode, &op);
1014         struct filename *tmp;
1015 
1016         if (fd)
1017                 return fd;
1018 
1019         tmp = getname(filename);
1020         if (IS_ERR(tmp))
1021                 return PTR_ERR(tmp);
1022 
1023         fd = get_unused_fd_flags(flags);
1024         if (fd >= 0) {
1025                 struct file *f = do_filp_open(dfd, tmp, &op);
1026                 if (IS_ERR(f)) {
1027                         put_unused_fd(fd);
1028                         fd = PTR_ERR(f);
1029                 } else {
1030                         fsnotify_open(f);
1031                         fd_install(fd, f);
1032                 }
1033         }
1034         putname(tmp);
1035         return fd;
1036 }
尝试在替换系统调用中使用它会使内核消息打印到控制台,不过:

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);
}

有更好的方法吗?我几乎可以肯定我的方法是错误的。

您可以使用
kern\u路径
kernel API从路径字符串获取inode信息。此函数依次调用执行路径查找操作的
do\u path\u lookup()
函数。通过打印从
get\u inode\u from\u pathname
函数获得的inode的inode编号(
i\u ino
inode结构字段),并将其与
ls
命令(
ls-i
)中的inode编号匹配,可以验证
kern\u path
函数的结果

我制作了以下内核模块,它不会使内核崩溃。我使用的是2.6.39内核

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
char*path_name=“/home/shubham/test_prgs/temp.c”;
int myinit(void)
{
结构inode*inode;
结构路径;
内核路径(路径名称、查找路径和路径);
inode=path.dentry->d_inode;
printk(“路径名:%s,索引节点:%lu\n”,路径名,索引节点->索引节点);
返回0;
}
void myexit(void)
{
返回;
}
模块_init(myinit);
模块_退出(myexit);
//模块作者(“Shubham”);
//模块描述(“从路径获取inode的模块”);
模块许可证(“GPL”);
模块许可证(“GPL v2”);

你能发送崩溃堆栈跟踪吗?

我想作者已经解决了他的问题,但是这个问题是谷歌搜索结果中的第一个链接,所以我会进一步解释

问题代码的问题在于使用了_用户指针。 当你钩住一个处理_用户指针的函数时,你必须做的第一件事就是将内容复制到你自己的内核缓冲区,在那里你将处理它,或者确保指针在处理它时不会失效

要将其复制到缓冲区,可以使用copy_from_user函数

char path[MAX_PATH] = {0};

if (copy_from_user(path, user_path, strlen_user(user_path))
{
  //error
}
//success
如果钩住sys\u open,可以使用getname/putname函数,就像在do\u sys\u open函数中所做的那样:

struct inode* get_inode_from_pathname(const char *pathname) {
    struct path path;
    kern_path(pathname, LOOKUP_FOLLOW, &path);
    return path.dentry->d_inode;
}
1010 long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
1011 {
1012         struct open_flags op;
1013         int fd = build_open_flags(flags, mode, &op);
1014         struct filename *tmp;
1015 
1016         if (fd)
1017                 return fd;
1018 
1019         tmp = getname(filename);
1020         if (IS_ERR(tmp))
1021                 return PTR_ERR(tmp);
1022 
1023         fd = get_unused_fd_flags(flags);
1024         if (fd >= 0) {
1025                 struct file *f = do_filp_open(dfd, tmp, &op);
1026                 if (IS_ERR(f)) {
1027                         put_unused_fd(fd);
1028                         fd = PTR_ERR(f);
1029                 } else {
1030                         fsnotify_open(f);
1031                         fd_install(fd, f);
1032                 }
1033         }
1034         putname(tmp);
1035         return fd;
1036 }

ps:S_的答案中的代码不会崩溃,因为事实上它为内核内的路径分配了缓冲区,所以当模块使用它时,它不会变得无效。

这就是我的代码目前所做的,但这会导致我的模块崩溃。我在上面的回复中添加了我的模块以获取inode编号。我在虚拟机中使用最小设置,因此我必须找出一些方法来捕获崩溃堆栈跟踪(具体是什么?)。我正在运行内核版本3.16.7,这可能是因为它被用于一个被劫持的系统调用,但我会看看我得到了什么。我也在3.16.3内核上尝试了我的模块,但没有得到任何崩溃。当你说你的模块崩溃时,到底发生了什么?我现在没有访问我的源代码的权限,但我确信这不是
\uuu user
的问题。很抱歉,但是
从路径名获取inode\u函数创建本地结构
路径
,然后返回其成员并在
自定义打开
中使用该数据。当您使用
current\u inode->i\u mode
访问时,这些信息不是从堆栈中清除了吗?@FredrickGauss我不知道。请注意,在使用inode之后,您需要调用
path\u put()
(这使得您的助手函数几乎无法使用)。