2015-01-09 3 views
2

Я видел много вопросов о том, как получить путь к файлу из его inode, но почти никто не делает обратное. Моему модулю ядра необходимо сделать это, чтобы получить дополнительную информацию о предметах запросов, переданных в open(), например, о ее флагах файлов или о том, является ли это устройством. Из того, что я был в состоянии раздобыть вместе из списков рассылки, справочных страниц, а также исходного кода Linux, я пришел с этой маленькой функцией:Извлечение структуры inode с указанием пути к файлу

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

Есть ли лучший способ сделать это? Я почти уверен, что мой путь неправильный.

ответ

3

Вы можете использовать API ядра kern_path, чтобы получить информацию о inode из строки пути. Эта функция, в свою очередь, вызывает функцию do_path_lookup(), которая выполняет операцию поиска пути. Вы можете проверить результаты функции kern_path напечатав номер индексного дескриптора (i_ino поля структуры индексного дескриптора) из инода вы получаете от вашей get_inode_from_pathname функции и соответствия его с номером индексного дескриптора из ls команды (ls -i <path of the file>)

I сделал следующий модуль ядра, и это не сбой ядра. Я использую ядро ​​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"); 

Вы можете отправить трассировку стека аварии?

+0

Это то, что делает мой код в настоящее время, но это приводит к сбою моего модуля. – Melab

+0

Я добавил свой модуль, чтобы получить номер inode в своем ответе выше. –

+0

Я использую минимальную настройку на виртуальной машине, поэтому мне придется выяснить способ захвата трассировки стека аварий (что конкретно?). Я запускаю версию ядра 3.16.7, и это, вероятно, связано с тем, что это используется в захваченном системном вызове, но я увижу, что получаю. – Melab

1

Я думаю, автор уже исправил свою проблему, но этот вопрос был первой ссылкой в ​​результатах поиска Google, поэтому я объясню это дальше.

Проблема с кодом вопроса заключалась в использовании указателя __user. Когда вы подключаете функцию, которая имеет дело с указателями __user, первое, что вам нужно сделать, это скопировать содержимое в собственный буфер ядра, где вы будете иметь дело с ним, или убедитесь, что указатель не станет недействительным, когда вы имеете дело с ним.

Чтобы скопировать его в буфер можно использовать функцию 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 не будет разбиваться, потому что на самом деле он выделяет буфер для пути внутри ядра, поэтому он не может стать недействительным, пока модуль работает с ним.

+0

У меня нет доступа к исходному коду на данный момент, но я уверен, что это не проблема с '__user'. – Melab