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操作所处的线程上下文)。

时间: 2024-10-11 01:52:27

File System Minifilter Drivers(文件系统微型过滤驱动)的相关文章

【整理学习HDFS】Hadoop Distributed File System 一个分布式文件系统

Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时,它和其他的分布式文件系统的区别也是很明显的.HDFS是一个高度容错性的系统,适合部署在廉价的机器上.HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用.HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的.HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的.HDFS是Apac

[LeetCode] Design In-Memory File System 设计内存文件系统

Design an in-memory file system to simulate the following functions: ls: Given a path in string format. If it is a file path, return a list that only contains this file's name. If it is a directory path, return the list of file and directory names in

HDFS(Hadoop Distributed File System )

HDFS(Hadoop Distributed File System ) HDFS(Hadoop Distributed File System )Hadoop分布式文件系统.是根据google发表的论文翻版的.论文为GFS(Google File System)Google 文件系统(中文,英文). 1. 架构分析 基础名词解释: Block: 在HDFS中,每个文件都是采用的分块的方式存储,每个block放在不同的datanode上,每个block的标识是一个三元组(block id, n

Resource is out of sync with the file system

在sts中,启动run on server时或查看项目文件时报错: Resource is out of sync with the file system: .... 这是文件系统不同步的问题,是因为在eclipse或mycelipse之外对工程中的resource进行修改引起的(或者是由不同的系统间对文件进行修改引起的):但是,有时没有在eclipse或mycelipse之外进行修改,也会报类似的错误. 解决办法:需要手动刷新一下资源管理器. (1)在eclipse或mycelipse中,工

Fast File System

不扯淡了,直接来写吧,一天一共要写三篇博客,还有两篇呢. 1. 这篇博客讲什么? Fast File System(FFS)快速文件系统,基本思想已经在在上一篇博客File System Implementation 里面说明了,FFS是对VSFS的一种优化改进使其可以被实际使用. 2. FFS基于VSFS的改进思想是什么? 这个呢,VSFS在存储文件的时候,根本没有考虑磁盘的寻址时间,把磁盘当做了一种随机存储介质!事实上由于局域性原理的存在,依据局域性而对存储做相应改进是非常有助于性能提升的.

linux nfs Read-only file system

[email protected]/4 # touch 1 touch: cannot touch `1': Read-only file system mount没有权限? [email protected]/0 # mount /dev/sda2 on / type ext4 (rw) proc on /proc type proc (rw) sysfs on /sys type sysfs (rw) devpts on /dev/pts type devpts (rw,gid=5,mode

一个简单的文件系统过滤驱动框架

很多人认为文件系统过滤驱动很复杂,其实也有一定道理,因为需要有很多细节需要考虑到,这是一个简单的文件系统过滤驱动,抛去了大部分细节,留下了一个简单的框架,其实这样文件系统过滤驱动就变得蛮简单的,很多接口可以不用实现,只要知道大致流程,其它都将会很清晰. #define DBG 1 #include <ntifs.h> #include "fsfilter.h" PDEVICE_OBJECT g_Cdo; PDRIVER_OBJECT g_MyDriver; NTSTATUS

操作系统原理(三)——文件系统(File system)

文件系统(File system) 1. 文件 首先要说文件的定义,文件是进程创建的信息逻辑单元. 由于磁带和光盘的性能较低,磁盘使用的较多.这里讨论文件储存在磁盘中的情况.磁盘可被认为是固定块儿大小的线性序列. 在操作系统看来,文件就是一个个字节流,操作系统不管这个文件的内容(不管它是.mp3音频文件,或者.jpg图片文件,在应用程序看来才有这种区分).文件在操作系统眼中只有3种:普通文件.目录文件.特殊文件. 文件的命名: 在Linux中,文件名大小写敏感:目录分隔符“/”绝对不能出现在文件

Linux文件系统只读Read-only file system

问题描述: 1.系统无法进行磁盘的读写操作(touch,cp,chmod)等等 2.服务器无法启动(也是因为无法创建文件) 3.只有涉及到系统磁盘的写操作,都会报错"Read-only file system" 问题原因: 1.系统没有正常关机,导致虚拟磁盘出现文件系统错误: 2.机器硬盘故障导致硬盘只读 一般情况是由于系统发现磁盘硬件(Riad卡,硬盘)故障或文件系统中文件被损坏后而采取的保护机制导致的.为了保护数据不破坏分区中已有内容,Linux在挂载文件系统是就只用read-on