首页
社区
课程
招聘
[求助]磁盘过滤驱动如何防止重入
发表于: 2013-4-28 22:01 13175

[求助]磁盘过滤驱动如何防止重入

2013-4-28 22:01
13175
磁盘过滤驱动,如果截取IRP_MJ_READ,IRP_MJ_WRITE,并且在自己的IRP_MJ_READ(WRITE)中间要使用ZwReadFile(ZwWriteFile)操作,这个时候,ZwReadFile(ZwWriteFile)显然又会产生IRP_MJ_READ,IRP_MJ_WRITE,这就造成了重入,如何避免这种重入呢?
注意,不是文件系统过滤驱动,也不是磁盘卷过滤驱动,而是磁盘过滤驱动。
文件系统过滤驱动可以用shadow device,但是磁盘过滤驱动好象无法用shadow device啊,因为无法命名一个磁盘设备的shadow device啊。而虚拟的shadow device上层肯定没有附着NTFS文件系统,所以无法用ZwCreate打开具体的shadow device的文件名啊。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (24)
雪    币: 49
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
可能你对shadow device的理解有点偏差
磁盘过滤也可以shadow device的。
不过避免重入的话  还可以考虑自己建立读写IRP发送到指定的设备 这样也可以避免重入 不过不知道符合不符合你的场景
如果不行的话 还是考虑自己建立磁盘过滤shadow device
2013-4-30 13:53
0
雪    币: 220
活跃值: (117)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
用MInifilter
有flt函数 防止重入的
2013-4-30 18:17
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
我虽然目前并没有写出实际的shadow device代码,但我的理解就是一个虚拟设备可以转发IRP。比如文件过滤驱动虚拟一个类似的文件shadow device,具有另一个设备名,打开文件就打开虚拟设备名加文件名就可以了。但是磁盘过滤驱动的shadow device是一个磁盘驱动,并没有NTFS文件系统,我如果读写磁盘的某个扇区,可以发irp给shadow device,但是我是要读写文件的,这个shadow device并没有文件系统,更没有文件夹文件名,比如我要打开“C:/A.BIN”,在文件系统过滤驱动的shadow device下可以打开“shadow/a.bin”,而在磁盘过滤驱动下,这个替换的文件名是不成立的。正是因为我要借用NTFS文件系统进行文件操做,所以疑问这个shadow device能否实现,如果不是文件操作而是读写磁盘某个扇区的数据,自然可以向下层disk.sys发送irp就可以了,而我要进行文件操做,难道还要我解析NTFS结构把对文件的操做转化为某个扇区的读写吗?
2013-4-30 22:10
0
雪    币: 49
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
直接创建IRP也能防止重入
在文件层与磁盘两过滤层配合 决定哪些文件的读写发送到磁盘设备的影子设备 也能防止重入
或者在文件过滤层直接使用MINI 也能防止文件层的重入
方法各种 视乎你的需求场景
2013-4-30 22:41
0
雪    币: 14
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
用一个变量,初始值为零,自己读写的时候置为一,过滤的时候加个判断。。。。。。菜鸟思维,,勿笑
2013-5-1 03:57
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
磁盘影子设备是一个虚设备,系统不会识别也不会在这个虚设备上建立文件系统。文件层的影子设备也要通过系统文件系统转发irp,而系统的文件系统转发irp是有系统生成直接发给真是磁盘的,是系统生成是不可控制转给磁盘影子设备的,而文件影子设备不可能直接将文件irp转成磁盘扇区读写irp再转给磁盘影子设备啊。
2013-5-1 08:23
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这样做好象不行啊。自己读写的时候,置一,但是,紧接着进入自己这个IRP_MJ_READ的区域的irp可能不止一个,也许有很多个,因为系统是并发运行的,有可能有别的irp同时产生,所以你仍然不能根据变量置为一了,就判断是自己发出来的irp,在对变量置一以后,完全可能是其他线程发出若干irp,然后再接着一个才是自己发出的重入的irp,所以还是无法判断。
2013-5-1 19:07
0
雪    币: 14
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
其实我最先想到的是psgetcurrentprocess       但是想了一会之后  菊花一紧  因为你是通过驱动来读写的  psgetcurrentprocess返回的应该总是system进程    所以才想了个折中的用变量的办法    psgetcurrentprocess可以不考虑多线程的同步     用变量的办法  多线程的确有问题    但是如果不在意效率   你可以用自旋锁啊 互斥体啊等等做线程同步来解决  只不过 如果你很在意效率  这样肯定不行了
2013-5-1 23:17
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
10
6楼的思路可以改进一下,把这个标志想办法放在Irp内就可以了。。。
2013-5-1 23:27
0
雪    币: 3116
活跃值: (1269)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
11
问题是中间文件系统给下层发请求的时候,好像会重新申请IRP

其实可以有办法能搞出多一个影子文件系统设备的,但有可能它和正宗的文件设备缓存不同步,这个比较杯具。
2013-5-1 23:37
0
雪    币: 49
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
影子设备是另一个过滤层 他提供给上层的数据 还是你真实磁盘的扇区以及其他信息。
只是取决于IRP是从影子设备路线下发到下层 还是从另一个过滤设备下发到下层
这样就避开了重入问题
2013-5-2 09:59
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
是啊,现在是按你说的,有2个影子设备,一个文件影子,一个磁盘影子,现在的问题是,我需要打开文件,
那么,使用真实文件设备打开,真实文件传递irp是传递到真实磁盘的,我无法控制真实文件设备传递irp到我的磁盘影子吧?
如果使用文件影子设备打开我要读写的文件,那么文件影子设备如果传递这个irp到真实文件设备,那最后真实文件设备又会传递irp到真实磁盘设备吧?还是无法传递irp到磁盘影子设备。
如果使用文件影子设备打开文件,然后传递irp到我的磁盘影子设备,这就需要我自己在文件影子设备这一层,把所有的文件操作转换成对磁盘影子设备的扇区读写,你想想,文件读写转换为扇区读写,这是一个庞大的ntfs的工作,我自己不可能去转换的。
2013-5-2 10:08
0
雪    币: 49
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
那么,使用真实文件设备打开,真实文件传递irp是传递到真实磁盘的,我无法控制真实文件设备传递irp到我的磁盘影子吧?
加了文件过滤为什么不能呢?

你13楼说的内容应该不是问题 影子设备也可以使用文件系统 NTFS能做得事情我们不必插手。
我觉得自己构造IRP
磁盘层影子设备
或者磁盘层影子设备加文件过滤
是应该能够满足防止重入的
2013-5-2 10:16
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
Irp的结构是固定的,每个字节有固定含义,有些字节是系统填写的,自己无法改变每个字节的含义。
唯一自己能写入的数据就是缓冲区里面的数据,而缓冲区里面的数据,自己可以添加一些标志变量,但是,不能保证,有某个用户缓冲区的数据正好和标志变量巧合怎么办?
2013-5-2 10:31
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
你是说,磁盘影子设备也形成一个“影子磁盘”,比如真实磁盘是disk0,影子磁盘是“disk1”,那么系统自动识别有2个磁盘,比如disk0有C,D,E,3个分区,那现在就变成有disk0的C,D,E,然后disk1也有F,G,H,实际就是C,D,E的相同影子,那么,资源管理器里面有C,D,E,F,G,H,6个盘符了吗?这是我不愿看到的,我只要有C,D,E三个盘符,不能多出F,G,H三个磁盘来。而且,这样多出F,G,H三个磁盘,任何用户程序都可以直接操作F,G,H磁盘就是操作真实磁盘,那不就绕过我的磁盘过滤驱动了,那我的磁盘过滤还有什么意义。
2013-5-2 10:37
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
其实我也看到过其他文章介绍说,建立一个线程,所有irp都放入这个线程,然后返回Pending,然后在线程中间检验,如果当前irp的线程就是自己这个线程,那么可以判断此irp是重入irp,否则就是其他线程的irp是需要进行过滤处理的。但是这种方式,是一种异步处理方式,我就是想探讨一下是否有同步处理方式。
2013-5-2 10:52
0
雪    币: 4817
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
LZ试过FILE_NO_INTERMEDIATE_BUFFERING没有?我没有试过,但FILE_NO_INTERMEDIATE_BUFFERING直接往下发,不过CACHE,会不会跟ZwWriteFile同一线程的呢?
我不了解,仅仅提供思路而已。
2013-5-2 10:53
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
是啊,如果没有这个参数,使用的是缓存空间,暂时不会产生磁盘读写irp,而当真正需要读写磁盘的时候,是由缓存管理器来发出irp,而缓存管理器的线程ID会不会又和过滤驱动自身产生的线程ID不同啊?如果是这样,那么判断重入就更麻烦了。
2013-5-2 11:05
0
雪    币: 4817
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
CACHE的线程ID不定,他自身有线程,可能会Write,具体策略我不了解。还有就你Write的时候,FS写CACHE,这时CACHE可能会Write,还有其他情况,比如其他进程操作CACHE导致CACHE空间不足,也可能Write。

你的情况我了解,我一般是把文件(按需求的最大大小)先创建出来,然后获取文件在磁盘中的布局(占用了哪些扇区),然后直接放过这些扇区的,这样就不过管重入的问题了。
2013-5-2 11:18
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
是啊,这是个好办法,但是这样就让别的程序直接读写这个相同的文件也不用经过过滤了。不过,可以在打开文件的时候设置独占打开,这样就禁止其他程序使用这个文件了。这个方法不错。
2013-5-2 11:25
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
但是这样,对于这个文件的属性修改,因为是涉及到$MFT文件的磁盘读写,那这样就对$MFT文件也进行了过滤,这样就无法修改这个文件的属性了,只能读写这个文件的内容部分。而且似乎这个文件在$bitmap文件中的位图文件也无法修改啊。总之这样只能放过对文件内容数据的读写,没有放过对文件相关属性和其他信息的读写。
2013-5-2 11:38
0
雪    币: 4817
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
还属性呢,大小都没法随便就变的,简单而稳定的做法,可能就要牺牲灵活性,如果你想把灵活性提高了,那可能就复杂了,很多时候不能十全十美的,就要看你的取舍了
2013-5-2 11:46
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
如果要完美的话,我想只能自己在过滤驱动里面写一个ntfs的文件系统了,自己把对文件的读写转化为扇区读写。呵呵,只是假设一下。而且这样做,还是不能得到系统NTFS文件系统的认可,难免系统ntfs对这样的单独磁盘操作会产生冲突。还是不完美。
2013-5-2 11:48
0
雪    币: 49
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
我觉得解决重入的工作量 比起 自己写个NTFS文件系统的工作量 还是小的多。 1:100吧
2013-5-26 13:59
0
游客
登录 | 注册 方可回帖
返回
//