我已经看到很多关于从它的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;
}
尝试在我的替换系统调用中使用它会使内核消息打印到控制台,但是:
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);
}
有更好的方法吗?我几乎是肯定的,我的方式是错的。
答案 0 :(得分:6)
您可以使用kern_path
内核API从路径字符串中获取inode信息。该函数依次调用执行路径查找操作的do_path_lookup()
函数。您可以通过打印从kern_path
函数获得的inode的inode编号(inode结构的i_ino
字段)并将其与inode编号匹配来验证get_inode_from_pathname
函数的结果来自ls
命令(ls -i <path of the file>
)
我制作了以下内核模块,它没有崩溃内核。我正在使用2.6.39内核。
#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");
你能发送崩溃堆栈跟踪吗?
答案 1 :(得分:2)
我想作者已经解决了他的问题,但这个问题是谷歌搜索结果中的第一个链接,所以我会进一步解释。
问题代码的问题是使用__user指针。 当你挂钩一个处理__user指针的函数时,你要做的第一件事就是将内容复制到你自己的内核缓冲区,在那里你将处理它或确保指针在你处理它时不会变得无效。 / p>
要将其复制到缓冲区,您可以使用copy_from_user函数
char path[MAX_PATH] = {0};
if (copy_from_user(path, user_path, strlen_user(user_path))
{
//error
}
//success
如果你挂钩sys_open,你可以使用getname / putname函数,就像在do_sys_open函数中一样:
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_S的答案的代码不会崩溃,因为事实上它为内核中的路径分配了缓冲区,因此在模块使用它时它不会变为无效。