2015-01-09 55 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

您可以使用kern_path內核API從路徑字符串中獲取inode信息。該函數依次調用執行路徑查找操作的函數do_path_lookup()。您可以通過打印您從get_inode_from_pathname功能得到inode的inode編號(inode的結構i_ino場)和從ls命令索引節點號匹配它(ls -i <path of the file>

我驗證kern_path函數的結果製作了以下內核模塊,並且不會崩潰內核。我正在使用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 2015-01-12 16:31:33

+0

我已經添加了我的模塊以獲取上面我的回覆中的inode編號。 – 2015-01-13 07:10:58

+0

我在虛擬機中使用了一個最小化的設置,所以我必須找出一些方法來捕獲崩潰堆棧跟蹤(具體是什麼?)。我正在運行內核版本3.16.7,這可能是由於這被用於被劫持的系統調用中,但我會看到我得到的。 – Melab 2015-01-13 17:28:17

1

我想作者已經解決了他的問題,但這個問題是谷歌搜索結果中的第一個鏈接,所以我會進一步解釋它。

問題代碼的問題是使用__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 2016-07-25 17:22:05