免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4874 | 回复: 18
打印 上一主题 下一主题

VFS层拦截read/write file_operations函数无效 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-02-07 18:10 |只看该作者 |倒序浏览
改变read,write,readdir,open,release等函数指针,发现readdir可以正常获得目录名,open,release只能截获目录的操作, read,write完全截获不了任何操作。 请问各位大虾有遇到类似问题吗。现在感觉上是对目录的操作都能截获,但是对文件操作的就完全没有。
readdir(工作正常) 和 read 代码如下
int my_readdir(struct file *fp, void *buf, filldir_t filldir)
{
        char *path = (char*)kmalloc(MAX_DIR_LENTH);
        unsigned int offset = MAX_DIR_LENTH-1;
        struct dentry* cwd = fp->f_dentry;
        int rs;
        path[MAX_DIR_LENTH-1] = '\0';
        // path add one slash in the end
        path[--offset] = '/';
        while( cwd->d_parent != cwd ) {
                offset -= cwd->d_name.len;
                strncpy(path + offset, cwd->d_name.name, cwd->d_name.len);
                path[--offset] = '/';
                cwd = cwd->d_parent;
        }
        if (offset == MAX_DIR_LENTH-1) path[--offset] = '/';
        printk("<1> Read Dir %s\n", path+offset);
        kfree(path);
        if (orig_readdir == NULL) {
                printk("<1> orig read dir function is NULL\n");
                return -1;
        }
        rs = orig_readdir(fp, buf, filldir);
        return rs;
}

ssize_t my_read (struct file *fp, char *buf, size_t len, loff_t *off)
{
        int rs;
        printk("<1> enter my read \n");   //这也没有输出
        char *path = (char*)kmalloc(MAX_DIR_LENTH);
        unsigned int offset = MAX_DIR_LENTH-1;
        struct dentry* cwd = fp->f_dentry;
        path[MAX_DIR_LENTH-1] = '\0';
        while( cwd->d_parent != cwd ) {
                offset -= cwd->d_name.len;
                strncpy(path + offset, cwd->d_name.name, cwd->d_name.len);
                path[--offset] = '/';
                cwd = cwd->d_parent;
        }
        printk("<1> Read file %s\n", path+offset);
        kfree(path);
        if (orig_read == NULL) {
                printk("<1> orig read function is NULL\n");
                return -1;
        }
        rs = orig_read(fp, buf, len, off);
        return rs;
}

挂载方式一样都是保存原来函数指针,用新函数指针代替
请个位兄弟指教

论坛徽章:
0
2 [报告]
发表于 2006-02-07 18:27 |只看该作者
截获方式? 最好贴一下代码

论坛徽章:
0
3 [报告]
发表于 2006-02-08 09:29 |只看该作者
谢谢albcamus 斑竹的关注。
替换file_operations,打开一个文件(我打开的是/),得到该fs的file_operations指针,替换。
下面是代码。
int patch_vfs(const char* p)
{
        struct file* filep;
        filep = filp_open(p, O_RDONLY, 0);
        if (IS_ERR(filep)){
                printk("<1> can not open file\n");
                return -1;
        }
        orig_read = filep->f_op->read;
        orig_write = filep->f_op->write;
        orig_readdir = filep->f_op->readdir;
        orig_ioctl = filep->f_op->ioctl;
        orig_open = filep->f_op->open;
        orig_lock = filep->f_op->lock;
        orig_mmap = filep->f_op->mmap;
        orig_release = filep->f_op->release;

        filep->f_op->read = my_read;
        filep->f_op->write = my_write;
        filep->f_op->readdir = my_readdir;
        filep->f_op->ioctl = my_ioctl;
        filep->f_op->open = my_open;
        filep->f_op->lock = my_lock;
        filep->f_op->mmap = my_mmap;
        filep->f_op->release = my_release;
       
        filp_close(filep, 0);
        return 0;
}

static int patch_init(void)
{
        if (patch_vfs(root_fs) != 0) return -1;
        printk("<1> VFS patched\n");
        return 0;
}

module_init(patch_init);

论坛徽章:
0
4 [报告]
发表于 2006-02-08 12:04 |只看该作者
你没有做任何READDIR操作,所以无read输出。

论坛徽章:
0
5 [报告]
发表于 2006-02-08 14:30 |只看该作者
我发现我表述不清楚,其实现在用ls命令,可以看到readdir有捕捉到。看到了有输出
Feb  7 17:50:24 xuan kernel:  open file /root/kernel
Feb  7 17:50:24 xuan kernel:  Read Dir /root/kernel/
Feb  7 17:50:24 xuan kernel:  Read Dir /root/kernel/
Feb  7 17:50:24 xuan kernel:  release file /root/kernel
但是文件的打开,读写就都没有能够捕捉到。 无论是read,write等都没有捕捉到,对文件的open,release也没有。
strace ls或者很多命令都看到用了 open read write的系统调用,就是没有捕捉到。我自己写的一个函数就是open两个文件,一个读一个写都没有捕捉到。
我看fs/read_write.c  里面sys_read函数是用了file->f_op->read的函数指针,应该会调用我替换了的my_read函数。不知何故,所以想请教各位。

[ 本帖最后由 viton_xuan 于 2006-2-8 14:33 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2006-02-08 15:22 |只看该作者
我猜想啊, 可能是因为你从“/”这个文件获得的指针, 而它碰巧是个目录。 不过这个自己也感觉解释不通, 我用file->f_dentry->d_inode->i_fop来截获的read、write、open等函数, 没问题。(我是用regular file做的)

论坛徽章:
0
7 [报告]
发表于 2006-02-08 17:18 |只看该作者

回复 1楼 viton_xuan 的帖子

我想,你的这种做法不具有通用性。也就是说,只有在操作你替换了调用以后的“那个文件”时,这个patch模块才起作用。

论坛徽章:
0
8 [报告]
发表于 2006-02-08 18:20 |只看该作者
原帖由 treul 于 2006-2-8 17:18 发表
我想,你的这种做法不具有通用性。也就是说,只有在操作你替换了调用以后的“那个文件”时,这个patch模块才起作用。


有通用性的。 你可以把函数指针指向的地址大印出来, 跟System.map或者/proc/kallsyms比对一下, 就看到那个地址代表一个通用的函数了。

论坛徽章:
0
9 [报告]
发表于 2006-02-09 02:40 |只看该作者
原帖由 viton_xuan 于 2006-2-8 09:29 发表
谢谢albcamus 斑竹的关注。
替换file_operations,打开一个文件(我打开的是/),得到该fs的file_operations指针,替换。
下面是代码。
int patch_vfs(const char* p)
{
        struct file* filep;
        filep = fil ...


你这样截获不了文件的读函数指针的. 上面的my_read函数替换的是目录操作函数ext3_dir_operations->generic_read_dir(), 如果你用的是ext3文件系统的话.

albcamus大哥说的"file->f_dentry->d_inode->i_fop来截获的read、write、open等函数"说的没错.

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
10 [报告]
发表于 2006-02-09 09:47 |只看该作者
借个地儿 问个问题.

这样在VFS层拦截. 和自己导出syscall_table 然后修改系统调用然后替换有什么区别??
后者应该包含前者吧?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP