Thursday, December 15, 2011

Debugging Minifilters: Using !fltkd.filter

Ever since I started this blog I had planned to go over all the fields that the !fltkd extension can show for the various FltMgr structures and talk about each of them. I'm going to start this with the !fltkd.filter command. Most commands take additional flags that control which information is shown. For this post I'll just focus on the default output without any flags and I'll cover the flags in a different post.

Before I begin I'd like to mention that the !fltkd command in general is heavily dependent on the public symbols for fltmgr.sys and so it doesn't work at all without the right symbols. Moreover, the extension itself and the symbols as well have some bugs and in some cases it can't display things correctly because some of the structures that it expects are not in the public symbols at all or at least they are not under the name the extension expects to find them. So you will occasionally see output from the debugger saying something along the lines of "Your debugger is not using the correct symbols … Type referenced: " followed by a type name. I've removed them from the output in the blog post and we'll work with what we have. Please note that if you want to follow along it's best to use a Win7 machine since the symbols were most complete in that release (though still not 100% fixed).

1: kd> !fltkd.filters

Filter List: 92cddd1c "Frame 0" 
   FLT_FILTER: 94144008 "luafv" "135000"
      FLT_INSTANCE: 94146008 "luafv" "135000"
   FLT_FILTER: 92cdda58 "FileInfo" "45000"
      FLT_INSTANCE: 930e7730 "FileInfo" "45000"
      FLT_INSTANCE: 93448dc8 "FileInfo" "45000"
      FLT_INSTANCE: 9357c340 "FileInfo" "45000"
      FLT_INSTANCE: 93584560 "FileInfo" "45000"
      FLT_INSTANCE: 9359a948 "FileInfo" "45000"
1: kd> !fltkd.filter 94144008 

FLT_FILTER: 94144008 "luafv" "135000"
   FLT_OBJECT: 94144008  [02000000] Filter
      RundownRef               : 0x00000008 (4)
      PointerCount             : 0x00000001 
      PrimaryLink              : [92cdda64-92cddd1c] 
   Frame                    : 92cddcc0 "Frame 0" 
   Flags                    : [00000006] FilteringInitiated NameProvider
   DriverObject             : 941427a8 
   FilterLink               : [92cdda64-92cddd1c] 
   PreVolumeMount           : 81f980cc  luafv!LuafvPreRedirect 
   PostVolumeMount          : 00000000  (null) 
   FilterUnload             : 00000000  (null) 
   InstanceSetup            : 81fa462b  luafv!LuafvInstanceSetup 
   InstanceQueryTeardown    : 00000000  (null) 
   InstanceTeardownStart    : 00000000  (null) 
   InstanceTeardownComplete : 00000000  (null) 
   ActiveOpens              : (941440dc)  mCount=1 
   Communication Port List  : (94144108)  mCount=0 
   Client Port List         : (94144134)  mCount=0 
   VerifierExtension        : 00000000 
   Operations               : 94144164 
   OldDriverUnload          : 00000000  (null) 
   SupportedContexts        : (941440a0)
      VolumeContexts           : (941440a0)
      InstanceContexts         : (941440a0)
      FileContexts             : (941440a0)
      StreamContexts           : (941440a0)
      StreamHandleContexts     : (941440a0)
      TransactionContext       : (941440a0)
   InstanceList             : (94144038)
      FLT_INSTANCE: 94146008 "luafv" "135000"

I'll just go over each field and discuss its meaning.
  • FLT_OBJECT: 94144008 [02000000] Filter - some of the main FltMgr objects (instance, volume and filter) begin with a standard structure that identifies the object type and contains some common synchronization primitives. You can see the structure by doing a "dt fltmgr!_FLT_OBJECT". The FLT_OBJECT is the first member of the structure and as such the address of the FLT_OBJECT is the same as the address of the bigger structure, which is the FLT_FILTER in our case.
  • RundownRef : 0x00000008 (4) - this is a rundown reference primitive that I've mentioned in my post here. The actual reference count is the value in parentheses. This value is incremented and decremented whenever someone calls FltObjectReference() and, respectively, FltObjectDereference(). This allows the filter to wait for other components to release their reference before tearing down (since the rundown reference will enter a special state that doesn't allow more references to be taken once the teardown process starts; this is different from a regular reference count where it's possible that the refcount never drops to 0)..
  • PointerCount : 0x00000001 - this is the actual reference count that controls when the memory is freed. There is no direct way filters can influence this (like FltReferenceObject), but I've seen communication ports increment this count.
  • PrimaryLink : [92cdda64-92cddd1c] - this is a link into a list of filters for the frame. Please remember that a filter is not aware of anything outside the frame and so the list of filters is a per-frame concept.
  • Frame : 92cddcc0 "Frame 0" - this is obviously a pointer to the frame the filter belongs to.
  • Flags : [00000006] FilteringInitiated NameProvider - obviously these are flags. Possible values include (as a general trick it's pretty easy to generate this list by changing the value of the flags in the structure and asking !fltkd.filter to display the filter again):
    • UnloadInProgress - the minifilter is unloading
    • FilteringInitiated - the minifilter has started filtering by calling FltStartFiltering().
    • NameProvider - the minifilter is a name provider. I think FltMgr sets this flag based on whether the minifilter registers the name provider callbacks.
  • DriverObject : 941427a8 - obviously the DRIVER_OBJECT for the filter.
  • FilterLink : [92cdda64-92cddd1c] - this is the same list as the PrimaryLink member of the FLT_OBJECT structure above.
  • PreVolumeMount : 81f980cc luafv!LuafvPreRedirect - this is actually the preOp callback for the IRP_MJ_MOUNT_VOLUME operation (that I've mentioned in my post How File System Filters Attach to Volumes - Part II). This looks like a strange place to have an operation callback but it makes sense because when this callback is called there is no instance associated with the volume (since the volume isn't mounted yet) and so the pointer couldn't have been called through the usual instance mechanism.
  • PostVolumeMount : 00000000 (null) - this is the postOp callback for the IRP_MJ_MOUNT_VOLUME operation.
  • FilterUnload : 00000000 (null) - this is the Unload callback (the FLT_REGISTRATION->FilterUnloadCallback member).
  • InstanceSetup : 81fa462b luafv!LuafvInstanceSetup - this is the FLT_REGISTRATION->InstanceSetupCallback member.
  • InstanceQueryTeardown : 00000000 (null) - this is the FLT_REGISTRATION->InstanceQueryTeardownCallback member.
  • InstanceTeardownStart : 00000000 (null) - this is the FLT_REGISTRATION->InstanceTeardownStartCallback member.
  • InstanceTeardownComplete : 00000000 (null) - this is the FLT_REGISTRATION->InstanceTeardownCompleteCallback member.
  • ActiveOpens : (941440dc) mCount=1 - the value in parentheses is a pointer to an internal FltMgr structure that is simply a doubly linked list protected by a mutex (you can see in the debugger by doing a dt fltmgr!_FLT_MUTEX_LIST_HEAD). For more information on this field please check out my post on Tracking a minifilter's ActiveOpens files.
  • Communication Port List : (94144108) mCount=0 - this is a list of opened communication ports for this filter (the same FLT_MUTEX_LIST_HEAD structure as mentioned above).
  • Client Port List : (94144134) mCount=0 - this is a list of connected communication ports.
  • VerifierExtension : 00000000 - this is the a structure that is used when DriverVerifier is enabled for this minifilter. I will go into more detail on this structure in a future post.
  • Operations : 94144164 - as mentioned in my post Debugging Minifilters: Finding the Callbacks this is actually a pointer to the _FLT_OPERATION_REGISTRATION structure that the filter used when it registered with FltMgr.
  • OldDriverUnload : 00000000 (null) - this is the routine that the driver registered as an unload routine. When a driver registers as a minifilter FltMgr needs to know when the driver is being unloaded (because it is possible to unload a minifilter like any other driver) and so FltMgr replaces the _DRIVER_OBJECT->DriverUnload member function with its own function so that it can detect that someone is trying to unload the driver and so that FltMgr can start the teardown process. Well, the original DriverUnload function is stored in the FLT_FILTER structure in this member.
  • SupportedContexts : (941440a0) - this is an array of information related to the context registration. I will discuss this in more depth in a future post.
  • InstanceList : (94144038) - this is a pointer to another FltMgr internal structure, the fltmgr!_FLT_RESOURCE_LIST_HEAD, which is a list protected by an ERESOURCE (as opposed to the fltmgr!_FLT_MUTEX_LIST_HEAD which was protected by a mutex). The entries in this list are the instances.

That's it for now. Next week I plan to discuss some of the !fltkd.filter flags and their output.

No comments:

Post a Comment