阅读:2426回复:15
可怕的IFS重入问题,分页。用户被禁言,该主题自动屏蔽! |
|
最新喜欢:cyliu |
沙发#
发布于:2002-12-02 10:30
问题出在\"用ring0I/O打开另一个文件\",这时你又会收到FS_OpenFile,然后\"用ring0I/O打开另一个文件\",然后。。。。 这样会出现死循环。
处理的办法大概有两个:1。不用ZwCreateFile打开文件而是直接构造IRP往下层传 2。用特别的方法识别FS_OpenFile是由自己的ZwCreateFile产生的,比如传给ZwCreateFile的文件名加入特殊的标志(当然在处理FS_OpenFile时还得改回正常文件名) |
|
|
板凳#
发布于:2002-12-02 13:09
这个问题当初也一样困扰了我两三个月,我把我的心得写出来和大家共享一下,希望能有用(有用的话别忘了给分:)
先说说sijun提到的两种方法: 1. 直接构造IRP,只适用于2000/XP,这个方法我一直没有成功:( 2. 在CreateFile时加入特殊标志。 通常是在文件名后面跟特殊标记,例如($:MYFILE),缺点是文件名过长时会引起不必要的麻烦,而且该方法会导致和很多防毒软件冲突。另外修改OPENFILE的标志位,比较简单,但是也不可靠(如果大家的驱动都用这个标志...) 3. 创建自己的用户线程或者系统线程来CreateFile,在OpenFile中判断是否是自己的线程(ID)在打开文件,如果是的话,当然直接PASS (强烈推荐) 4. 在收到FS_OpenFile时,记下当前线程ID,然后打开文件,当第二个FS_OpenFile重入时,发现该线程已被记录,就PASS(简单易行) 方法3、4也不是完美的方法,实际使用时发现也会和某个特定的软件冲突。 在2000下还得考虑CACHE的问题,不能随便PASS有危险的Create 另外在Xp下,微软终于加入了针对FileObject的Context字段,可以有限解决Read/Write可能引起的死锁以及其它经常做Filter碰到的问题,可惜2000和98都没有这个功能。 |
|
地板#
发布于:2002-12-02 13:16
另外你指的paging是swapperfile吗?如果是的话,在OpenFile里判断有没有R0_SWAPPER_CALL标志,有的话,千万要PASS哦!
|
|
地下室#
发布于:2002-12-02 14:32
用户被禁言,该主题自动屏蔽! |
|
5楼#
发布于:2002-12-02 17:58
怎么会得出这个结论的:
>> IFS在同步调用时是不可重入的 >> 所以,如果我在FS_OpenFile的时候不管通过任何方法都无法调用到IFS提供的ring0 Service了. IFS明显可以重入,而且FS_OpenFile里调用ring0完全可以啊,另外你挂住FS_OpenFile,等用户层处理?有什么理由非得这样做吗? |
|
6楼#
发布于:2002-12-02 19:12
用户被禁言,该主题自动屏蔽! |
|
7楼#
发布于:2002-12-02 21:44
用户被禁言,该主题自动屏蔽! |
|
8楼#
发布于:2002-12-03 12:17
...弄了半天怎么又回来了...前面不是很详细地给你回答了吗。
|
|
9楼#
发布于:2002-12-03 12:48
用户被禁言,该主题自动屏蔽! |
|
10楼#
发布于:2002-12-03 13:29
>> 1.直接构造是可能的.使用未公开的ifsreq,104h大小.Stan Michelle也确实做到了,但正如他自己说的那样,在取的入口点上好像是很存在问题的.我不准备这样做,太麻烦了.
直接构造是最不推荐的方法 >> 2.改文件名,这没用.要改回去,不是一个ppath的问题. 可以的,我试过 >> 3.使用线程ID.可问题是,ioreq中使用的pid,并不是线程ID.我并不肯定这种做法,如果可以这恐怕是个好方法了. Get_Cur_Thread_Handle 不就可以了啊,在自己的线程中先调用一下,然后在FS_OpenFile里也调用,比较一下就可以了,Norton Anti-Virus就是这样做的 >> 4.记录线程ID的方法是不行的.实际上,你可以看到打开操作在有的时候会接连打开两次到三次(原因是什么,我也不知道).这样,我想你不能说下面一个打开操作就是你发出的吧. 我的很多Driver都是这样做的,冲突的软件最少,也最简单(记住,同一个线程怎么可能会同时有两次操作?你能在一个线程里同时处理两件事吗?所以第二次以后就必然是重入的,PASS就行啦,当然这个重入也可能是其它的Filter重入,但是没有关系的,他们有自己的处理) 同时记得FS_OpenFile处理结束时,这个线程就不要再跟踪了。 >> 实际上,我试了使用未使用的标志位的方法,是可以的.但正如你说的,我怕会有冲突. 还在研究中. 在ME下改标志位问题最多,所以非常不推荐 >> 另,关于第三种方法,能否说明详细点?谢谢. 创建自己的系统线程,挂着等待事件。FS_OpenFile时,激活事件,把需要的参数传递给系统线程,等待系统线程处理完毕。同时FS_OpenFile入口如果发现当前线程是自己的系统线程,就PASS。 >> BTW,已经给了大大你分啊!!!呵呵 谢啦:) |
|
11楼#
发布于:2002-12-03 14:39
用户被禁言,该主题自动屏蔽! |
|
12楼#
发布于:2002-12-03 16:56
4的方法我也常用。
但假设,如果某人写了一个非常烂的程序,先发了一个ReadFile,driver返回pending,而这个程序又不WaitForSingleObject,直接就发了另外一个ReadFile,这时候启不是一个线程发了2个ioreq? 不过,实际测试中没有碰到过,但愿这种程序不要出现才好啊! :D |
|
|
13楼#
发布于:2002-12-04 09:50
driver既然返回pending,这个线程就取消记录了,所以没有问题的。异步的ReadFile如果没有完成再次调用ReadFile本身就会出问题,就算没有Filter存在,98下也常会死机。
|
|
14楼#
发布于:2002-12-08 12:45
4的方法我也常用。 虽说人家这种程序很烂了?应该是很高级才对嘛。 异步IO还是很有用的嘛。 服务器软件应该用得很多。 |
|
15楼#
发布于:2003-01-08 18:16
我也遇到了该死的同样的问题,谢谢你们的讨论,让我茅塞顿开,实在太感谢了!
|
|
|