File System Minifilter Drivers(文件系统微型过滤驱动)入门
问题:
公司之前有一套文件过滤驱动,但是在实施过程中经常出现问题,现在交由我维护。于是在边看代码的过程中,一边查看官方资料,进行整理。
这套文件过滤驱动的目的只要是根据应用层下发的策略来控制对某些特定文件的控制,例如根据后缀名来决定是否允许查看,是否允许查看指定目录啊之类的功能。
介绍:
MSDN上对可安装的文件系统驱动介绍http://msdn.microsoft.com/en-us/library/windows/hardware/ff548143(v=vs.85).aspx:其中树形结构菜单可以看出可安装的文件驱动类型种类:
文件系统驱动那说的应该就是最基本的驱动了,过滤驱动则是完全基于文件驱动中的操作进行手动过滤,可以理解成你hook了系统的create函数,然后如果你要拦截这个操作你就按要求返回不允许,否则就传给系统下一层去继续就好了。
而minifilter驱动则是通过向过滤管理器(Filter Manager)驱动进行注册自己需要过滤的一些操作,提供指定格式的回调函数让过滤管理器来进行调用即可。对于每一种操作,minifilter都可以注册一个“过滤前”和“过滤后”被调用的回调函数。(有点类似于Linux内核上probe调试技术)。(preCreate和postCreate用来作为后面“过滤前”和“过滤后”被调用的回调函数的例子)。
要注意minifilter的加载顺序是根据一个Altitude来决定的,可以理解成驱动所处的维度。例如,当FilterManager检测到要执行create的时候,就去调用注册了对该操作进行过滤的minifilter的回调函数,根据Altitude的值从大到小的顺序先调用preCreate函数。而FilterManager检测到create执行完成后,便按照Altitude的值从小到大的顺序去调用postCreate函数。
minifilter是基于FilterManager所提供的类似插件一样的模块,它可以调用FilterManager所提供很多功能:http://msdn.microsoft.com/en-us/library/windows/hardware/ff541613(v=vs.85).aspx
加载和卸载:
FilterLoad和FilterUnload可用于在用户态程序控制minifilter驱动的加载和卸载。
这里要注意的是minifilter还存在一个instance的概念,这个instance应该就是指某个特定的minifilter,比如有三个minifilter A、B、C。就代表三个minifilter,每一个instance有特定的名字、altitude和flags。当在instance里面调用FltStartFiltering的时候就会去通知FilterManager去将这个insance关联到磁盘以及相关的I/0操作过滤表上。如果在FLtStartFiltering返回之前,FilterManager检测新挂上的磁盘的话,就会自动通知这个instance(通过调用回调函数InstanceSetupCallBack),所以minifilter注册时提供的Instance开头的回调函数,主要是用于FilterManager对这个驱动的一些反馈操作。(比如关联磁盘啊、取消关联啊之类的)。
此外,minifilter自己主动去卸载的话,当然是调用FltUnregisterFilter函数了。
资料:
英语能力确实不太好,在看后面的I/O操作的介绍的时候看的实在费解。幸好有搜到中文资料:http://blog.csdn.net/jununfly/article/category/517002。还是挺感慨很多高深底层的东西都只有英文资料。我就不多做口舌甚至好有可能误导了。
WDK示例:在WDK开发包示例中的IFSK Samples类别下。源码目录是src/filesys/minifilter。中文介绍:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=24504987&id=208208
可能根据我的需求,比较拥有的应该是以上三个例子了,其中swapBuffers那个,用来做加解密比较适合参考。
记录:
记录下我自己遇到的问题:
1、想要做个最简单的测试,通过vs来直接调试,于是简单的仅仅过滤IRP_MJ_CREATE操作,并且在Pre函数里得到操作的文件名,然后输出。而对于FLT_REGISTRATION结构体中,其他可选的回调函数全部置NULL。效果是根本不会进入到的我的pre函数中,原因是我压根没有attach我的驱动的instance到相关卷标上。(这里可以增进对instance这概念的理解,也就是说必须在相关卷标上attach了对应的instance才会生效)。所以如果在系统启动通过fltmc load命令或者FilterLoad和FltLoadFilter来手动加载驱动的,需要手动去关联minifilter到本地磁盘上。可以用fltmc attach命令、FilterAttach、FltAttachVolume、FilterAttachAtAltitude、FltAttachVolumeAtAltitude来手动加载。
2、原来的过滤驱动代码中,是在InstanceSetup中根据需要关联的卷来获取磁盘信息等,保存到Instance的上下文中。如果开启了磁盘控制,还要对USB类型的磁盘设备名称进行记录。话说这里为什么不在磁盘驱动里面记录呢??
3、原来的代码里创建上下文的地方,既调用了FltAllocateContext也调用了FltSet***Context函数的,如果都成功的话,需要调用两次FltReleaseContext,而实际只调用了一次。
上下文(context):
流上下文(stream context):为文件流所设置的上下文,需要和打开了的文件对象关联,所以不能在pre-create回调函数中直接关联,但是可以在pre-create中创建,然后通过pre-create的最后一个参数传递到post-create中进行调用FltSetStreamContext进行关联。
Pre回调函数(PFLT_PRE_OPERATION_CALLBACK)
FLT_PREOP_COMPLETE:表示当前的过滤驱动完成了本次I/O操作,过滤管理器就不再往下发送本次I/O请求,而是依次向上调用post回调函数。这种情况下IoStatus.Status的值就是最终I/O操作的执行结果(不能是STATUS_PENDING)。
FLT_PREOP_SUCCESS_NO_CALLBACK/FLT_PREOP_SUCCESS_WITH_CALLBACK:这个返回值表示处理成功,让过滤管理器去做自己的事,区别在于WITH_CALLBACK的返回值会标明需要回调post函数。而NO_CALLBACK的则标明不需要。
FLT_PREOP_PENDING:顾名思义,表明当前过滤驱动将本次I/O操作挂起了,过滤管理器需要等待当前驱动调用FltCompletePendedPreOperation函数后才会继续本次I/0操作处理流程。注意只有对于基于IRP中断的I/O操作(用FLT_IS_IRP_OPERATION宏测试)才可以挂起。
FLT_PREOP_DISALLOW_FASTIO:只有操作是fast I/O操作(用FLT_IS_FASTIO_OPERATION(Data)进行测试)时才可以返回这个值,表明过滤驱动不允许fast I/O操作继续执行。因此过滤管理器不会再下发该请求,而是依次向上调用post回调函数。这种情况下不需要设置IoStatus.Status的值,过滤管理器会自动设置这个值。
FLT_PREOP_SYNCHRONIZE:这个返回值表明处理未完成,保持当前过滤驱动上下文线程环境,交由过滤管理器继续下发后调用post回调函数后继续处理。也只对基于IRP中断的操作有效,并且必须有post函数,如果不是基于IRP中断的,就会和FLT_PREOP_SUCCESS_WITH_CALLBACK一样。注意:对于Create操作,不应该返回这个值,因为文件管理器已经为这个操作进行同步了。此外对于同步的读和写操作,如果返回这个值会严重影响驱动和系统性能。
如果在pre和post函数中更改了Data的内容,必须调用FltSetCallbackDataDirty函数(更改IoStatus除外)。
Post回调函数(PFLT_POST_OPERATION_CALLBACK)
这个回调函数执行的中断等级为IRQL <= DISPATCH_LEVEL。所以需要注意以下几点:1、不能安全调用必须低于IRQL级别的任何内核模式的派遣函数。2、在这个函数内开辟的任何数据结构必须位于非页内存。3、该函数不可分页。4、不能请求资源(resource)、信号量(mutextes)和快速信号量(fast mutexes),只能获取互斥锁(spin lock)。5、不能获取、设置或者删除上下文,但可以释放上下文。
相对于Pre回调函数多了最后一个参数Flags,这个参数如果存在FLTFL_POST_OPERATION_DRAINING标记位,则表明当前过滤驱动实例正在被取消关联,本次调用是为了清理pre回调函数传入的completion context,返回值必须是FLT_POSTOP_FINISHED_PROCESSING,并且这个回调是在IRQL<=APC_LEVEL执行的。
FLT_POSTOP_FINISHED_PROCESSING:表明本过滤驱动完成了对I/0操作的处理并将控制交还给过滤管理器。
FLT_POSTOP_MORE_PROCESSING_REQUIRED:只有当微过滤驱动将本次I/O操作发送到工作队列中时,才能返回这个值,微过滤驱动最后必须负责完成这个I/O操作。过滤管理器会继续等待FltCompletePendedPostOperation函数被调用后才继续执行控制。注意:这个返回值也必须对基于IRP中断的操作执行。
任何要被执行在IRQL<DISPATCH_LEVEL的I/O完成处理都不能在这个回调函数内直接执行。取而代之,可以使用FltDoCompletionRpocessingWhenSafe或者FltQueueDeferredIoWorkItem之类的函数发送到工作队列中。
除了以下情况外,要确保在Flags参数没有FLTFL_POST_OPERATION_DRAINING标记位的时候才能调用FltDoCompletionRpocessingWhenSafe函数:
1、如果微过滤驱动的pre回调函数为一个基于IRP中断的操作返回FLT_PREOP_SYNCHRONIZE,那么对应的post回调要保证和pre回调都处在IRQL<=APC_LEVEL的线程上下文中。
2、对于create操作的post回调要保证中断级别为IRQL_PASSIVE_LEVEL(原始IRP_MJ_CREATE操作所处的线程上下文)。
Buffer传输方式
注意IRP_MJ_READ和IRP_MJ_WRITE可以是基于IRP或fast I/O的操作.当它们基于IRP时,buffering方法由以上描述的设备对象标记决定.当它们是fast I/O,它们总是使用neither I/O.更多关于可以是基于IRP或fast I/O的操作的I/O操作的信息,参考可以是IRP-I/O或Fast I/O的操作.
总结:
很遗憾直接写上了总结,事实上上面的内容已经是半个多月前写的了,一方面是有其他事情,一方面发现有点滥竽充数的感觉,没有内容可写,写出来也比较肤浅。在调试的过程中不断出现问题,不断的更改,很多东西改好了也未必能解释出来。
主要原因还是对windows的文件系统本身就不怎么了解,在这个前提下去做过滤操作,就难上加难了。
File System Minifilter Drivers(文件系统微型过滤驱动)入门的更多相关文章
- 基于Minifilter框架的文件过滤驱动理解
概述 Minifilter即File System Minifilter Drivers,是Windows为了简化第三方开发人员开发文件过滤驱动而提供的一套框架,这个框架依赖于一个称之为Filter ...
- File System 之本地文件系统
上一篇文章提到了,最近做一个基于 File System/IndexedDB的应用,上一篇是定额和使用的查询. 因为LocalFileSystem只有chrome支持,有点尴尬,如果按需加载又何来尴尬 ...
- [LeetCode] Design In-Memory File System 设计内存文件系统
Design an in-memory file system to simulate the following functions: ls: Given a path in string form ...
- chattr lsattr linux file system attributes - linux 文件系统扩展属性
我们使用 linux 文件系统扩展属性,能够对linux文件系统进行进一步保护:从而给文件 赋予一些额外的限制:在有些情况下,能够对我们的系统提供保护: chattr命令用来改变文件属性.这项指令可改 ...
- GFS(Google File System,谷歌文件系统)----(1)文件系统简介
分布式文件系统 系统是构建在普通的.廉价的机器上,因此故障是常态而不是意外 系统希望存储的是大量的大型文件(单个文件size很大) 系统支持两种类型读操作:大量的顺序读取以及小规模的随机读取(larg ...
- GFS(Google File System,谷歌文件系统)----(1)读写一致性
GFS副本控制协议--中心化副本控制协议 对于副本集的更新操作有一个中心节点来协调管理,将分布式的并发操作转化为单点的并发操作,从而保证副本集内各节点的一致性.在GFS中,中心节点称之为Primary ...
- HDFS(Hadoop Distributed File System )
HDFS(Hadoop Distributed File System ) HDFS(Hadoop Distributed File System )Hadoop分布式文件系统.是根据google发表 ...
- Fast File System
不扯淡了,直接来写吧,一天一共要写三篇博客,还有两篇呢. 1. 这篇博客讲什么? Fast File System(FFS)快速文件系统,基本思想已经在在上一篇博客File System Implem ...
- File System Implementation 文件系统设计实现
先来扯淡吧,上一篇文章说到要补习的第二篇文章介绍文件系统的,现在就来写吧.其实这些技术都已经是很久以前的了,但是不管怎么样,是基础,慢慢来学习吧.有种直接上Spark源码的冲动.. 1. 这篇博客具体 ...
随机推荐
- instanceof 和 构造函数
1. intanceof 运算符 instanceof 运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例. instanceof左边是实例对象 右边是构造函数.它的运算实质是检查右边构建函数 ...
- noip 2012 疫情控制
/* 考试的时候没想出正解 也没打暴力 时间不够了 随便yy了几种情况按出现的先后顺序处理而没有贪心 的了20分 不粘了 正解是围绕首都的儿子来搞的 显然先二分答案 对于每个限定的最大时间 我们尝试着 ...
- HTML简要内容
1. html基础 html是用来制作网页的标记语言,不需编译,直接由浏览器执行.大小写不敏感,推荐使用小写.html文件必须使用html或htm为文件名后缀. html主体结构: (1)DTD头: ...
- Jquery~$when_done_then的用法
对于$.ajax请求来说,如果层级比较多,程序看起来会比较乱,而为了解决这种问题,才有了$when...done...fail...then的封装,它将$.ajax这嵌套结构转成了顺序平行的结果,向下 ...
- Android中Application全局方法(变量)的调用
Application和Actovotu,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息.通常我们是 ...
- 关于Linux下面msyql安装后并未设置初始密码,但是登录报错“Access denied for user 'root'@'localhost' (using password: NO)”的解决方案
如上图:首先我安装mysql的时候并没有设置密码,但是就是登不进去,百度了一下,解决方案如下: 解决方案地址:http://zhidao.baidu.com/link?url=7QvuOKtfRdMT ...
- JS 改变input 输入框样式
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- 自定义android精美聊天界面
编写精美聊天界面,那就肯定要有收到的消息和发送的消息. 首先还是编写主界面,修改activity_chat.xml中的代码,如下所示: <?xml version="1.0" ...
- linux File Handling commands 'ls'.
ref:Linux / Unix Command: ls NAME ls - list directory contents SYNOPSIS ls [OPTION]... [FILE]... DES ...
- 从Select语句看Oracle查询原理(了解Oracle的查询机制)
第一步:客户端把语句发给服务器端执行 当我们在客户端执行select语句时,客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle客户端是不会做任何的操作,他的主 ...