- 论坛徽章:
- 9
|
本帖最后由 Tinnal 于 2010-10-13 20:29 编辑
回复 7# ouyangyufu
回复 7# ouyangyufu
之前的问题给你找出来了。主要是因为proc文件系统的inode操作proc_pid_follow_link函数没有通过nd_set_link函数把连接文件的路径存在dentry里头,而只直接把dentry改为目标文件的dentry。因我们通过nd_get_link函数而没法获得对应的路径。真气死我了,内核代码规范的不统一真令人担忧,查得我快吐血了。还是redhat 9 好的,我的fedora里头连原码都没有。害得我又得把ARM实验板抱出来。proc_pid_follow_link的原码如下:- static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
- {
- struct inode *inode = dentry->d_inode;
- int error = -EACCES;
- /* We don't need a base pointer in the /proc filesystem */
- path_release(nd);
- /* Are we allowed to snoop on the tasks file descriptors? */
- if (!proc_fd_access_allowed(inode))
- goto out;
- error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);
- nd->last_type = LAST_BIND;
- out:
- return ERR_PTR(error);
- }
复制代码 气人的代码!
改写完以后的代码就可以读出fd的符号连接了,用的方法是得到目标文件后,用d_path命令重建目标文件的路径。- /*
- * Author:Tinnal <Tinnal.Feng@miartech.com>
- *
- *
- * The source code in this file can be freely used, adapted,
- * and redistributed in source or binary form, so long as an
- * acknowledgment appears in derived source files.No warranty
- * is attached;we cannot take responsibility for errors or
- * fitness for use.
- *
- * Modification:
- * Tinnal V1.00 2010-10-10 Create the file.
- */
-
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/init.h>
- #include <linux/kernel.h> /* printk() */
- #include <linux/fs.h> /* everything... */
- #include <linux/namei.h> /* path_lookup*/
- static char *path = NULL;
- module_param(path, charp, 0);
- #define BUFFER_SIZE (512)
- char path_buffer[BUFFER_SIZE];
- static int __init PathLookup_init(void)
- {
- struct nameidata nd;
- void *cookie;
- char *link_path = NULL;
- if(path == NULL)
- {
- printk("PathLookup: Used: insmod PathLookup path=\"<Link file name>\"\n");
- return -1;
- }
- printk("PathLookup: The link file you enter is: %s\n", path);
- if (path_lookup(path, 0, &nd)) {
- printk("PathLookup: path %s not found!\n", path);
- return -1;
- }
- printk("PathLookup: The real file is %s\n", nd.dentry->d_name.name);
- printk("PathLookup: The link file's dentry is: %p\n", nd.dentry);
- nd.depth = 0;
- cookie = nd.dentry->d_inode->i_op->follow_link(nd.dentry, &nd);
- if (!IS_ERR(cookie)) {
- #if 0
- printk("PathLookup: [followlink]:%s\n", nd_get_link(&nd));
- #else
- printk("PathLookup: Target denrty:%p\n", nd.dentry);
- link_path = d_path(nd.dentry, nd.mnt, path_buffer, BUFFER_SIZE);
- printk("PathLookup: [followlink]:%s\n", link_path);
- #endif
- if (nd.dentry->d_inode->i_op->put_link)
- nd.dentry->d_inode->i_op->put_link(nd.dentry, &nd, cookie);
- }
- path_release(&nd);
- return 0;
- }
- static void __exit PathLookup_exit(void)
- {
- }
- module_init(PathLookup_init);
- module_exit(PathLookup_exit);
- MODULE_AUTHOR("Tinnal <tinnal.feng@miartech.com>");
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_DESCRIPTION("V1.00");
复制代码 这种做法只针对proc这破文件系统。对普通LINK文件失败,因为对普通文件进行follow_link操作后,是不会改dentry本身的,也就是:它还是指向连接文件本身而不是目标。我们可以用新的程序对正常的link文件和/proc/XXX/fd下的连接文件进行测试。
正常的link文件输出:
insmod PathLookup.ko path="./link"
PathLookup: The link file you enter is: ./link
PathLookup: The real file is link
PathLookup: The link file's dentry is: c3fef098
PathLookup: Target denrty:c3fef098
PathLookup: [followlink]:/link
可以看到dentry 前后指针是一致的。
/proc/XXX/fd下文件输出:
insmod PathLookup.ko path="/proc/737/fd/0"
PathLookup: The link file you enter is: /proc/737/fd/0
PathLookup: The real file is 0
PathLookup: The link file's dentry is: c3e282c8
PathLookup: Target denrty:c3d544b8
PathLookup: [followlink]:/dev/ttyS0
可以看到dentry 前后指针是不一致的。
(以上结果是在开发板上运行的情况,PC一样)
可以看出,这个程序已经不适用于正常连接文件了。
为什么不直接用readlink函数?因为破函数直接在函数体内copy_to_uesr了,妈的!还是做应用好,一个readlink就搞定!
补充几句:自己多RTFSC。这东西很耗时间,帮不了你多少次。 |
|