Crash in FsRtlIsPagingFile

I am getting a crash when seding IRP to a disk object. It only happens when system memory is low and the action to trigger the crash is to open task manage->Resource Monitor. The device object is an PCI-E SSD device that has its own driver. Can someone tell me what is FsRtlIsPagingFile trying to check. The IRP is built by my driver so it is supposed to have nothing to do with paging request.

Probably caused by : fileinfo.sys ( fileinfo!FIPreReadWriteCallback+eb )

Followup: MachineOwner

7: kd> !analyze -v
****************************************************************************
***
*

*
* Bugcheck
Analysis *
*

*
****************************************************************************
***

SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e) This is a very common bugcheck.
Usually the exception address pinpoints the driver/function that caused the
problem. Always note this address as well as the link date of the
driver/image that contains this address.
Arguments:
Arg1: ffffffffc0000005, The exception code that was not handled
Arg2: fffff80002109a00, The address that the exception occurred at
Arg3: fffff88011fa5658, Exception Record Address
Arg4: fffff88011fa4eb0, Context Record Address

Debugging Details:

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx
referenced memory at 0x%08lx. The memory could not be %s.

FAULTING_IP:
nt!FsRtlIsPagingFile+0
fffff800`02109a00 488b5118 mov rdx,qword ptr [rcx+18h]

EXCEPTION_RECORD: fffff88011fa5658 – (.exr 0xfffff88011fa5658)
ExceptionAddress: fffff80002109a00 (nt!FsRtlIsPagingFile)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000000018
Attempt to read from address 0000000000000018

CONTEXT: fffff88011fa4eb0 – (.cxr 0xfffff88011fa4eb0)
rax=fffff8000221c170 rbx=0000000000000000 rcx=0000000000000000
rdx=fffff88011fa59c8 rsi=fffffa80f37eddb0 rdi=0000000000000000
rip=fffff80002109a00 rsp=fffff88011fa5898 rbp=fffff88011fa59a0
r8=fffff88011fa59a0 r9=0000000000000000 r10=fffffa806d883010
r11=fffff88011fa5948 r12=0000000000000000 r13=0000000000000001
r14=fffffa804030dab0 r15=fffff88011fa5af0
iopl=0 nv up ei pl zr na po nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b
efl=00010246
nt!FsRtlIsPagingFile:
fffff80002109a00 488b5118 mov rdx,qword ptr [rcx+18h] ds:002b:0000000000000018=???
Resetting default scope

PROCESS_NAME: System

CURRENT_IRQL: 0

ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced
memory at 0x%08lx. The memory could not be %s.

READ_ADDRESS: 0000000000000018

BUGCHECK_STR: 0x7E

DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE

LAST_CONTROL_TRANSFER: from fffff8800d9d8163 to fffff80002109a00

STACK_TEXT:
fffff88011fa5898 fffff8800d9d8163 : fffffa800000a000 00001f8000490220 0000000000000001 fffffa803f2543c8 : nt!FsRtlIsPagingFile
fffff88011fa58a0 fffff8800154b067 : fffffa80f37ede50 0000000000000000 00000000000000eb fffff88004f9d390 :
fileinfo!FIPreReadWriteCallback+0xeb
fffff88011fa5950 fffff8800154c329 : fffff88011fa5a00 fffffa806d883204 fffffa804051b000 fffff8000201a801 :
fltmgr!FltpPerformPreCallbacks+0x2f7
fffff88011fa5a50 fffff8800154a6c7 : fffffa806d883010 fffffa8010896700 fffffa804051b040 fffff88001c07e60 :
fltmgr!FltpPassThrough+0x2d9
fffff88011fa5ad0 fffff88001c08123 : 0000000000000000 fffff88002ce6618 0000000000000000 0000000000000000 :
fltmgr!FltpDispatch+0xb7
fffff88011fa5b30 fffff88001c08484 : fffffa806d883010 fffff88002ce6618 fffff88002ce6660 fffff88001cc5860 :
MyDriver!commit_request+0x233 [f:\autobuild\windev\windows\osio_win.c @ 1379]
fffff88011fa5bb0 fffff88001c0884d : fffff88002ce6618 fffff8000208474f
fffff88002cc65e0 fffff88001c168f7 :
MyDriver!commit_request_range+0x34
[f:\autobuild\windev\windows\osio_win.c @ 1780]
fffff88011fa5c20 fffff88001c0899a : 0000000000000000 0000000000020000 0000000000000008 0000000000000000 :
MyDriver!chunk_requests+0x1a1 [f:\autobuild\windev\windows\osio_win.c @ 1919]
fffff88011fa5c70 fffff88001c08a04 : 0000000000000000 0000000000000000 fffff88002dd2100 0000000000000000 :
MyDriver!process_h+0x10e [f:\autobuild\windev\windows\osio_win.c @ 2018]
fffff88011fa5ca0 fffff88001c08aa5 : fffffa802b7f31d0 0000000000000080 fffff88001c08a70 0072006f00660000 :
MyDriver!process_consolidation_queues+0x48
[f:\autobuild\windev\windows\osio_win.c @ 2030]
fffff88011fa5cd0 fffff88001c06133 : fffffa802b7f31d0 ffffffffffff8ad0 fffff88001c08a70 0000000000000000 :
MyDriver!consolidation_thread+0x35
[f:\autobuild\windev\windows\osio_win.c @ 2048]
fffff88011fa5d10 fffff80002317fee : fffffa805e9a0b60 fffffa800ca74040 726ab04c72638e58 7263fef401b00c8c :
MyDriver!DriverThread+0x43 [f:\autobuild\windev\windows\osisr_win.c @ 1058]
fffff88011fa5d40 fffff8000206e5e6 : fffff800021f2e80 fffffa805e9a0b60 fffff80002200cc0 0061004d00200064 :
nt!PspSystemThreadStartup+0x5a
fffff88011fa5d80 0000000000000000 : fffff88011fa6000 fffff88011fa0000 fffff88011fa5a20 0000000000000000 :
nt!KxStartSystemThread+0x16

FOLLOWUP_IP:
fileinfo!FIPreReadWriteCallback+eb
fffff880`0d9d8163 413bc4 cmp eax,r12d

SYMBOL_STACK_INDEX: 1

SYMBOL_NAME: fileinfo!FIPreReadWriteCallback+eb

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: fileinfo

IMAGE_NAME: fileinfo.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 4a5bc481

STACK_COMMAND: .cxr 0xfffff88011fa4eb0 ; kb

FAILURE_BUCKET_ID: X64_0x7E_fileinfo!FIPreReadWriteCallback+eb

BUCKET_ID: X64_0x7E_fileinfo!FIPreReadWriteCallback+eb

Followup: MachineOwner

It’s attempting to dereference the fscontext in the fileobject (offset 0x18) but the fileobject in this case is NULL.

This is interesting, the Irp is built with IoBuildAsynchronousFsdRequest, and the device object is a disk opened with ZwOpenFile and its device name ??\pcie#diskfusionio_iodrive_320gb__0001#124204#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}. So there should be no file object gets involved. And the same driver works fine for all other devices. And even for this device, it only happen when trying to open resource monitor. Maybe I can set the fileobject manually to fool around the underlying driver?

If I don’t use ZwOpenFile, instead get the device pointe by attaching to it as a filter. This works fine. Is there any other way to open a devcie other than ZwOpenFile, or any parameters that tell Windows that it is not a file, but a disk device?

On 3/8/2013 10:12 AM, ren.j@263.net wrote:

If I don’t use ZwOpenFile, instead get the device pointe by attaching to it as a filter. This works fine. Is there any other way to open a devcie other than ZwOpenFile, or any parameters that tell Windows that it is not a file, but a disk device?

Correct me if I am wrong, but aren’t you the one who is deciding to send
the IRP down which is resulting in the crash? Could you possibly just
NOT send that particular IRP when you have a file object that references
something other than a regular file?

It is block level cache basically, so the IRP I send to cache device is a newly built IRP and has nothing to do with the original IRP. For example, the original IRP may be a write to LBA 100 but the IRP I send to cache device is to LBA 0. So file system is supposed to not be in the picture.

On 3/8/2013 10:38 AM, ren.j@263.net wrote:

It is block level cache basically, so the IRP I send to cache device is a newly built IRP and has nothing to do with the original IRP. For example, the original IRP may be a write to LBA 100 but the IRP I send to cache device is to LBA 0. So file system is supposed to not be in the picture.

Where is fileinfo!FIPreReadWriteCallback getting the null file object
pointer from that it is passing to nt!FsRtlIsPagingFile, your IRP?

>

Where is fileinfo!FIPreReadWriteCallback getting the null file object
pointer from that it is passing to nt!FsRtlIsPagingFile, your IRP?

Looks like it is FLT_CALLBACK_DATA::FileObject, if that is of any help.

Piss poor programming on MS’s part not to test for the null pointer
before calling FsRtlIsPagingFile. On w2k3 and earlier you can get away
with that because FsRtlIsPagingFile merely does a bitwise comparison of
the pointer value with the file object pointers in the nt!MmPagingFile
array. Since Windows Vista FsRtlIsPagingFile actually tries to
dereference the file object pointer.

“George M. Garner Jr.” wrote in message news:xxxxx@ntdev…

Piss poor programming on MS’s part not to test for the null pointer before
calling FsRtlIsPagingFile.

FsRtlIsPagingFile is annotated as taking a non-optional file object pointer
as a parameter:

LOGICAL FsRtlIsPagingFile(
In PFILE_OBJECT FileObject
);

Thus, if you call it with a NULL pointer that’s your problem. The real bug
in this case is calling the file system with an IRP that doesn’t have a file
object in it. I suspect that even without FileInfo this would have
eventually crashed when the IRP hit the file system.

-scott
OSR

“George M. Garner Jr.” wrote in message news:xxxxx@ntdev…

Where is fileinfo!FIPreReadWriteCallback getting the null file object
pointer from that it is passing to nt!FsRtlIsPagingFile, your IRP?

Looks like it is FLT_CALLBACK_DATA::FileObject, if that is of any help.

Piss poor programming on MS’s part not to test for the null pointer
before calling FsRtlIsPagingFile. On w2k3 and earlier you can get away
with that because FsRtlIsPagingFile merely does a bitwise comparison of
the pointer value with the file object pointers in the nt!MmPagingFile
array. Since Windows Vista FsRtlIsPagingFile actually tries to
dereference the file object pointer.

On 3/8/2013 3:45 PM, Scott Noone wrote:

FsRtlIsPagingFile is annotated as taking a non-optional file object
pointer as a parameter

Yes, and that is why fileinfo!FIPreReadWriteCallback should have tested
the file object pointer before calling FsRtlIsPagingFile with a null
pointer.

The real bug in this case is calling the file system with
> an IRP that doesn’t have a file object in it. <

Maybe that is the ultimate problem. But according to the OP’s original
description the crash “only happens when system memory is low…” If
the OP is sending an IRP down that requires a file object I would expect
it to crash every time, not just under low resource situations.
However, perhaps the OP can clarify what he is doing.

I managed to reproduce it even when the memory is not low. So the only necessary and sufficient cause is to open resource manager. I write a piece of test code so my driver can sends write IRP even there is no incoming IO. So now it is has nothing to do with anything else above. And it still crash as well. How can I fill out the file object field of the IRP I build? Sometimes the stack is a little different, but is still at FsRtlIsPagingFile. The input of FltIsCallbackDataDirty seems to be the IRP I sent down. But after that, I have no idea where did the file object come from.

fffff88006976e58 fffff80001bb5d92 nt!DbgBreakPointWithStatus
fffff88006976e60 fffff80001bb6b7e nt!HeadlessDispatch+0x192
fffff88006976ec0 fffff80001ace744 nt!KeEnterKernelDebugger+0x76e
fffff88006977590 fffff80001e392b4 nt!KeBugCheckEx+0x104
fffff880069775d0 fffff80001df8679 nt!RtlGetNextRange+0x334
fffff88006977610 fffff80001afa4ec nt!MmGetSystemRoutineAddress+0x54f5
fffff88006977640 fffff80001af9f6d nt!_C_specific_handler+0x8c
fffff880069776b0 fffff80001af8d45 nt!RtlUnwindEx+0x99d
fffff880069776e0 fffff80001b09dc1 nt!FsRtlDissectName+0x6a5
fffff88006977dc0 fffff80001acdcc2 nt!IoGetPagingIoPriority+0x901
fffff88006978460 fffff80001acc83a nt!KeSynchronizeExecution+0x3e32
fffff88006978640 fffff80001b57c90 nt!KeSynchronizeExecution+0x29aa
fffff880069787d8 fffff88007245163 nt!FsRtlIsPagingFile
fffff880069787e0 fffff8800137c067 fileinfo+0x1163
fffff88006978890 fffff8800137d329 fltmgr!FltAcquirePushLockShared+0x907
fffff88006978990 fffff8800137b6c7 fltmgr!FltIsCallbackDataDirty+0xa39
fffff88006978a10 fffff88001c568dc fltmgr+0x16c7
fffff88006978a70 fffff88001c573eb MyDriver!commit_request+0x29c [f:\phastdata\v2.0windows\windows\osio_win.c @ 1373]

“George M. Garner Jr.” wrote in message news:xxxxx@ntdev…

Yes, and that is why fileinfo!FIPreReadWriteCallback should have tested the
file object pointer before calling FsRtlIsPagingFile with a null pointer.

I’ve never seen any driver in the FS stack check for a NULL file object
pointer in the I/O path. For example, see the FASTFAT source in read.c at
the top of its read dispatch entry point (FatFsdRead):

//
// We are first going to do a quick check for paging file IO. Since this
// is a fast path, we must replicate the check for the fsdo.
//

if (!FatDeviceIsFatFsdo( IoGetCurrentIrpStackLocation(Irp)->DeviceObject))
{

Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext);

I’m not saying that checks for NULL are a bad thing in general, but in this
case there is an implicit contract at the FS level that there will be file
object in the IRP. Otherwise the FS has no idea what file you’re talking
about.

-scott
OSR

“George M. Garner Jr.” wrote in message news:xxxxx@ntdev…

On 3/8/2013 3:45 PM, Scott Noone wrote:

FsRtlIsPagingFile is annotated as taking a non-optional file object
pointer as a parameter

Yes, and that is why fileinfo!FIPreReadWriteCallback should have tested
the file object pointer before calling FsRtlIsPagingFile with a null
pointer.

The real bug in this case is calling the file system with
an IRP that doesn’t have a file object in it. <

Maybe that is the ultimate problem. But according to the OP’s original
description the crash “only happens when system memory is low…” If
the OP is sending an IRP down that requires a file object I would expect
it to crash every time, not just under low resource situations.
However, perhaps the OP can clarify what he is doing.

>How can I fill out the file object field of the IRP I build?

How did you get the device object that you’re sending the request to in the
first place? You must have had to open it, at which point you would have
received a file object.

-scott
OSR

wrote in message news:xxxxx@ntdev…

I managed to reproduce it even when the memory is not low. So the only
necessary and sufficient cause is to open resource manager. I write a piece
of test code so my driver can sends write IRP even there is no incoming IO.
So now it is has nothing to do with anything else above. And it still crash
as well. How can I fill out the file object field of the IRP I build?
Sometimes the stack is a little different, but is still at
FsRtlIsPagingFile. The input of FltIsCallbackDataDirty seems to be the IRP I
sent down. But after that, I have no idea where did the file object come
from.

fffff88006976e58 fffff80001bb5d92 nt!DbgBreakPointWithStatus
fffff88006976e60 fffff80001bb6b7e nt!HeadlessDispatch+0x192
fffff88006976ec0 fffff80001ace744 nt!KeEnterKernelDebugger+0x76e
fffff88006977590 fffff80001e392b4 nt!KeBugCheckEx+0x104
fffff880069775d0 fffff80001df8679 nt!RtlGetNextRange+0x334
fffff88006977610 fffff80001afa4ec nt!MmGetSystemRoutineAddress+0x54f5
fffff88006977640 fffff80001af9f6d nt!_C_specific_handler+0x8c
fffff880069776b0 fffff80001af8d45 nt!RtlUnwindEx+0x99d
fffff880069776e0 fffff80001b09dc1 nt!FsRtlDissectName+0x6a5
fffff88006977dc0 fffff80001acdcc2 nt!IoGetPagingIoPriority+0x901
fffff88006978460 fffff80001acc83a nt!KeSynchronizeExecution+0x3e32
fffff88006978640 fffff80001b57c90 nt!KeSynchronizeExecution+0x29aa
fffff880069787d8 fffff88007245163 nt!FsRtlIsPagingFile
fffff880069787e0 fffff8800137c067 fileinfo+0x1163
fffff88006978890 fffff8800137d329 fltmgr!FltAcquirePushLockShared+0x907
fffff88006978990 fffff8800137b6c7 fltmgr!FltIsCallbackDataDirty+0xa39
fffff88006978a10 fffff88001c568dc fltmgr+0x16c7
fffff88006978a70 fffff88001c573eb MyDriver!commit_request+0x29c
[f:\phastdata\v2.0windows\windows\osio_win.c @ 1373]

>How did you get the device object that you’re sending the request to in the

first place? You must have had to open it, at which point you would have
received a file object.
ZwOpenFile returns a handle, it is passed to ObReferenceObjectByHandle to get file object, and then get device object using IoGetRelatedDeviceObject. The point is normally we don’t need this file object when calling IoBuildAsynchronousFsdRequest. Which field should I fill out. IRP->Overlay.OriginalFileObject ? I tried to set it manually and it didn’t work.

RetStatus = ZwOpenFile( &VolHandle,
STANDARD_RIGHTS_ALL,
&ObjectAttrs,
&IoStatus,
0,
FILE_NON_DIRECTORY_FILE );

if (RetStatus == STATUS_SUCCESS)
{
RetStatus = ObReferenceObjectByHandle( VolHandle,
THREAD_ALL_ACCESS,
*IoFileObjectType,
KernelMode,
(PVOID)&FileObject,
NULL );

if ( RetStatus == STATUS_SUCCESS ) {
pDevObject = IoGetRelatedDeviceObject( FileObject );
MY_TRACE( LOG_DEBUG,“%ws IoGet FObj %p DevObj %p\n”, ObjectName.Buffer, FileObject, pDevObject );
ObReferenceObject( ( PVOID )pDevObject );
ZwClose( VolHandle );
}
else
{
MY_TRACE( LOG_ERROR, “Couldn’t reference device %ws RetStatus=0x%x”, ObjectName.Buffer, RetStatus );
ZwClose( VolHandle );
}
}

What is the major function code that you are sending down, IRP_MJ_WRITE?
It seems like that is documented as taking a file object pointer in
the current IRP stack location.
http://msdn.microsoft.com/en-us/library/windows/hardware/ff549427(v=vs.85).aspx.
Maybe also need a file pointer in
pIrp->Tail.Overlay.OriginalFileObject but I don’t see that documented.
No clue as to why your code doesn’t blow up every time.

>No clue as to why your code doesn’t blow up every time.
The code only has problem with one specific vendor’s SSD card. And I think they have some caching stuff also in their driver that is why they check whether the IRP is page IO.

On 3/8/2013 5:01 PM, ren.j@263.net wrote:

I tried to set it manually and it didn’t work.

Don’t forget to increment the reference count on the file object when
you set it into the IRP.

The following code works, anybody knows why? Microsoft has never mentioned this file object needs to be set after calling IoBuildAsynchronousFsdRequest.

irpStack = IoGetNextIrpStackLocation(bio);
irpStack->FileObject = SavedFileObj;

On 3/9/2013 9:09 AM, ren.j@263.net wrote:

The following code works, anybody knows why? Microsoft has never mentioned this file object needs to be set after calling IoBuildAsynchronousFsdRequest.

irpStack = IoGetNextIrpStackLocation(bio);
irpStack->FileObject = SavedFileObj;

http://msdn.microsoft.com/en-us/library/windows/hardware/ff549427(v=vs.85).aspx.

Look midway down in the page:

"IrpSp->FileObject

A pointer to the file object that is associated with DeviceObject.
If the FO_SYNCHRONOUS_IO flag is set in IrpSp->FileObject->Flags, the
file object was opened for synchronous I/O.

The IrpSp->FileObject parameter contains a pointer to the
RelatedFileObject field, which is also a FILE_OBJECT structure. The
RelatedFileObject field of the FILE_OBJECT structure is not valid during
the processing of IRP_MJ_WRITE and should not be used."

> I’ve never seen any driver in the FS stack check for a NULL file object

pointer in the I/O path. For example, see the FASTFAT source in read.c at
the top of its read dispatch entry point (FatFsdRead):

Correct, and also IoIsOperationSynchronous will crash if the FO pointer in the IRP is NULL.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com