Vista / Crash while calling FltIsDirectory

Hi.

I am developing a MiniFilter (AV/passive). OS is Vista x86. In PostCreate I
determine if the FileObj refers to a directory by calling “FltIsDirectory”.
Pretty straight forward… but in a very rare case the system bluescreens.

The crash happens reproducible while using “Windows System Image Manager”.

Bugcheck Analysis is below. I even dumped the FileObj via !fileobj and it
seems to be ok. Any idea what might be the problem?

Regards
Frank

kd> !analyze -v
*******************************************************************************
*
*
* Bugcheck Analysis
*
*
*
*******************************************************************************

NTFS_FILE_SYSTEM (24)
If you see NtfsExceptionFilter on the stack then the 2nd and 3rd
parameters are the exception record and context record. Do a .cxr
on the 3rd parameter and then kb to obtain a more informative stack
trace.
Arguments:
Arg1: 001904ab
Arg2: 941ee5d4
Arg3: 941ee2d0
Arg4: 860fae7b

Debugging Details:

EXCEPTION_RECORD: 941ee5d4 – (.exr ffffffff941ee5d4)
ExceptionAddress: 860fae7b (Ntfs!NtfsDecodeFileObject+0x00000039)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: 00000004
Attempt to read from address 00000004

CONTEXT: 941ee2d0 – (.cxr ffffffff941ee2d0)
eax=941ee6f4 ebx=00000000 ecx=00000000 edx=941ee6ec esi=941ee6e8
edi=00000005
eip=860fae7b esp=941ee69c ebp=941ee6a4 iopl=0 nv up ei pl nz na po
nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000
efl=00010202
Ntfs!NtfsDecodeFileObject+0x39:
860fae7b 8b5104 mov edx,dword ptr [ecx+4]
ds:0023:00000004=???
Resetting default scope

PROCESS_NAME: ImageCat.EXE

CURRENT_IRQL: 0

ERROR_CODE: (NTSTATUS) 0xc0000005 - Die Anweisung in “0x%08lx” verweist auf
Speicher in “0x%08lx”. Der Vorgang “%s” konnte nicht auf dem Speicher
durchgef hrt werden.

READ_ADDRESS: 00000004

BUGCHECK_STR: 0x24

DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE

LAST_CONTROL_TRANSFER: from 861719ed to 860fae7b

STACK_TEXT:
941ee6a4 861719ed 941ee794 83745278 941ee6e8 Ntfs!NtfsDecodeFileObject+0x39
941ee71c 86174f30 941ee794 8374a230 9498f5f5
Ntfs!NtfsCommonQueryInformation+0x56
941ee780 8617504b 941ee794 8374a230 00000001
Ntfs!NtfsFsdDispatchSwitch+0x175
941ee8ac 81867cc9 8451e220 8374a230 8374a230 Ntfs!NtfsFsdDispatchWait+0x1c
941ee8c4 86380b29 00000000 00000000 00000000 nt!IofCallDriver+0x63
941ee8f8 86382e83 8451e220 83745278 941ee920
fltmgr!FltpQueryInformationFile+0xc3
941ee940 8636ea1c 84529bb0 00000000 83745278
fltmgr!SetStreamListStandardInformationFlags+0x71
941ee97c 89743d78 8334b348 84e9e9e8 941ee9bf fltmgr!FltIsDirectory+0x8e
941ee9ac 8636912d 83745068 941ee9d0 00fbeb80
MiniIcpt!MiniIcptPostCreate+0xfe
[f:\projekte\monitor\kernel_driver\miniinterceptor\sys\miniinterceptor.cpp @
1728]
941eea10 8636bfa8 00745008 00000000 83745008
fltmgr!FltpPerformPostCallbacks+0x1f1
941eea24 8636c4de 83745008 83507540 941eea64
fltmgr!FltpProcessIoCompletion+0x10
941eea34 8636c8c9 8452d020 83507540 83745008
fltmgr!FltpPassThroughCompletion+0x94
941eea64 8637ea91 941eea84 00000000 00000000
fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x97
941eeab0 81867cc9 8452d020 84529bb0 837452d4 fltmgr!FltpCreate+0x2a1
941eeac8 819c8e57 941e50c0 832e2394 8425b988 nt!IofCallDriver+0x63
941eeb80 819dacdd 8425b9a0 00000000 832e22f0 nt!IopParseDevice+0xcff
941eec10 819cc94e 00000000 941eec68 00000040 nt!ObpLookupObjectName+0x615
941eec70 819f2198 049ede10 00000000 9fcc7f01 nt!ObOpenObjectByName+0x13c
941eece4 81a1879d 049ede74 80100080 049ede10 nt!IopCreateFile+0x5ec
941eed30 818461fa 049ede74 80100080 049ede10 nt!NtCreateFile+0x34
941eed30 771f0f34 049ede74 80100080 049ede10 nt!KiFastCallEntry+0x12a
WARNING: Frame IP not in any known module. Following frames may be wrong.
049ede6c 00000000 00000000 00000000 00000000 0x771f0f34

FOLLOWUP_IP:
Ntfs!NtfsDecodeFileObject+39
860fae7b 8b5104 mov edx,dword ptr [ecx+4]

SYMBOL_STACK_INDEX: 0

SYMBOL_NAME: Ntfs!NtfsDecodeFileObject+39

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: Ntfs

IMAGE_NAME: Ntfs.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 4549aceb

STACK_COMMAND: .cxr 0xffffffff941ee2d0 ; kb

FAILURE_BUCKET_ID: 0x24_Ntfs!NtfsDecodeFileObject+39

BUCKET_ID: 0x24_Ntfs!NtfsDecodeFileObject+39

kd> !fileobj 83745278

\Users\xxx\AppData\Local\Temp\IMGMGR_install_Windows Vista
ULTIMATE_ijp1mqxj.mtg\Windows\System32\SMI\Store\Machine\SCHEMA.DAT

Device Object: 0x8425b9a0 \Driver\volmgr
Vpb is NULL
Access: Read SharedRead SharedDelete

Flags: 0x28
No Intermediate Buffering
Sequential Only

FsContext: 0x85009518 FsContext2: 0x85009518
CurrentByteOffset: 0
Cache Data:
Section Object Pointers: 85009564
Shared Cache Map: 00000000

Ok, I guess the particular in this case is, that FileObj->Vpb is NULL. But
what does this mean?

“frank” schrieb im Newsbeitrag news:xxxxx@ntfsd…
> Hi.
>
> I am developing a MiniFilter (AV/passive). OS is Vista x86. In PostCreate
> I determine if the FileObj refers to a directory by calling
> “FltIsDirectory”. Pretty straight forward… but in a very rare case the
> system bluescreens.
>
> The crash happens reproducible while using “Windows System Image Manager”.
>
> Bugcheck Analysis is below. I even dumped the FileObj via !fileobj and it
> seems to be ok. Any idea what might be the problem?
>
> Regards
> Frank
>
> kd> !analyze -v
> ***
> *
> * Bugcheck Analysis
> *
>

>
> NTFS_FILE_SYSTEM (24)
> If you see NtfsExceptionFilter on the stack then the 2nd and 3rd
> parameters are the exception record and context record. Do a .cxr
> on the 3rd parameter and then kb to obtain a more informative stack
> trace.
> Arguments:
> Arg1: 001904ab
> Arg2: 941ee5d4
> Arg3: 941ee2d0
> Arg4: 860fae7b
>
> Debugging Details:
> ------------------
>
>
> EXCEPTION_RECORD: 941ee5d4 – (.exr ffffffff941ee5d4)
> ExceptionAddress: 860fae7b (Ntfs!NtfsDecodeFileObject+0x00000039)
> ExceptionCode: c0000005 (Access violation)
> ExceptionFlags: 00000000
> NumberParameters: 2
> Parameter[0]: 00000000
> Parameter[1]: 00000004
> Attempt to read from address 00000004
>
> CONTEXT: 941ee2d0 – (.cxr ffffffff941ee2d0)
> eax=941ee6f4 ebx=00000000 ecx=00000000 edx=941ee6ec esi=941ee6e8
> edi=00000005
> eip=860fae7b esp=941ee69c ebp=941ee6a4 iopl=0 nv up ei pl nz na po
> nc
> cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010202
> Ntfs!NtfsDecodeFileObject+0x39:
> 860fae7b 8b5104 mov edx,dword ptr [ecx+4]
> ds:0023:00000004=???
> Resetting default scope
>
> PROCESS_NAME: ImageCat.EXE
>
> CURRENT_IRQL: 0
>
> ERROR_CODE: (NTSTATUS) 0xc0000005 - Die Anweisung in “0x%08lx” verweist
> auf Speicher in “0x%08lx”. Der Vorgang “%s” konnte nicht auf dem Speicher
> durchgef hrt werden.
>
> READ_ADDRESS: 00000004
>
> BUGCHECK_STR: 0x24
>
> DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE
>
> LAST_CONTROL_TRANSFER: from 861719ed to 860fae7b
>
> STACK_TEXT:
> 941ee6a4 861719ed 941ee794 83745278 941ee6e8
> Ntfs!NtfsDecodeFileObject+0x39
> 941ee71c 86174f30 941ee794 8374a230 9498f5f5
> Ntfs!NtfsCommonQueryInformation+0x56
> 941ee780 8617504b 941ee794 8374a230 00000001
> Ntfs!NtfsFsdDispatchSwitch+0x175
> 941ee8ac 81867cc9 8451e220 8374a230 8374a230 Ntfs!NtfsFsdDispatchWait+0x1c
> 941ee8c4 86380b29 00000000 00000000 00000000 nt!IofCallDriver+0x63
> 941ee8f8 86382e83 8451e220 83745278 941ee920
> fltmgr!FltpQueryInformationFile+0xc3
> 941ee940 8636ea1c 84529bb0 00000000 83745278
> fltmgr!SetStreamListStandardInformationFlags+0x71
> 941ee97c 89743d78 8334b348 84e9e9e8 941ee9bf fltmgr!FltIsDirectory+0x8e
> 941ee9ac 8636912d 83745068 941ee9d0 00fbeb80
> MiniIcpt!MiniIcptPostCreate+0xfe
> [f:\projekte\monitor\kernel_driver\miniinterceptor\sys\miniinterceptor.cpp
> @ 1728]
> 941eea10 8636bfa8 00745008 00000000 83745008
> fltmgr!FltpPerformPostCallbacks+0x1f1
> 941eea24 8636c4de 83745008 83507540 941eea64
> fltmgr!FltpProcessIoCompletion+0x10
> 941eea34 8636c8c9 8452d020 83507540 83745008
> fltmgr!FltpPassThroughCompletion+0x94
> 941eea64 8637ea91 941eea84 00000000 00000000
> fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x97
> 941eeab0 81867cc9 8452d020 84529bb0 837452d4 fltmgr!FltpCreate+0x2a1
> 941eeac8 819c8e57 941e50c0 832e2394 8425b988 nt!IofCallDriver+0x63
> 941eeb80 819dacdd 8425b9a0 00000000 832e22f0 nt!IopParseDevice+0xcff
> 941eec10 819cc94e 00000000 941eec68 00000040 nt!ObpLookupObjectName+0x615
> 941eec70 819f2198 049ede10 00000000 9fcc7f01 nt!ObOpenObjectByName+0x13c
> 941eece4 81a1879d 049ede74 80100080 049ede10 nt!IopCreateFile+0x5ec
> 941eed30 818461fa 049ede74 80100080 049ede10 nt!NtCreateFile+0x34
> 941eed30 771f0f34 049ede74 80100080 049ede10 nt!KiFastCallEntry+0x12a
> WARNING: Frame IP not in any known module. Following frames may be wrong.
> 049ede6c 00000000 00000000 00000000 00000000 0x771f0f34
>
>
> FOLLOWUP_IP:
> Ntfs!NtfsDecodeFileObject+39
> 860fae7b 8b5104 mov edx,dword ptr [ecx+4]
>
> SYMBOL_STACK_INDEX: 0
>
> SYMBOL_NAME: Ntfs!NtfsDecodeFileObject+39
>
> FOLLOWUP_NAME: MachineOwner
>
> MODULE_NAME: Ntfs
>
> IMAGE_NAME: Ntfs.sys
>
> DEBUG_FLR_IMAGE_TIMESTAMP: 4549aceb
>
> STACK_COMMAND: .cxr 0xffffffff941ee2d0 ; kb
>
> FAILURE_BUCKET_ID: 0x24_Ntfs!NtfsDecodeFileObject+39
>
> BUCKET_ID: 0x24_Ntfs!NtfsDecodeFileObject+39
>
>
> kd> !fileobj 83745278
>
> \Users\xxx\AppData\Local\Temp\IMGMGR_install_Windows Vista
> ULTIMATE_ijp1mqxj.mtg\Windows\System32\SMI\Store\Machine\SCHEMA.DAT
>
> Device Object: 0x8425b9a0 \Driver\volmgr
> Vpb is NULL
> Access: Read SharedRead SharedDelete
>
> Flags: 0x28
> No Intermediate Buffering
> Sequential Only
>
> FsContext: 0x85009518 FsContext2: 0x85009518
> CurrentByteOffset: 0
> Cache Data:
> Section Object Pointers: 85009564
> Shared Cache Map: 00000000
>
>
>
>

Are you checking status of operation in Data->IoStatus.Status?

Yes, I do. The file/stream has been opened with status success.

“Jan Milan” schrieb im Newsbeitrag
news:xxxxx@ntfsd…
> Are you checking status of operation in Data->IoStatus.Status?
>
>
>
>
>

This is a bug in FltIsDirectory.

System Image Manager uses wimfltr.sys to overlay the contents of a wim on top of ntfs, and wimfltr takes ownership of any file objects in that overlay and uses its own format for the structures in the FsContext1 and FsContext2 fields.

The bug occurs when you call FltIsDirectory on a file that wimfltr.sys owns. Instead of sending the IRP for this function to all the filters in the device stack, filter manager sends the IRP directly down to NTFS. NTFS doesn’t know how to deal with wimfltr’s custom FsContext fields, and crashes.

Until a fix for this issue is available, you should avoid calling FltIsDirectory on file objects exposed by wimfltr. These files have NodeTypeCode == 0x1029 in their FSRTL_ADVANCED_FCB_HEADER.

An interesting issue that this raises is that if I don’t know who “owns”
the file object, I have no safe way of doing what you suggested as a
work-around. You stated:

“Until a fix for this issue is available, you should avoid calling
FltIsDirectory on file objects exposed by wimfltr. These files have
NodeTypeCode == 0x1029 in their FSRTL_ADVANCED_FCB_HEADER.”

But this assumes that the owner of that file object used an
FSRTL_ADVANCED_FCB_HEADER, which isn’t a requirement (and may not be
true.)

The approach *I* have taken in my own work is before doing this
validation I will carefully probe the address:

  • If the region with my magic number straddles a page boundary, I know
    it isn’t mine since my structures never do so (but I can’t say the same
    about some other file system drivers structures.)

  • If the address is not valid I don’t want to use it. But the official
    Microsoft position is that I should not use
    MmIsNonPagedSystemAddressValid (see Peter Weiland’s comment January 25,
    2007 in NTDEV saying “Any solution which requires probing around in
    memory you don’t own looking for magic numbers is just plain bad,
    regardless of whether it’s the ‘only way’ you can do it.”) If there’s
    no way to validate it, there’s no way for me to safely access it (since
    it might be a variant of my “index into a table” example above.) I
    ignore this restriction (which requires some work on the WDK because the
    function is marked as deprecated) and use it anyway.

  • THEN I look at the magic number.

I do know that if *I* don’t validate the file objects sent into my file
systems, my driver will die and unlike NTFS *I* will get the irate
customer call and the bug report saying “your driver crashed the system,
and see, ‘!analyze -v’ clearly confirms that fact.” If I use the
validation technique you described it will break (been there, done
that.) If I use a deprecated function I’m being ill-behaved. So, given
the current tools available and allowed it is not possible to validate a
file object. Thus, while you have offered up a pragmatic solution, it
makes assumptions that aren’t necessarily true.

So the approach I’ve taken is similarly pragmatic, but violates the
precepts of the OS as it is currently constructed. I don’t like doing
that, but there is no other way to achieve that other than assuming
“magic thinking” will keep the system from crashing.

Don’t get me wrong, I appreciate the suggested work-around, but I would
suggest that those using it need to be very cautious about probing
something (a file object’s FsContext pointer) that they do not own and
about which they know nothing. While the probing I propose above might
be a “bad idea” it’s still better than crashing the OS in my driver,
since no amount of argument ever convinces a user that the crash wasn’t
my fault when Microsoft says it is.

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

I haven’t expected to get an answer after all…so I tried my own workaround
which is kind of naive, I guess.

if (FltObjects->FileObject->Vpb == NULL &&
FltObjects->FileObject->DeviceObject->Vpb != NULL)
{
// don’t call FltIsDirectory in this case

}

I will try to implement as you suggested, instead.

Thanks very much.
Frank